* Subscribe to backend timing stats snapshots for a workspace.
(workspaceId: string)
| 1573 | */ |
| 1574 | |
| 1575 | private subscribeToStats(workspaceId: string): void { |
| 1576 | if (!this.client) { |
| 1577 | return; |
| 1578 | } |
| 1579 | |
| 1580 | // Only subscribe for registered workspaces when we have at least one UI consumer. |
| 1581 | if (!this.isWorkspaceRegistered(workspaceId)) { |
| 1582 | return; |
| 1583 | } |
| 1584 | if ((this.statsListenerCounts.get(workspaceId) ?? 0) <= 0) { |
| 1585 | return; |
| 1586 | } |
| 1587 | |
| 1588 | // Skip if already subscribed |
| 1589 | if (this.statsUnsubscribers.has(workspaceId)) { |
| 1590 | return; |
| 1591 | } |
| 1592 | |
| 1593 | const controller = new AbortController(); |
| 1594 | const { signal } = controller; |
| 1595 | let iterator: AsyncIterator<WorkspaceStatsSnapshot> | null = null; |
| 1596 | |
| 1597 | (async () => { |
| 1598 | try { |
| 1599 | const subscribedIterator = await this.client!.workspace.stats.subscribe( |
| 1600 | { workspaceId }, |
| 1601 | { signal } |
| 1602 | ); |
| 1603 | iterator = subscribedIterator; |
| 1604 | |
| 1605 | for await (const snapshot of subscribedIterator) { |
| 1606 | if (signal.aborted) break; |
| 1607 | queueMicrotask(() => { |
| 1608 | if (signal.aborted) { |
| 1609 | return; |
| 1610 | } |
| 1611 | this.workspaceStats.set(workspaceId, snapshot); |
| 1612 | this.statsStore.bump(workspaceId); |
| 1613 | }); |
| 1614 | } |
| 1615 | } catch (error) { |
| 1616 | if (signal.aborted || isAbortError(error)) return; |
| 1617 | console.warn(`[WorkspaceStore] Error in stats subscription for ${workspaceId}:`, error); |
| 1618 | } |
| 1619 | })(); |
| 1620 | |
| 1621 | this.statsUnsubscribers.set(workspaceId, () => { |
| 1622 | controller.abort(); |
| 1623 | void iterator?.return?.(); |
| 1624 | }); |
| 1625 | } |
| 1626 | |
| 1627 | /** |
| 1628 | * Cancel any pending idle state bump for a workspace. |
no test coverage detected