app.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import asyncio
  2. import os
  3. from operator import itemgetter
  4. from random import randint, sample
  5. from typing import Any
  6. import uvloop
  7. from asyncpg import create_pool
  8. from jinja2 import Template
  9. from starlite import MediaType, Starlite, get
  10. asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
  11. connection_pool: Any = None
  12. async def init_connection_pool() -> None:
  13. global connection_pool
  14. connection_pool = await create_pool(
  15. user=os.getenv('PGUSER', 'benchmarkdbuser'),
  16. password=os.getenv('PGPASS', 'benchmarkdbpass'),
  17. database='hello_world',
  18. host='tfb-database',
  19. port=5432
  20. )
  21. def normalize_queries(value: str | None) -> int:
  22. queries = int(value) if value and value.isnumeric() else 1
  23. if queries > 500:
  24. return 500
  25. if queries < 1:
  26. return 1
  27. return queries
  28. def load_fortunes_template() -> "Template":
  29. path = os.path.join('templates', 'fortune.html')
  30. with open(path, 'r') as template_file:
  31. template_text = template_file.read()
  32. return Template(template_text)
  33. fortune_template = load_fortunes_template()
  34. @get(path='/json')
  35. def json_serialization() -> dict[str, str]:
  36. return {'message': 'Hello, world!'}
  37. @get(path='/db')
  38. async def single_database_query() -> dict[str, int]:
  39. row_id = randint(1, 10000)
  40. async with connection_pool.acquire() as connection:
  41. number = await connection.fetchval(
  42. 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1',
  43. row_id
  44. )
  45. return {'id': row_id, 'randomNumber': number}
  46. @get(path='/queries')
  47. async def multiple_database_queries(queries: None | str = None) -> list[dict[str, int]]:
  48. row_ids = sample(range(1, 10000), normalize_queries(queries))
  49. worlds = []
  50. async with connection_pool.acquire() as connection:
  51. statement = await connection.prepare('SELECT "randomnumber", "id" FROM "world" WHERE id = $1')
  52. for row_id in row_ids:
  53. number = await statement.fetchval(row_id)
  54. worlds.append({'id': row_id, 'randomNumber': number})
  55. return worlds
  56. @get(path='/fortunes', media_type=MediaType.HTML)
  57. async def render_fortunes_template() -> str:
  58. async with connection_pool.acquire() as connection:
  59. fortunes = await connection.fetch('SELECT * FROM Fortune')
  60. fortunes.append([0, 'Additional fortune added at request time.'])
  61. fortunes.sort(key=itemgetter(1))
  62. return fortune_template.render(fortunes=fortunes)
  63. @get(path='/updates')
  64. async def database_updates(queries: None | str = None) -> list[dict[str, int]]:
  65. num_queries = normalize_queries(queries)
  66. updates = list(zip(sorted(sample(range(1, 10000 + 1), num_queries)), sample(range(1, 10000), num_queries)))
  67. worlds = [
  68. {"id": row_id, "randomNumber": number} for row_id, number in updates
  69. ]
  70. async with connection_pool.acquire() as connection:
  71. statement = await connection.prepare('SELECT "id", "randomnumber" FROM "world" WHERE id = $1')
  72. for row_id, _ in updates:
  73. await statement.fetchval(row_id)
  74. await connection.executemany('UPDATE "world" SET "randomnumber"=$1 WHERE id=$2', updates)
  75. return worlds
  76. @get(path='/plaintext', media_type=MediaType.TEXT)
  77. def plaintext() -> bytes:
  78. return b'Hello, world!'
  79. app = Starlite(
  80. route_handlers=[
  81. database_updates,
  82. json_serialization,
  83. multiple_database_queries,
  84. plaintext,
  85. render_fortunes_template,
  86. single_database_query,
  87. ],
  88. on_startup=[init_connection_pool],
  89. openapi_config=None,
  90. )