-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
schema: multi-tenancy #1140
base: main
Are you sure you want to change the base?
schema: multi-tenancy #1140
Conversation
Signed-off-by: sadath-12 <[email protected]>
✅ Deploy Preview for thriving-cassata-78ae72 canceled.
|
""" | ||
Async database session. | ||
""" | ||
session_manager = get_session_manager() | ||
session_manager = get_session_manager(request) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Related to my other comment, I would just pass in the schema here. so:
session_manager = get_session_manager(schema=request.headers.get("schema")
datajunction-server/datajunction_server/api/access/authentication/basic.py
Outdated
Show resolved
Hide resolved
Signed-off-by: sadath-12 <[email protected]>
Signed-off-by: sadath-12 <[email protected]>
Signed-off-by: sadath-12 <[email protected]>
I have updated the implementation to only route to different schema and remove creation of schema code as discussed with @samredai |
Signed-off-by: sadath-12 <[email protected]>
if schema: | ||
engine = engine.execution_options(schema_translate_map={None: schema}) | ||
|
||
settings.customSchema = request.headers.get("new_tenant") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sadath-12 can you help me understand why you need to modify the settings instance directly like this? Also, since you're pulling schema from the "tenant" header, you don't need this settings property at all anymore, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @samredai , this is to tell dj to switch to the schema when we hit register schema endpoint (created internally) so dj can run migrations on it on runtime or else it will have to be restarted
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @sadath-12 I understand the intent here now. I don't think modifying the application settings is the right approach though. Instead we should parameterize the alembic migration scripts (I think I recall @shangyian proposing this). Then in your custom endpoint logic, you can programmatically set that schema parameter using the context.
Wondering if this is close to finalization? Anything we can do to help ? |
@ockhamlabs sorry for the late reply here. Let's revisit this after this refactor for the query service goes in which should make this ultimately much easier to achieve. I'm planning to catch up with @sadath-12 soon, either during the community meeting or async. |
(after talk with @samredai ) |
@sadath-12 super sorry for losing track of this. I think we're close to figuring this out--this PR is doing the right thing by parsing the tenant value from the request header, but let's save any of the changes in the datajunction-query directory or to the alembic/env.py file for a follow up PR. If you could update this PR to just include the changes to datajunction_server/config.py and datajunction_server/utils.py, we can iterate on that and get this PR merged pretty quickly. |
""" | ||
Get session manager | ||
""" | ||
session_manager = DatabaseSessionManager() | ||
session_manager.schema = request.headers.get("tenant") | ||
settings = get_settings() | ||
settings.customSchema = request.headers.get("new_tenant") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sadath-12 from our discussions I remember you telling me that you had to do this so that the alembic script would run properly when you init a new tenant's schema, but since this commit the alembic scripts are now configurable to target a specific schema. This means in any of your custom endpoints you could do something like this:
from alembic.config import Config
from alembic import command
...
SCHEMA = request.headers.get("tenant") # For example, "tenant1"
if SCHEMA:
alembic_cfg = Config()
alembic_cfg.set_main_option("script_location", "./alembic")
alembic_cfg.cmd_opts = {"x": [f"uri=postgresql+psycopg://username:password@server:5432/{SCHEMA}"]}
command.upgrade(alembic_cfg, "head")
...
Which means you don't need to add this customSchema to the settings class at all.
Summary
The pr allows the users to pass schema as tenant in headers if the users wants multi-tenancy into their application .
Also it removes
Form()
reading from/basic/user
and usesrequest.json()
to read from body aspydantic
does not reset the pointers and causesstream consumed error
Test Plan
make check
passesmake test
shows 100% unit test coverageDeployment Plan