* Fetch persisted session usage from backend and update in-memory cache. * Uses a per-workspace request version guard so slower/older responses * cannot overwrite fresher state (e.g. rapid workspace switches).
(workspaceId: string)
| 1094 | * cannot overwrite fresher state (e.g. rapid workspace switches). |
| 1095 | */ |
| 1096 | private refreshSessionUsage(workspaceId: string): void { |
| 1097 | const client = this.client; |
| 1098 | if (!client || !this.isWorkspaceRegistered(workspaceId)) { |
| 1099 | return; |
| 1100 | } |
| 1101 | |
| 1102 | const requestVersion = (this.sessionUsageRequestVersion.get(workspaceId) ?? 0) + 1; |
| 1103 | this.sessionUsageRequestVersion.set(workspaceId, requestVersion); |
| 1104 | |
| 1105 | client.workspace |
| 1106 | .getSessionUsage({ workspaceId }) |
| 1107 | .then((data) => { |
| 1108 | // Stale-response guard: a newer refresh was issued while this one was |
| 1109 | // in-flight. The newer request owns the "known" flip too — flipping it |
| 1110 | // here would let the chat view reveal before the latest usage landed, |
| 1111 | // re-opening the post-reveal pop-in this barrier exists to prevent. |
| 1112 | if ((this.sessionUsageRequestVersion.get(workspaceId) ?? 0) !== requestVersion) { |
| 1113 | return; |
| 1114 | } |
| 1115 | // Workspace may have been removed while the fetch was in-flight. |
| 1116 | if (!this.isWorkspaceRegistered(workspaceId)) { |
| 1117 | return; |
| 1118 | } |
| 1119 | // The latest settled fetch makes the usage "known" (including a null |
| 1120 | // response = known-empty) — the chat view's first-paint barrier |
| 1121 | // distinguishes that from not-yet-loaded so usage-derived banners |
| 1122 | // can't pop in after reveal. |
| 1123 | this.markSessionUsageKnown(workspaceId); |
| 1124 | if (!data) { |
| 1125 | return; |
| 1126 | } |
| 1127 | |
| 1128 | if ( |
| 1129 | this.providersConfig && |
| 1130 | this.providersConfigFingerprint != null && |
| 1131 | data.tokenStatsCache?.providersConfigVersion !== this.providersConfigFingerprint |
| 1132 | ) { |
| 1133 | repriceSessionUsage(data, this.providersConfig, this.providersConfigFingerprint); |
| 1134 | } |
| 1135 | |
| 1136 | this.sessionUsage.set(workspaceId, data); |
| 1137 | this.usageStore.bump(workspaceId); |
| 1138 | }) |
| 1139 | .catch((error) => { |
| 1140 | console.warn(`Failed to fetch session usage for ${workspaceId}:`, error); |
| 1141 | // Self-heal: a failed LATEST fetch must not hold the first-paint |
| 1142 | // barrier. Stale failures defer to the newer in-flight request, same |
| 1143 | // as the success path above. |
| 1144 | if ((this.sessionUsageRequestVersion.get(workspaceId) ?? 0) === requestVersion) { |
| 1145 | this.markSessionUsageKnown(workspaceId); |
| 1146 | } |
| 1147 | }); |
| 1148 | } |
| 1149 | |
| 1150 | private async refreshProvidersConfig(client: RouterClient<AppRouter>): Promise<void> { |
| 1151 | // Version counter prevents an older, slower response from overwriting a newer one. |
no test coverage detected