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:
@@ -1,5 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
|
||||
import pytest
|
||||
from unittest.mock import AsyncMock
|
||||
|
||||
@@ -107,3 +109,53 @@ async def test_resolver_checks_deployment_admission_before_and_after_provider_ca
|
||||
with pytest.raises(RuntimeError, match='expired during provider call'):
|
||||
await resolver.resolve('workspace-a', now=150)
|
||||
assert checks == 2
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_directory_activity_reconciliation_drops_historical_snapshots():
|
||||
provider = AsyncMock()
|
||||
provider.get_workspace_entitlement = AsyncMock(return_value=_snapshot())
|
||||
resolver = EntitlementResolver('instance-a', provider)
|
||||
await resolver.reconcile_active_workspaces({'workspace-a', 'workspace-b'})
|
||||
await resolver.resolve('workspace-a', now=150)
|
||||
|
||||
await resolver.reconcile_active_workspaces({'workspace-b'})
|
||||
|
||||
assert resolver.snapshot_counts() == {
|
||||
'active_workspaces': 1,
|
||||
'cached_snapshots': 0,
|
||||
}
|
||||
with pytest.raises(EntitlementUnavailableError, match='directory projection'):
|
||||
await resolver.resolve('workspace-a', now=150)
|
||||
provider.get_workspace_entitlement.assert_awaited_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_directory_fence_wins_race_with_inflight_entitlement_fetch():
|
||||
provider_started = asyncio.Event()
|
||||
release_provider = asyncio.Event()
|
||||
|
||||
async def fetch(_workspace_uuid: str) -> EntitlementSnapshot:
|
||||
provider_started.set()
|
||||
await release_provider.wait()
|
||||
return _snapshot()
|
||||
|
||||
provider = AsyncMock()
|
||||
provider.get_workspace_entitlement = AsyncMock(side_effect=fetch)
|
||||
resolver = EntitlementResolver('instance-a', provider)
|
||||
await resolver.reconcile_active_workspaces({'workspace-a'})
|
||||
resolve_task = asyncio.create_task(resolver.resolve('workspace-a', now=150))
|
||||
await provider_started.wait()
|
||||
|
||||
await resolver.update_workspace_activity(
|
||||
active_workspace_uuids=set(),
|
||||
inactive_workspace_uuids={'workspace-a'},
|
||||
)
|
||||
release_provider.set()
|
||||
|
||||
with pytest.raises(EntitlementUnavailableError, match='directory projection'):
|
||||
await resolve_task
|
||||
assert resolver.snapshot_counts() == {
|
||||
'active_workspaces': 0,
|
||||
'cached_snapshots': 0,
|
||||
}
|
||||
|
||||
@@ -86,6 +86,50 @@ async def test_consumes_valid_workspace_launch_assertion_once():
|
||||
await service.consume_assertion(token, expected_workspace_uuid=WORKSPACE_UUID)
|
||||
|
||||
|
||||
async def test_replay_cache_does_not_scan_all_live_assertions(monkeypatch):
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
now = int(time.time())
|
||||
service = _service(private_key, now=now)
|
||||
for index in range(512):
|
||||
await service._consume_jti(f'jti-{index}', now + 90)
|
||||
|
||||
class NoGlobalIterationDict(dict):
|
||||
def __iter__(self):
|
||||
raise AssertionError('replay admission scanned all live assertions')
|
||||
|
||||
def keys(self):
|
||||
raise AssertionError('replay admission scanned all live assertions')
|
||||
|
||||
def items(self):
|
||||
raise AssertionError('replay admission scanned all live assertions')
|
||||
|
||||
def values(self):
|
||||
raise AssertionError('replay admission scanned all live assertions')
|
||||
|
||||
guarded_jtis = NoGlobalIterationDict(service._consumed_jtis)
|
||||
monkeypatch.setattr(service, '_consumed_jtis', guarded_jtis)
|
||||
|
||||
await service._consume_jti('jti-new', now + 90)
|
||||
|
||||
assert len(guarded_jtis) == 513
|
||||
|
||||
|
||||
async def test_replay_cache_fails_closed_at_capacity(monkeypatch):
|
||||
from langbot.pkg.cloud import launch
|
||||
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
now = int(time.time())
|
||||
service = _service(private_key, now=now)
|
||||
monkeypatch.setattr(launch, '_CONSUMED_JTI_MAX_ENTRIES', 2)
|
||||
await service._consume_jti('jti-1', now + 90)
|
||||
await service._consume_jti('jti-2', now + 90)
|
||||
|
||||
with pytest.raises(SpaceLaunchError, match='replay cache capacity'):
|
||||
await service._consume_jti('jti-3', now + 90)
|
||||
with pytest.raises(SpaceLaunchError, match='already been consumed'):
|
||||
await service._consume_jti('jti-1', now + 90)
|
||||
|
||||
|
||||
async def test_rejects_expired_wrong_workspace_and_wrong_instance_assertions():
|
||||
private_key = Ed25519PrivateKey.generate()
|
||||
now = int(time.time())
|
||||
|
||||
Reference in New Issue
Block a user