app.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import multiprocessing
  2. from random import randint, sample
  3. import asyncpg
  4. import jinja2
  5. from panther import Panther
  6. from panther.app import API
  7. from panther.events import Event
  8. from panther.request import Request
  9. from panther.response import Response, PlainTextResponse, HTMLResponse
  10. cpu_count = multiprocessing.cpu_count()
  11. MAX_POOL_SIZE = 1000 // cpu_count
  12. MIN_POOL_SIZE = max(MAX_POOL_SIZE // 2, 1)
  13. connection_pool = None
  14. fortune_template = jinja2.Environment(
  15. loader=jinja2.FileSystemLoader('templates'),
  16. autoescape=True
  17. ).get_template('fortune.html')
  18. @Event.startup
  19. async def on_startup():
  20. global connection_pool
  21. connection_pool = await asyncpg.create_pool(
  22. user='benchmarkdbuser',
  23. password='benchmarkdbpass',
  24. database='hello_world',
  25. host='tfb-database',
  26. port=5432,
  27. min_size=MIN_POOL_SIZE,
  28. max_size=MAX_POOL_SIZE,
  29. )
  30. @Event.shutdown
  31. async def on_shutdown():
  32. await connection_pool.close()
  33. @API()
  34. def json_serialization():
  35. return Response(data={'message': 'Hello, world!'})
  36. @API()
  37. async def single_database_query():
  38. row_id = randint(1, 10000)
  39. async with connection_pool.acquire() as connection:
  40. number = await connection.fetchval('SELECT id, randomnumber FROM world WHERE id = $1', row_id)
  41. return Response(data={'id': row_id, 'randomNumber': number})
  42. @API()
  43. async def multiple_database_queries(request: Request):
  44. try:
  45. count = int(request.query_params.get('queries', 1))
  46. except (ValueError, TypeError):
  47. count = 1
  48. row_ids = sample(range(1, 10000), min(max(count, 1), 500))
  49. async with connection_pool.acquire() as connection:
  50. statement = await connection.prepare('SELECT id, randomnumber FROM world WHERE id = $1')
  51. worlds = [{'id': i, 'randomNumber': await statement.fetchval(i)} for i in row_ids]
  52. return Response(data=worlds)
  53. @API()
  54. async def fortunes():
  55. async with connection_pool.acquire() as connection:
  56. fortune_records = await connection.fetch('SELECT * FROM Fortune')
  57. fortune_records = [(row['id'], row['message']) for row in fortune_records]
  58. fortune_records.append((0, 'Additional fortune added at request time.'))
  59. fortune_records.sort(key=lambda row: row[1])
  60. data = fortune_template.render(fortunes=fortune_records)
  61. return HTMLResponse(data=data)
  62. @API()
  63. async def database_updates(request: Request):
  64. try:
  65. count = int(request.query_params.get('queries', 1))
  66. except (ValueError, TypeError):
  67. count = 1
  68. num_queries = min(max(count, 1), 500)
  69. updates = list(zip(
  70. sample(range(1, 10000), num_queries),
  71. sorted(sample(range(1, 10000), num_queries))
  72. ))
  73. worlds = [{'id': row_id, 'randomNumber': number} for row_id, number in updates]
  74. async with connection_pool.acquire() as connection:
  75. statement = await connection.prepare('SELECT id, randomnumber FROM world WHERE id = $1')
  76. for _, row_id in updates:
  77. await statement.fetchval(row_id)
  78. await connection.executemany('UPDATE world SET randomnumber = $1 WHERE id = $2', updates)
  79. return Response(data=worlds)
  80. @API()
  81. def plaintext():
  82. return PlainTextResponse(b'Hello, world!')
  83. url_routing = {
  84. 'json': json_serialization,
  85. 'db': single_database_query,
  86. 'queries': multiple_database_queries,
  87. 'fortunes': fortunes,
  88. 'updates': database_updates,
  89. 'plaintext': plaintext,
  90. }
  91. app = Panther(__name__, configs=__name__, urls=url_routing)