app.py 4.0 KB

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