/** * Durable retry queue for failed child write operations (GA-1). * * When a child session write fails, the operation is recorded here and * retried with exponential backoff (1s, 2s, 4s, 8s, 16s). After 5 failed * attempts the child session is marked "degraded" and a `[Hivemind]` error * is logged. Retry records are persisted to disk under * `.hivemind/session-tracker/retry-degraded.json` for recovery after restart. * * The queue flushes on initialization and on a periodic 30-second interval * (managed by lifecycle wiring outside this module). * * @module session-tracker/persistence/retry-queue */ /** Minimal structured logger matching the harness pattern. */ interface Logger { debug: (msg: string, data?: unknown) => void; warn: (msg: string, data?: unknown) => void; error: (msg: string, data?: unknown) => void; } /** * A failed child write operation awaiting retry. */ export interface RetryRecord { /** Child session identifier. */ sessionID: string; /** Immediate parent session identifier. */ parentID: string; /** Data that was being written when the failure occurred. */ data: Record; /** Number of retry attempts already made (0 = not yet retried). */ attempt: number; /** Error message from the last failure. */ lastError?: string; /** Current status of this retry record. */ status: "pending" | "completed" | "degraded"; /** ISO 8601 timestamp when this record was created. */ createdAt: string; /** Optional write function for auto-retry (test/internal use). */ writeFn?: () => Promise; } /** * Configuration for the ChildWriteRetryQueue. */ export interface RetryQueueConfig { /** Absolute path to the project root. */ projectRoot: string; /** Optional callback invoked when a record is marked degraded. */ onDegraded?: (record: RetryRecord) => void; } /** Maximum number of retry attempts before marking a record degraded. */ export declare const MAX_RETRIES = 5; /** Exponential backoff intervals in milliseconds: 1s, 2s, 4s, 8s, 16s. */ export declare const BACKOFF_SCHEDULE_MS: number[]; /** Periodic flush interval in milliseconds (30 seconds). */ export declare const FLUSH_INTERVAL_MS = 30000; /** * Manages failed child write operations with exponential backoff retry, * persistent degraded records, and flush-on-init semantics. * * Retry records are persisted to `.hivemind/session-tracker/retry-degraded.json` * so they survive harness restarts. The queue is in-memory for active retries; * degraded records are flushed to disk. * * @example * ```typescript * const queue = new ChildWriteRetryQueue({ projectRoot: "/path/to/project" }) * * // Enqueue a failed write * queue.enqueue({ * sessionID: "ses_child_001", * parentID: "ses_parent_001", * data: { status: "active", turns: [] }, * attempt: 0, * }) * * // Flush all pending retries immediately * await queue.flush() * ``` */ export declare class ChildWriteRetryQueue { private projectRoot; private records; private log; private timers; private pendingRetries; private onDegraded?; /** * @param config - Queue configuration. * @param config.projectRoot - Absolute path to the project root. * @param config.onDegraded - Optional callback for degraded records. */ constructor(config: RetryQueueConfig); /** * Inject a structured logger. Default is no-op. * Called by the plugin composition root to wire the harness-level logger. */ setLogger(injected: Logger): void; /** * Returns the number of pending retry records. * * @returns Count of records with status "pending". */ pendingCount(): number; /** * Returns the current attempt count for a given session ID. * * @param sessionID - The child session identifier. * @returns Number of retry attempts made, or 0 if not found. */ attemptCount(sessionID: string): number; /** * Returns the current status of a retry record. * * @param sessionID - The child session identifier. * @returns Status string ("pending", "completed", "degraded"), or undefined. */ getStatus(sessionID: string): string | undefined; /** * Enqueues a failed child write operation for retry. * * The record is stored in-memory with status "pending" and a timer is * scheduled for the first retry attempt using exponential backoff. * * @param op - The failed write operation to retry. */ enqueue(op: { sessionID: string; parentID: string; data: Record; attempt: number; writeFn?: () => Promise; }): void; /** * Schedules the next retry attempt for a given session using exponential * backoff from the BACKOFF_SCHEDULE_MS array. * * @param sessionID - The child session identifier. */ private scheduleRetry; /** * Attempts a single retry for the given session. On success the record * is marked "completed". On failure the attempt counter increments and * the next retry is scheduled. After MAX_RETRIES failures the record * is marked "degraded" and persisted to disk. * * @param sessionID - The child session identifier. */ private retryOnce; /** * Flushes all pending retry records immediately, bypassing timers. * * Each pending record is processed through the retry logic. Records * without a `writeFn` are immediately marked "degraded" and persisted. * Records with a `writeFn` attempt the write and complete or degrade * based on the result. * * @returns Promise that resolves when all pending records have been processed. */ flush(): Promise; /** * Persists a degraded retry record to disk under the session tracker root. * * The file `retry-degraded.json` contains an array of all degraded records. * Uses atomic write for crash safety. * * @param record - The degraded retry record to persist. */ private persistDegradedRecord; /** * Returns all active retry records (for testing and debugging). * * @returns Array of all records currently in the queue. */ getAllRecords(): RetryRecord[]; /** * Waits for all in-flight retry operations to complete. * Useful in tests with async write functions and fake timers. * * @returns Promise that resolves when all pending retries finish. */ waitForPendingRetries(): Promise; /** * Clears all retry records and timers. Used in tests. */ clear(): void; } /** * Alias for backward compatibility with test imports. * @deprecated Use `ChildWriteRetryQueue` directly. */ export declare const RetryQueue: typeof ChildWriteRetryQueue; export {}; //# sourceMappingURL=retry-queue.d.ts.map