mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-07-21 02:05:45 +00:00
fix(config): normalize the postgres:// short scheme for the async ORM engine (#4293)
`app_sqlalchemy_url` rewrites `postgresql://` to `postgresql+asyncpg://` but
leaves libpq's `postgres://` short scheme untouched, so it reaches
`create_async_engine` verbatim and raises
`NoSuchModuleError: Can't load plugin: sqlalchemy.dialects:postgres`.
The two consumers of the same `database.postgres_url` disagree about that
scheme, which is what makes this a partial, backend-only failure rather than a
clean config error:
- the checkpointer and store pass the raw URL to psycopg
(`runtime/checkpointer/provider.py`, `runtime/store/provider.py`), and
psycopg's `conninfo_to_dict` accepts `postgres://` and `postgresql://`
identically;
- the application ORM engine goes through `app_sqlalchemy_url`
(`persistence/engine.py:181`), and SQLAlchemy dropped the `postgres`
dialect alias in 2.0.
So a `postgres://` DSN brings the checkpointer up and takes the ORM engine
down. The `postgres_url` field docstring already promises the opposite --
"the +asyncpg driver suffix is added automatically where needed".
`postgres://` is a legal libpq URI scheme, not a typo, and is the form
`$DATABASE_URL` commonly takes on managed Postgres providers -- which is
exactly what the module docstring recommends configuring
(`postgres_url: $DATABASE_URL`).
Normalize it alongside `postgresql://`. The existing tests covered
`postgresql://` and `postgresql+asyncpg://` but not the short scheme; the new
case fails on main with the `NoSuchModuleError` above.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
90d511f3d2
commit
dd2f73c1a1
@@ -98,5 +98,8 @@ class DatabaseConfig(BaseModel):
|
||||
url = self.postgres_url
|
||||
if url.startswith("postgresql://"):
|
||||
url = url.replace("postgresql://", "postgresql+asyncpg://", 1)
|
||||
elif url.startswith("postgres://"):
|
||||
# libpq's short alias: accepted by the psycopg checkpointer, but not a SQLAlchemy dialect.
|
||||
url = url.replace("postgres://", "postgresql+asyncpg://", 1)
|
||||
return url
|
||||
raise ValueError(f"No SQLAlchemy URL for backend={self.backend!r}")
|
||||
|
||||
@@ -49,6 +49,15 @@ class TestDatabaseConfig:
|
||||
assert url.startswith("postgresql+asyncpg://")
|
||||
assert "u:p@h:5432/db" in url
|
||||
|
||||
def test_app_sqlalchemy_url_postgres_short_scheme(self):
|
||||
c = DatabaseConfig(
|
||||
backend="postgres",
|
||||
postgres_url="postgres://u:p@h:5432/db",
|
||||
)
|
||||
url = c.app_sqlalchemy_url
|
||||
assert url.startswith("postgresql+asyncpg://")
|
||||
assert "u:p@h:5432/db" in url
|
||||
|
||||
def test_app_sqlalchemy_url_postgres_already_asyncpg(self):
|
||||
c = DatabaseConfig(
|
||||
backend="postgres",
|
||||
|
||||
Reference in New Issue
Block a user