@@ -206,13 +206,6 @@ export function pruneStaleEntries(
|
206 | 206 | export const DEFAULT_QUOTA_SUSPENSION_TTL_MS = 30 * 60 * 1000; // 30 minutes |
207 | 207 | const QUOTA_SUSPENSION_CLEANUP_FACTOR = 2; // entries beyond N*ttl are deleted outright |
208 | 208 | |
209 | | -export interface QuotaSuspensionMaintenanceResult { |
210 | | -/** Suspensions whose state was advanced from "suspended" to "resuming" so the next attempt injects a handoff. */ |
211 | | -resumed: Array<{ sessionKey: string; laneId?: string }>; |
212 | | -/** Entries whose `quotaSuspension` field was removed entirely (already-resumed records past 2x TTL). */ |
213 | | -cleared: number; |
214 | | -} |
215 | | - |
216 | 209 | export type QuotaSuspensionEntryMaintenanceResult = { |
217 | 210 | /** Patch to apply to the entry, or null when no TTL transition is due. */ |
218 | 211 | patch: Partial<SessionEntry> | null; |
@@ -253,54 +246,6 @@ export function resolveQuotaSuspensionEntryMaintenance(params: {
|
253 | 246 | return { patch: null, cleared: false }; |
254 | 247 | } |
255 | 248 | |
256 | | -/** |
257 | | - * Two-stage TTL maintenance for `quotaSuspension` records: |
258 | | - * 1. After `ttlMs`, transition `state: "suspended" → "resuming"` so the next |
259 | | - * attempt for that session sees the resume marker and injects a handoff. |
260 | | - * 2. After `2 * ttlMs`, drop the field entirely (the record has done its job). |
261 | | - * |
262 | | - * Mutates `store` in-place. The caller is responsible for translating the |
263 | | - * returned `resumed[]` into in-process lane-concurrency restoration calls, |
264 | | - * which keeps this module free of `process/*` dependencies. |
265 | | - */ |
266 | | -export function pruneQuotaSuspensions(params: { |
267 | | -store: Record<string, SessionEntry>; |
268 | | -now: number; |
269 | | -ttlMs?: number; |
270 | | -log?: boolean; |
271 | | -}): QuotaSuspensionMaintenanceResult { |
272 | | -const ttlMs = params.ttlMs ?? DEFAULT_QUOTA_SUSPENSION_TTL_MS; |
273 | | -const resumed: Array<{ sessionKey: string; laneId?: string }> = []; |
274 | | -let cleared = 0; |
275 | | -for (const [sessionKey, entry] of Object.entries(params.store)) { |
276 | | -const result = resolveQuotaSuspensionEntryMaintenance({ |
277 | | - entry, |
278 | | -now: params.now, |
279 | | - ttlMs, |
280 | | -}); |
281 | | -if (!result.patch) { |
282 | | -continue; |
283 | | -} |
284 | | -if (result.cleared) { |
285 | | -delete entry.quotaSuspension; |
286 | | -cleared++; |
287 | | -} else if (result.patch.quotaSuspension) { |
288 | | -entry.quotaSuspension = result.patch.quotaSuspension; |
289 | | -} |
290 | | -if (result.resumed) { |
291 | | -resumed.push({ sessionKey, laneId: result.resumed.laneId }); |
292 | | -} |
293 | | -} |
294 | | -if ((resumed.length > 0 || cleared > 0) && params.log !== false) { |
295 | | -log.info("processed quota-suspension TTLs", { |
296 | | -resumed: resumed.length, |
297 | | - cleared, |
298 | | - ttlMs, |
299 | | -}); |
300 | | -} |
301 | | -return { resumed, cleared }; |
302 | | -} |
303 | | - |
304 | 249 | function getEntryUpdatedAt(entry?: SessionEntry): number { |
305 | 250 | return entry?.updatedAt ?? Number.NEGATIVE_INFINITY; |
306 | 251 | } |
|