MCPcopy
hub / github.com/coder/mux / PRStatusStore

Class PRStatusStore

src/browser/stores/PRStatusStore.ts:164–664  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

162 * Store for GitHub PR status. Fetches status via gh CLI and caches results.
163 */
164export class PRStatusStore {
165 private client: RouterClient<AppRouter> | null = null;
166 private readonly refreshController: RefreshController;
167 private isActive = true;
168
169 // Workspace-based PR detection (keyed by workspaceId)
170 private workspacePRSubscriptions = new MapStore<string, WorkspacePRCacheEntry>();
171 private workspacePRCache = new Map<string, WorkspacePRCacheEntry>();
172 private runtimeRetryUnsubscribers = new Map<string, () => void>();
173
174 // Track active subscriptions per workspace so we only refresh workspaces that are actually visible.
175 private workspaceSubscriptionCounts = new Map<string, number>();
176
177 // Track latest merge queue enrichment request while an in-flight fetch is running.
178 private mergeQueueRefreshPending = new Map<string, MergeQueueRefreshRequest>();
179
180 // Track per-workspace async merge queue enrichment to avoid overlapping gh api calls.
181 private mergeQueueRefreshInFlight = new Map<string, Promise<void>>();
182
183 // Like GitStatusStore: batch immediate refreshes triggered by subscriptions.
184 private immediateUpdateQueued = false;
185 private workspaceMetadata = new Map<string, FrontendWorkspaceMetadata>();
186 private readonly runtimeStatusStore: PassiveRuntimeDeps;
187
188 constructor(runtimeStatusStore?: PassiveRuntimeDeps);
189 constructor(runtimeStatusStore?: Pick<RuntimeStatusStore, "getStatus">);
190 constructor(
191 runtimeStatusStore:
192 | PassiveRuntimeDeps
193 | Pick<RuntimeStatusStore, "getStatus"> = getRuntimeStatusStore()
194 ) {
195 this.runtimeStatusStore = {
196 getStatus: (workspaceId) => runtimeStatusStore.getStatus(workspaceId),
197 subscribeKey:
198 "subscribeKey" in runtimeStatusStore
199 ? (workspaceId, listener) => runtimeStatusStore.subscribeKey(workspaceId, listener)
200 : () => () => undefined,
201 };
202 this.refreshController = new RefreshController({
203 onRefresh: () => this.refreshAll(),
204 onRefreshError: (failure) => {
205 console.error("[PRStatusStore] refresh failed:", failure.errorMessage);
206 },
207 debounceMs: 5000,
208 refreshOnFocus: true,
209 focusDebounceMs: 1000,
210 });
211 }
212
213 setClient(client: RouterClient<AppRouter> | null): void {
214 this.client = client;
215
216 if (!client) {
217 return;
218 }
219
220 // If hooks subscribed before the client was ready, ensure we refresh once it is.
221 if (this.workspaceSubscriptionCounts.size > 0) {

Callers

nothing calls this directly

Calls 6

subscribeKeyMethod · 0.80
setMethod · 0.80
bindListenersMethod · 0.80
requestImmediateMethod · 0.80
getMethod · 0.65
deleteMethod · 0.45

Tested by

no test coverage detected