app.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import asyncio
  2. import asyncpg
  3. import os
  4. import jinja2
  5. from logging import getLogger
  6. from apidaora import appdaora, html, route, text
  7. from random import randint
  8. from operator import itemgetter
  9. from typing import TypedDict, Optional
  10. logger = getLogger(__name__)
  11. READ_ROW_SQL = 'SELECT "randomnumber", "id" FROM "world" WHERE id = $1'
  12. READ_ROW_SQL_TO_UPDATE = 'SELECT "id", "randomnumber" FROM "world" WHERE id = $1'
  13. WRITE_ROW_SQL = 'UPDATE "world" SET "randomnumber"=$1 WHERE id=$2'
  14. ADDITIONAL_ROW = [0, 'Additional fortune added at request time.']
  15. async def setup_database():
  16. global connection_pool
  17. connection_pool = await asyncpg.create_pool(
  18. user=os.getenv('PGUSER', 'benchmarkdbuser'),
  19. password=os.getenv('PGPASS', 'benchmarkdbpass'),
  20. database='hello_world',
  21. host='tfb-database',
  22. port=5432
  23. )
  24. def load_fortunes_template():
  25. path = os.path.join('templates', 'fortune.html')
  26. with open(path, 'r') as template_file:
  27. template_text = template_file.read()
  28. return jinja2.Template(template_text)
  29. def get_num_queries(queries):
  30. try:
  31. query_count = int(queries)
  32. except (ValueError, TypeError):
  33. return 1
  34. if query_count < 1:
  35. return 1
  36. if query_count > 500:
  37. return 500
  38. return query_count
  39. connection_pool = None
  40. sort_fortunes_key = itemgetter(1)
  41. template = load_fortunes_template()
  42. loop = asyncio.get_event_loop()
  43. loop.run_until_complete(setup_database())
  44. @route.get('/json')
  45. async def json_serialization():
  46. return {'message': 'Hello, world!'}
  47. class DatabaseObject(TypedDict):
  48. id: int
  49. randomNumber: float
  50. @route.get('/db')
  51. async def single_database_query():
  52. row_id = randint(1, 10000)
  53. async with connection_pool.acquire() as connection:
  54. number = await connection.fetchval(READ_ROW_SQL, row_id)
  55. return DatabaseObject(id=row_id, randomNumber=number)
  56. @route.get('/queries')
  57. async def multiple_database_queries(queries: Optional[str] = None):
  58. num_queries = get_num_queries(queries)
  59. row_ids = [randint(1, 10000) for _ in range(num_queries)]
  60. worlds = []
  61. async with connection_pool.acquire() as connection:
  62. statement = await connection.prepare(READ_ROW_SQL)
  63. for row_id in row_ids:
  64. number = await statement.fetchval(row_id)
  65. worlds.append(
  66. DatabaseObject(
  67. id=row_id,
  68. randomNumber=number
  69. )
  70. )
  71. return worlds
  72. @route.get('/fortunes')
  73. async def fortunes():
  74. async with connection_pool.acquire() as connection:
  75. fortunes = await connection.fetch('SELECT * FROM Fortune')
  76. fortunes.append(ADDITIONAL_ROW)
  77. fortunes.sort(key=sort_fortunes_key)
  78. content = template.render(fortunes=fortunes)
  79. return html(content)
  80. @route.get('/updates')
  81. async def database_updates(queries: Optional[str] = None):
  82. worlds = []
  83. updates = set()
  84. async with connection_pool.acquire() as connection:
  85. statement = await connection.prepare(READ_ROW_SQL_TO_UPDATE)
  86. for _ in range(get_num_queries(queries)):
  87. record = await statement.fetchrow(randint(1, 10000))
  88. world = DatabaseObject(
  89. id=record['id'], randomNumber=record['randomnumber']
  90. )
  91. world['randomNumber'] = randint(1, 10000)
  92. worlds.append(world)
  93. updates.add((world['id'], world['randomNumber']))
  94. await connection.executemany(WRITE_ROW_SQL, updates)
  95. return worlds
  96. @route.get('/plaintext')
  97. async def plaintext():
  98. return text('Hello, world!')
  99. app = appdaora([
  100. json_serialization,
  101. single_database_query,
  102. multiple_database_queries,
  103. fortunes,
  104. database_updates,
  105. plaintext
  106. ])