mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-04 00:27:14 +00:00
fix(cloud): serialize directory catch-up (#2500)
Co-authored-by: dadachann <185672915+dadachann@users.noreply.github.com>
This commit is contained in:
@@ -453,13 +453,28 @@ class UserRouterGroup(group.RouterGroup):
|
||||
)
|
||||
break
|
||||
except WorkspaceNotFoundError:
|
||||
if projection_service is None or attempt == 3:
|
||||
if projection_service is None:
|
||||
raise
|
||||
elif projection_service is None or attempt == 3:
|
||||
elif projection_service is None:
|
||||
break
|
||||
|
||||
if attempt == 3:
|
||||
break
|
||||
await projection_service.sync_once()
|
||||
account = await self.ap.user_service.get_user_by_uuid(launch['account_uuid'])
|
||||
|
||||
if access is None and projection_service is not None:
|
||||
# The target event may be deeper than the bounded incremental
|
||||
# page budget. One authoritative signed snapshot catches this
|
||||
# process up without turning the callback into unbounded polling.
|
||||
await projection_service.refresh_snapshot()
|
||||
account = await self.ap.user_service.get_user_by_uuid(launch['account_uuid'])
|
||||
if account is not None:
|
||||
self.ap.user_service._require_active_account(account)
|
||||
access = await self.ap.workspace_collaboration_service.resolve_account_workspace(
|
||||
account.uuid,
|
||||
launch['workspace_uuid'],
|
||||
)
|
||||
if account is None:
|
||||
raise SpaceLaunchError('Launch Account is not projected into Core')
|
||||
if access is None: # pragma: no cover - bounded loop resolves or raises.
|
||||
|
||||
@@ -125,10 +125,21 @@ class DirectoryProjectionService:
|
||||
# The database cursor remains the shared projection high-water mark,
|
||||
# while this cursor tracks what this process has actually observed.
|
||||
self._consumer_cursor: int | None = None
|
||||
self._sync_lock = asyncio.Lock()
|
||||
|
||||
async def initialize(self) -> None:
|
||||
"""Block Cloud startup until one full signed snapshot is committed."""
|
||||
|
||||
async with self._sync_lock:
|
||||
await self._refresh_snapshot()
|
||||
|
||||
async def refresh_snapshot(self) -> None:
|
||||
"""Refresh from one full signed snapshot within the sync single-flight."""
|
||||
|
||||
async with self._sync_lock:
|
||||
await self._refresh_snapshot()
|
||||
|
||||
async def _refresh_snapshot(self) -> None:
|
||||
last_superseded: _DirectorySnapshotSuperseded | None = None
|
||||
for _attempt in range(5):
|
||||
snapshot = await self.provider.fetch_snapshot(self.instance_uuid)
|
||||
@@ -159,9 +170,13 @@ class DirectoryProjectionService:
|
||||
delay = min(max(delay * 2, self.sync_interval_seconds), self.max_staleness_seconds / 2)
|
||||
|
||||
async def sync_once(self) -> None:
|
||||
async with self._sync_lock:
|
||||
await self._sync_once()
|
||||
|
||||
async def _sync_once(self) -> None:
|
||||
cursor = self._consumer_cursor
|
||||
if cursor is None:
|
||||
await self.initialize()
|
||||
await self._refresh_snapshot()
|
||||
return
|
||||
batch = await self.provider.fetch_events(
|
||||
self.instance_uuid,
|
||||
|
||||
Reference in New Issue
Block a user