mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-08-08 20:30:59 +00:00
feat(cloud): harden multi-tenant runtime resources
This commit is contained in:
@@ -13,11 +13,13 @@ from langbot.pkg.persistence.databases import postgresql
|
||||
@pytest.mark.asyncio
|
||||
async def test_postgresql_manager_parses_explicit_url_without_string_reassembly(monkeypatch) -> None:
|
||||
captured = None
|
||||
captured_options = None
|
||||
sentinel_engine = object()
|
||||
|
||||
def create_engine(url):
|
||||
nonlocal captured
|
||||
def create_engine(url, **options):
|
||||
nonlocal captured, captured_options
|
||||
captured = url
|
||||
captured_options = options
|
||||
return sentinel_engine
|
||||
|
||||
monkeypatch.setattr(postgresql.sqlalchemy_asyncio, 'create_async_engine', create_engine)
|
||||
@@ -40,6 +42,13 @@ async def test_postgresql_manager_parses_explicit_url_without_string_reassembly(
|
||||
assert captured.password == 'p@ss'
|
||||
assert captured.query['ssl'] == 'require'
|
||||
assert 'sslmode' not in captured.query
|
||||
assert captured_options == {
|
||||
'pool_size': 10,
|
||||
'max_overflow': 10,
|
||||
'pool_timeout': 30,
|
||||
'pool_recycle': 1800,
|
||||
'pool_pre_ping': True,
|
||||
}
|
||||
assert manager.engine is sentinel_engine
|
||||
|
||||
|
||||
@@ -47,7 +56,7 @@ async def test_postgresql_manager_parses_explicit_url_without_string_reassembly(
|
||||
async def test_postgresql_manager_builds_structured_url_with_special_password(monkeypatch) -> None:
|
||||
captured = None
|
||||
|
||||
def create_engine(url):
|
||||
def create_engine(url, **_options):
|
||||
nonlocal captured
|
||||
captured = url
|
||||
return object()
|
||||
@@ -76,6 +85,60 @@ async def test_postgresql_manager_builds_structured_url_with_special_password(mo
|
||||
assert captured.database == 'langbot'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_postgresql_manager_applies_explicit_bounded_pool_options(monkeypatch) -> None:
|
||||
captured_options = None
|
||||
|
||||
def create_engine(_url, **options):
|
||||
nonlocal captured_options
|
||||
captured_options = options
|
||||
return object()
|
||||
|
||||
monkeypatch.setattr(postgresql.sqlalchemy_asyncio, 'create_async_engine', create_engine)
|
||||
ap = SimpleNamespace(
|
||||
instance_config=SimpleNamespace(
|
||||
data={
|
||||
'database': {
|
||||
'postgresql': {
|
||||
'pool_size': 24,
|
||||
'max_overflow': 0,
|
||||
'pool_timeout_seconds': 7,
|
||||
'pool_recycle_seconds': 600,
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
await postgresql.PostgreSQLDatabaseManager(ap).initialize()
|
||||
|
||||
assert captured_options == {
|
||||
'pool_size': 24,
|
||||
'max_overflow': 0,
|
||||
'pool_timeout': 7,
|
||||
'pool_recycle': 600,
|
||||
'pool_pre_ping': True,
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
('name', 'value'),
|
||||
[
|
||||
('pool_size', 0),
|
||||
('pool_size', True),
|
||||
('max_overflow', -1),
|
||||
('pool_timeout_seconds', 0),
|
||||
('pool_recycle_seconds', '1800'),
|
||||
],
|
||||
)
|
||||
async def test_postgresql_manager_rejects_invalid_pool_options(name, value) -> None:
|
||||
ap = SimpleNamespace(instance_config=SimpleNamespace(data={'database': {'postgresql': {name: value}}}))
|
||||
|
||||
with pytest.raises(ValueError, match=rf'database\.postgresql\.{name}'):
|
||||
await postgresql.PostgreSQLDatabaseManager(ap).initialize()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_postgresql_manager_rejects_non_postgresql_url_without_echoing_secret() -> None:
|
||||
ap = SimpleNamespace(
|
||||
|
||||
@@ -104,6 +104,7 @@ async def test_release_migration_disposes_operator_engine_on_failure(monkeypatch
|
||||
manager = SimpleNamespace(
|
||||
db=SimpleNamespace(engine=engine),
|
||||
initialize=AsyncMock(side_effect=RuntimeError('migration failed')),
|
||||
shutdown=AsyncMock(side_effect=engine.dispose),
|
||||
)
|
||||
|
||||
def manager_factory(*args, **kwargs):
|
||||
@@ -121,6 +122,7 @@ async def test_release_migration_disposes_operator_engine_on_failure(monkeypatch
|
||||
await release_migration.run_cloud_release_migration(ap, environ=_operator_environ())
|
||||
|
||||
assert ap.persistence_mgr is manager
|
||||
manager.shutdown.assert_awaited_once()
|
||||
engine.dispose.assert_awaited_once()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user