-
-
Notifications
You must be signed in to change notification settings - Fork 252
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
[Question]Can i use async db driver to serve db changes? #805
Comments
Hi, You are right, currently alembic does not support async drivers. That being saind I think we would accept PR that add that functionality. |
Thanks for answer @CaselIT! Have a great day! |
Speaking with mike on gitter it is indeed just the env.py that needs to change, to something like this: async def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
engine = create_async_engine(...)
def do_migrations(connection):
context.configure(connection=connection, target_metadata=target_metadata, **config_options)
with context.begin_transaction():
context.run_migrations()
async with engine.connect() as connection:
await connection.run_sync(do_migrations)
await engine.dispose()
if context.is_offline_mode():
run_migrations_offline()
else:
import asyncio
asyncio.run(run_migrations_online()) |
Great! Thank you @CaselIT, I'll try this! |
There shouldn't, but I don't think it would make a difference in this case using one or the other |
CaselIT has proposed a fix for this issue in the master branch: Add async template to Alembic https://gerrit.sqlalchemy.org/c/sqlalchemy/alembic/+/2609 |
you konw you could just leave everything as it is, and use a database URL with "?async_fallback=True". this will run each DBAPI method in a new asyncio loop under the hood. @CaselIT would that be a less trouble? |
Ah right we also support that. One thing I'm not sure is if we want to make that api public. IIRC it is currently not documented. Also maybe having the async call in env feels less magic for people? |
well theyre both magic :) but this way the user feels like they're a little bit more a part of it :) |
HI @zzzeek!
|
No that's not needed if you modify the env with the async bits. |
@crotaoryx yes, you can just change the URL to have ?async_fallback=True and you have to change nothing else. What this basically does is move the "sync->async" part to happen for each database call, rather than your initial asyncio.run(). @CaselIT and I tend to differ on this approach, for me "magic is magic" but he is correct that the more longhand way is a tiny bit less "magic". It's also more efficient at scale though that doesn't matter much for a migration script. |
Hi there! I am also trying to use it with my sqlalchemy project which uses asyncpg, but I also got the normal The version is |
both should work. we added a faq entry for this https://alembic.sqlalchemy.org/en/latest/cookbook.html#using-asyncio-with-alembic please let us know if you find issues |
I cannot reproduce, are you sure you are using an updated version of alembic? |
Yeah, I am using the latest of |
I guess you should try uninstalling and re-installing it. I tried in an empty docker image, so installing from a clean environment works |
Alright, I'll do that. I am having the trouble with pipenv locking and I even commented on their official repo's issues too. Its just too crappy atm |
I have used this one, but I have this error
|
we just added (yesterday) a clarification regarding that error at https://docs.sqlalchemy.org/en/14/orm/extensions/asyncio.html#synopsis-core tldr: add an |
doesn't work for me(( @CaselIT db.py import sqlalchemy
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
from settings.base import SQLALCHEMY_DATABASE_URI
engine = create_async_engine(url=SQLALCHEMY_DATABASE_URI, future=True, echo=True)
# Base = declarative_base()
Session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)
metadata = sqlalchemy.MetaData()
async def get_sql_db():
async with Session() as session:
yield session env.py async def run_migrations_online():
def do_migrations(connection):
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async with engine.connect() as connection:
await connection.run_sync(do_migrations)
await engine.dispose()
if context.is_offline_mode():
run_migrations_offline()
else:
import asyncio
asyncio.run(run_migrations_online()) I just try to create the first migration but I got the same problem :(
|
I just tried and I cannot reproduce. (aiosqlite and asyncpg) |
@CaselIT
|
I cannot reproduce on windows and of linux (fedora). Commenting If you have a reproducer it's probably best to report in another issue |
For those like me who read this issue to find a solution but couldn't make it work, the Alembic team as a "async" version of their env.py available at https://github.com/sqlalchemy/alembic/blob/9b01e5fa7178333f2e78ee0fc1322112307b51dd/alembic/templates/async/env.py This one works well :) |
There's also a cookbook entry: https://alembic.sqlalchemy.org/en/latest/cookbook.html#using-asyncio-with-alembic |
Alembic has added async support for the |
What about upgrading programmatically? When running
|
alembic upgrade() is a sync-style method. therefore it has to be run in run_sync. run_sync is given the "sync" connection, which has to be bound to the API per https://alembic.sqlalchemy.org/en/latest/cookbook.html#sharing-a-connection-with-a-series-of-migration-commands-and-environments . Therefore, ensuring the changes to env.py are made as per https://alembic.sqlalchemy.org/en/latest/cookbook.html#sharing-a-connection-with-a-series-of-migration-commands-and-environments to accommodate a connection, this looks like: def run_upgrade(connection, cfg):
cfg.attributes['connection'] = connection
command.upgrade(cfg, "head")
async def run_async_upgrade():
async with async_engine.begin() as conn:
await connection.run_sync(run_upgrade, config) |
@zzzeek I can't get it to work. Following your instructions and running the upgrade in my code I get all the sql upgrade commands printed to the terminal and it finishes with:
Nothing happens in the DB. I'm not sure what's going on. Also the alembic cli upgrade command is now failing:
Am I using the wrong version of some library maybe? EDIT: Just checked and I'm running on latest sqlalchemy and alembic |
Hi @alejoar Could you open a new issue or discussion with a complete example? Thanks |
this was extremely helpfull! ty |
Anyone experiencing this issue, just read the quoted answer. |
THANK YO SOO MUCH EVERYONE I FINALLY WITH THE HELP OF THE ASYNC env.py TEMPLATE SOLVED MY PROBLEM ITS BEEN TWO DAYS!!! my stackoverflow question: https://stackoverflow.com/questions/78742213/alembic-not-recognizing-multiple-models-using-fastapi |
Hi guys!
I'm newbie with alembic and wanted clarify one thing.
As i understood based on docs, alembic uses sync database driver(for example, psycopg2) to serve db changes. At the same time i saw SQLAlchemy is moving forward with async, which means i can use asyncpg. As result, it seems app need has both of them - psycopg2 and asyncpg.
Is it possible to use just asyncpg for alembic and SQLAlchemy? Or maybe it's planned future feature? I know that alembic don't need async features to modify db, but i think it's good for "clean requirements" purpose use one driver for both cases.
Or i'm wrong and maybe missing something?
Thanks!
The text was updated successfully, but these errors were encountered: