mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-10-30 04:15:45 +08:00
fix(persistence): make resource URL catalog downgrade work standalone
0041_resource_urls could not be rolled back through the supported entry point (`python -m langbot.pkg.persistence.alembic_runner downgrade`): - SQLite failed with `no such function: langbot_expand_resource_urls`. The UDF is registered by an Engine `connect` hook that only runs when the application installs the catalog, so a standalone migration process held a connection without it. - Both backends failed with `AttributeError: 'Engine' object has no attribute '_langbot_resource_aliases'`, because `uninstall()` assumed `install()` had already run on that engine. Register the expansion UDF on the migration connection for SQLite, and let `uninstall()` skip the alias cache when the engine never installed it. The downgrade still rewrites retained payloads back to literal URLs and drops the catalog; only the missing hooks were at fault. Co-authored-by: multica-agent <[email protected]>
This commit is contained in:
co-authored by
multica-agent
parent
c1284be8fc
commit
1f81966606
@@ -70,12 +70,29 @@ def upgrade():
|
||||
cursor = rows[-1][key.name]
|
||||
|
||||
|
||||
def _ensure_sqlite_expansion(connection) -> None:
|
||||
"""Install the expansion UDF on this already-open SQLite connection.
|
||||
|
||||
Downgrade is often run by a standalone migration process whose engine was
|
||||
created outside the application boot path, so the ``connect`` hook never
|
||||
registered `langbot_expand_resource_urls` for the connection in use.
|
||||
"""
|
||||
from langbot.pkg.persistence.resource_urls import register_sqlite
|
||||
|
||||
dbapi = getattr(connection.connection, 'dbapi_connection', None)
|
||||
if dbapi is None:
|
||||
raise RuntimeError('SQLite resource URL downgrade requires a DBAPI connection')
|
||||
register_sqlite(dbapi, None)
|
||||
|
||||
|
||||
def downgrade():
|
||||
from langbot.pkg.entity.persistence.base import Base
|
||||
from langbot.pkg.persistence.media import MediaReferenceText, MediaReferenceJSON
|
||||
from langbot.pkg.persistence.resource_urls import uninstall
|
||||
|
||||
connection = op.get_bind()
|
||||
if connection.dialect.name == 'sqlite':
|
||||
_ensure_sqlite_expansion(connection)
|
||||
existing = set(sa.inspect(connection).get_table_names())
|
||||
for table in sorted(Base.metadata.tables.values(), key=lambda table: table.name):
|
||||
if table.name not in existing:
|
||||
|
||||
@@ -148,7 +148,10 @@ def uninstall(engine):
|
||||
sa.event.remove(engine, 'before_cursor_execute', normalize_parameters)
|
||||
engine.dialect._langbot_resource_urls = False
|
||||
engine.clear_compiled_cache()
|
||||
engine._langbot_resource_aliases.clear()
|
||||
# A migration process may uninstall an engine that never ran install().
|
||||
aliases = getattr(engine, '_langbot_resource_aliases', None)
|
||||
if aliases is not None:
|
||||
aliases.clear()
|
||||
|
||||
|
||||
def normalize_parameters(connection, cursor, statement, parameters, context, executemany):
|
||||
|
||||
Reference in New Issue
Block a user