Jun 26 MT-1 phase

This commit is contained in:
2026-06-26 16:37:44 -04:00
parent fc39491891
commit 07cf2e5816
9 changed files with 300 additions and 55 deletions
+29
View File
@@ -0,0 +1,29 @@
"""
app/tenancy/routing.py
----------------------
RoutingSession — the per-request tenant-aware SQLAlchemy session.
Subclasses Flask-SQLAlchemy's own Session so that all existing behaviour
(default bind, __bind_key__ resolution) is preserved. The ONLY change: when a
tenant engine has been selected for the current request (g.tenant_engine, set
by the resolver middleware), every query binds to that engine instead.
When no tenant engine is present — multi-tenancy disabled, an exempt path, a
CLI invocation, or any non-request context — this falls through to the normal
Flask-SQLAlchemy behaviour, i.e. the app's configured default database. This
makes the routing layer completely inert until a tenant is actually resolved,
so the existing single-tenant deployment is unaffected.
"""
from flask import g, has_app_context
from flask_sqlalchemy.session import Session as _FlaskSQLAlchemySession
class RoutingSession(_FlaskSQLAlchemySession):
def get_bind(self, mapper=None, clause=None, bind=None, **kwargs):
# Respect an explicitly supplied bind (engine-targeted operations).
if bind is None and has_app_context():
tenant_engine = g.get('tenant_engine', None)
if tenant_engine is not None:
return tenant_engine
return super().get_bind(mapper=mapper, clause=clause, bind=bind, **kwargs)