Files
shopdb-flask/scripts/loadtest/pool_status.py
benjamin.baker 0d5b9730e3 Add load test harness for pool and fleet sizing
Adds the scripts used to size the connection pool and validate fleet polling under load: burst arrival and mixed workload drivers, pool and resource samplers, a UI probe, host seed/drop SQL, and a gevent Dockerfile. Hosts are addressed by compose service name (api:5001) rather than a local path, so the harness runs against any stack rather than one machine.

loadtest_token.py mints a scoped collector token named LOADTEST and prints the secret once, then revokes only that token by name so a real collector token is never touched. envkeyfallback is false, so the harness needs a genuine managed token rather than an env key.
2026-09-07 12:39:53 -04:00

43 lines
1.3 KiB
Python

"""Report SQLAlchemy pool saturation from inside the API container.
WHY: MySQL's max_connections is NOT the ceiling that binds first. The effective
limit is per-process: pool_size + max_overflow, multiplied by worker count.
With the defaults (5 + 10) and 4 workers that is 60, not 151. A peak of 52
therefore means 87 percent of the real ceiling, not 34 percent.
Prints the computed ceiling so a measured high-water mark can be compared
against the right number.
Usage (inside the api container, PYTHONPATH=/app):
python pool_status.py
"""
import json
import os
from shopdb import create_app
from shopdb.api import db
def main():
app = create_app(os.environ.get('FLASK_ENV', 'production'))
with app.app_context():
engine = db.engine
pool = engine.pool
size = pool.size()
overflow = getattr(pool, '_max_overflow', 0)
workers = int(os.environ.get('GUNICORN_WORKERS', '4'))
print(json.dumps({
'pool_class': type(pool).__name__,
'pool_size': size,
'max_overflow': overflow,
'per_worker_ceiling': size + overflow,
'workers': workers,
'effective_ceiling': (size + overflow) * workers,
'checkedout': pool.checkedout(),
'status': pool.status(),
}, indent=2))
if __name__ == '__main__':
main()