app_async_raw.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/env python
  2. from datetime import datetime
  3. import os
  4. from random import randint, sample
  5. import asyncpg
  6. from asyncache import cached
  7. from cachetools.keys import hashkey
  8. from microdot_asgi import Microdot
  9. from microdot_jinja import render_template
  10. app = Microdot()
  11. get_world_sql = 'SELECT id, randomnumber FROM world WHERE id = $1'
  12. update_world_sql = 'UPDATE world SET randomnumber = $1 WHERE id = $2'
  13. fortune_sql = 'SELECT * FROM fortune'
  14. db = None
  15. async def asgi(scope, receive, send):
  16. if scope['type'] == 'lifespan':
  17. while True:
  18. message = await receive()
  19. if message['type'] == 'lifespan.startup':
  20. global db, get_world_stmt, update_world_stmt, fortune_stmt
  21. db = await asyncpg.create_pool(os.environ['DATABASE_URL'])
  22. await send({'type': 'lifespan.startup.complete'})
  23. elif message['type'] == 'lifespan.shutdown':
  24. db.close()
  25. await send({'type': 'lifespan.shutdown.complete'})
  26. return
  27. else:
  28. return await app(scope, receive, send)
  29. def get_num_queries(request, name="queries"):
  30. try:
  31. num_queries = request.args.get(name, 1, type=int)
  32. except ValueError:
  33. num_queries = 1
  34. if num_queries < 1:
  35. return 1
  36. if num_queries > 500:
  37. return 500
  38. return num_queries
  39. def generate_ids(num_queries):
  40. return sample(range(1, 10001), num_queries)
  41. @app.route("/json")
  42. async def test_json(request):
  43. return {"message": "Hello, World!"}
  44. @app.route("/db")
  45. async def test_db(request):
  46. id = randint(1, 10000)
  47. async with db.acquire() as conn:
  48. result = await conn.fetchrow(get_world_sql, id)
  49. world = {'id': result[0], 'randomNumber': result[1]}
  50. return world
  51. async def get_world(stmt, id):
  52. result = await stmt.fetchrow(id)
  53. return {'id': result[0], 'randomNumber': result[1]}
  54. @app.route("/queries")
  55. async def test_queries(request):
  56. async with db.acquire() as conn:
  57. stmt = await conn.prepare(get_world_sql)
  58. worlds = [await get_world(stmt, id) for id in generate_ids(get_num_queries(request))]
  59. return worlds
  60. @app.route("/fortunes")
  61. async def test_fortunes(request):
  62. async with db.acquire() as conn:
  63. fortunes = list(await conn.fetch(fortune_sql))
  64. fortunes.append((0, "Additional fortune added at request time."))
  65. fortunes.sort(key=lambda f: f[1])
  66. return render_template("fortunes_raw.html", fortunes=fortunes), {'Content-Type': 'text/html; charset=utf-8'}
  67. @app.route("/updates")
  68. async def test_updates(request):
  69. worlds = []
  70. updated_worlds = []
  71. ids = generate_ids(get_num_queries(request))
  72. ids.sort() # to avoid deadlocks
  73. async with db.acquire() as conn:
  74. get_stmt = await conn.prepare(get_world_sql)
  75. update_stmt = await conn.prepare(update_world_sql)
  76. for id in ids:
  77. world = await get_world(get_stmt, id)
  78. new_value = randint(1, 10000)
  79. updated_worlds.append((new_value, id))
  80. worlds.append({'id': id, 'randomNumber': new_value})
  81. await update_stmt.executemany(updated_worlds)
  82. return worlds
  83. @app.route("/plaintext")
  84. async def test_plaintext(request):
  85. return b"Hello, World!"
  86. @cached(cache={}, key=lambda stmt, id: hashkey(id))
  87. async def get_cached_world(stmt, id):
  88. result = await stmt.fetchrow(id)
  89. return {'id': result[0], 'randomNumber': result[1]}
  90. @app.route("/cached-queries")
  91. async def test_cached_queries(request):
  92. async with db.acquire() as conn:
  93. get_stmt = await conn.prepare(get_world_sql)
  94. worlds = [await get_cached_world(get_stmt, id) for id in generate_ids(get_num_queries(request, 'count'))]
  95. return worlds