main.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import os
  2. import multiprocessing
  3. from pathlib import Path
  4. import aiohttp_jinja2
  5. import aiopg.sa
  6. import asyncpg
  7. import jinja2
  8. from aiohttp import web
  9. from sqlalchemy.engine.url import URL
  10. from .views import (
  11. json,
  12. single_database_query_orm,
  13. multiple_database_queries_orm,
  14. fortunes,
  15. updates,
  16. plaintext,
  17. single_database_query_raw,
  18. multiple_database_queries_raw,
  19. fortunes_raw,
  20. updates_raw,
  21. )
  22. CONNECTION_ORM = os.getenv('CONNECTION', 'ORM').upper() == 'ORM'
  23. THIS_DIR = Path(__file__).parent
  24. def pg_dsn() -> str:
  25. """
  26. :return: DSN url suitable for sqlalchemy and aiopg.
  27. """
  28. return str(URL(
  29. database='hello_world',
  30. password=os.getenv('PGPASS', 'benchmarkdbpass'),
  31. host='tfb-database',
  32. port='5432',
  33. username=os.getenv('PGUSER', 'benchmarkdbuser'),
  34. drivername='postgres',
  35. ))
  36. async def startup(app: web.Application):
  37. dsn = pg_dsn()
  38. # number of gunicorn workers = multiprocessing.cpu_count() as per gunicorn_conf.py
  39. # max_connections = 2000 as per toolset/setup/linux/databases/postgresql/postgresql.conf:64
  40. # give 10% leeway
  41. max_size = min(1800 / multiprocessing.cpu_count(), 160)
  42. max_size = max(int(max_size), 1)
  43. min_size = max(int(max_size / 2), 1)
  44. print(f'connection pool: min size: {min_size}, max size: {max_size}, orm: {CONNECTION_ORM}')
  45. if CONNECTION_ORM:
  46. app['pg'] = await aiopg.sa.create_engine(dsn=dsn, minsize=min_size, maxsize=max_size, loop=app.loop)
  47. else:
  48. app['pg'] = await asyncpg.create_pool(dsn=dsn, min_size=min_size, max_size=max_size, loop=app.loop)
  49. async def cleanup(app: web.Application):
  50. if CONNECTION_ORM:
  51. app['pg'].close()
  52. await app['pg'].wait_closed()
  53. else:
  54. await app['pg'].close()
  55. def setup_routes(app):
  56. if CONNECTION_ORM:
  57. app.router.add_get('/json', json)
  58. app.router.add_get('/db', single_database_query_orm)
  59. app.router.add_get('/queries/{queries:.*}', multiple_database_queries_orm)
  60. app.router.add_get('/fortunes', fortunes)
  61. app.router.add_get('/updates/{queries:.*}', updates)
  62. app.router.add_get('/plaintext', plaintext)
  63. else:
  64. app.router.add_get('/db', single_database_query_raw)
  65. app.router.add_get('/queries/{queries:.*}', multiple_database_queries_raw)
  66. app.router.add_get('/fortunes', fortunes_raw)
  67. app.router.add_get('/updates/{queries:.*}', updates_raw)
  68. def create_app(loop):
  69. app = web.Application(loop=loop)
  70. jinja2_loader = jinja2.FileSystemLoader(str(THIS_DIR / 'templates'))
  71. aiohttp_jinja2.setup(app, loader=jinja2_loader)
  72. app.on_startup.append(startup)
  73. app.on_cleanup.append(cleanup)
  74. setup_routes(app)
  75. return app