main.py 2.5 KB

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