Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 3x 5x 5x 5x 3x 3x 3x 3x 5x 5x 5x 3x 1x 3x 3x | /**
* @module parliamentary-data/mcp-retry-queue/retry-policy
* @description Backoff + cap policy for queue entries. Builds new entries
* (`createRetryQueueEntry`) and merges them into the on-disk queue with
* deduplication (`enqueueRetryEntries`).
*
* Default expiry: 7 days. Entries are keyed by `${resourceType}:${resourceId}`
* so re-enqueuing the same resource does not duplicate the row but preserves
* the original `requestedAt` / `expiresAt` and `attemptCount`.
*
* @author Hack23 AB
* @license Apache-2.0
*/
import type { MCPCoverageState } from '../../types/mcp.js';
import {
DEFAULT_MCP_RETRY_QUEUE_PATH,
MCP_RETRY_QUEUE_SCHEMA,
loadMcpRetryQueue,
saveMcpRetryQueue,
type MCPRetryQueueEntry,
type MCPRetryQueueFile,
} from './persistence.js';
const DEFAULT_EXPIRY_DAYS = 7;
export function createRetryQueueEntry(options: {
resourceType: MCPRetryQueueEntry['resourceType'];
resourceId: string;
tool: string;
coverageState: MCPCoverageState;
params: Record<string, unknown>;
docType?: string | null;
reason?: string;
requestedAt?: string;
expiresInDays?: number;
}): MCPRetryQueueEntry {
const requestedAt = options.requestedAt ?? new Date().toISOString();
const expiresAt = new Date(
new Date(requestedAt).getTime() + ((options.expiresInDays ?? DEFAULT_EXPIRY_DAYS) * 86400000),
).toISOString();
return {
resourceType: options.resourceType,
resourceId: options.resourceId,
tool: options.tool,
docType: options.docType ?? null,
coverageState: options.coverageState,
requestedAt,
expiresAt,
attemptCount: 0,
params: { ...options.params },
...(options.reason ? { reason: options.reason } : {}),
};
}
export function enqueueRetryEntries(
entries: MCPRetryQueueEntry[],
queuePath: string = DEFAULT_MCP_RETRY_QUEUE_PATH,
): MCPRetryQueueFile {
const queue = loadMcpRetryQueue(queuePath);
const deduped = new Map<string, MCPRetryQueueEntry>();
for (const existing of queue.entries) {
deduped.set(`${existing.resourceType}:${existing.resourceId}`, existing);
}
for (const entry of entries) {
const key = `${entry.resourceType}:${entry.resourceId}`;
const previous = deduped.get(key);
deduped.set(key, previous
? {
...previous,
...entry,
attemptCount: previous.attemptCount,
requestedAt: previous.requestedAt,
expiresAt: previous.expiresAt,
}
: entry);
}
const updated: MCPRetryQueueFile = {
schema: MCP_RETRY_QUEUE_SCHEMA,
updatedAt: new Date().toISOString(),
entries: [...deduped.values()].sort((a, b) => a.resourceId.localeCompare(b.resourceId)),
};
saveMcpRetryQueue(updated, queuePath);
return updated;
}
|