import { ScopeDBError } from "./errors.js"; import type { AppendRowsResult } from "./protocol.js"; export type AppendFailurePolicy = "stop" | "continue"; export type AppendStreamState = "open" | "closing" | "closed" | "failed"; export type AppendCircuitState = "closed" | "open" | "half-open"; export interface AppendStreamOptions { /** * Whether a failed batch stops the stream or allows later batches to continue. */ failurePolicy: Policy; } export interface AppendWaitOptions { signal?: AbortSignal; } /** * Local admission result from `sendAll()`; it does not confirm remote delivery. */ export interface AppendAdmissionResult { acceptedRows: number; } /** Delivery outcomes covered by a continue-mode `flush()` or `shutdown()`. */ export interface AppendDeliveryReport { /** * `unknown` means no covered rows are known to have committed and at least * one batch may have committed; callers must not blindly replay it. */ outcome: "ok" | "partial" | "failed" | "unknown"; acceptedRows: number; committedRows: number; failedRows: number; unknownRows: number; droppedRows: number; committedBatches: number; failedBatches: number; unknownBatches: number; retries: number; /** Wall time from requesting this barrier until every covered batch settled. */ durationMs: number; } export interface AppendStreamStats { state: AppendStreamState; circuitState: AppendCircuitState; acceptedRows: number; committedRows: number; failedRows: number; unknownRows: number; droppedRows: number; droppedByReason: Readonly<{ bufferFull: number; invalidRecord: number; recordTooLarge: number; circuitOpen: number; closed: number; }>; retries: number; pendingRows: number; pendingBytes: number; inFlightBatches: number; lastFailure?: Readonly<{ atMs: number; message: string; appendState?: "rejected" | "unknown"; }>; lastReport?: Readonly; } export interface AppendBatchFailureEvent { error: ScopeDBError; batchRows: number; batchBytes: number; outcome: "rejected" | "unknown"; action: "continuing" | "circuit-opened" | "stopped"; } export interface AppendCircuitBreakerOptions { failureThreshold: number; cooldownMs: number; } export type AppendBarrierResult = Policy extends "continue" ? AppendDeliveryReport : AppendRowsResult | null; export declare class AppendStreamBuilder { private readonly client; private readonly database; private readonly schema; private readonly table; private readonly failurePolicy; private currentBatchBytes; private currentBatchRows; private currentFlushIntervalMs; private currentChannelCapacity; private currentMaxPendingBytes; private currentMaxInFlightRequests; private currentAttemptTimeoutMs; private currentCircuitBreaker; private readonly batchFailureListeners; private currentRetry; private constructor(); /** * Target NDJSON payload size. A single row may exceed it, up to 8 MiB. * @deprecated Use `targetBatchBytes()`. */ batchBytes(batchBytes: number): this; /** Target NDJSON payload size. A single row may exceed it, up to 8 MiB. */ targetBatchBytes(targetBatchBytes: number): this; /** Maximum number of rows in one append request. */ maxBatchRows(maxBatchRows: number): this; /** * Maximum time from the first buffered row until its batch is dispatched. * @deprecated Use `flushIntervalMs()`. */ flushInterval(flushIntervalMs: number): this; /** Maximum time from the first buffered row until its batch is dispatched. */ flushIntervalMs(flushIntervalMs: number): this; channelCapacity(channelCapacity: number): this; /** @deprecated Use `maxBufferedBytes()`. */ maxPendingBytes(maxPendingBytes: number): this; maxBufferedBytes(maxBufferedBytes: number): this; /** * Maximum number of append requests in flight. Defaults to 4. * @deprecated Use `maxConcurrentBatches()`. */ maxInFlightRequests(maxInFlightRequests: number): this; /** Maximum number of append requests in flight. Defaults to 4. */ maxConcurrentBatches(maxConcurrentBatches: number): this; maxRetries(maxRetries: number): this; initialBackoff(initialBackoffMs: number): this; maxBackoff(maxBackoffMs: number): this; /** * Per-attempt HTTP timeout in milliseconds. A timeout has an unknown outcome. * @deprecated Use `attemptTimeoutMs()`. */ attemptTimeout(attemptTimeoutMs: number): this; /** Per-attempt HTTP timeout in milliseconds. */ attemptTimeoutMs(attemptTimeoutMs: number): this; /** Configure the continue-mode circuit breaker, or disable it. */ circuitBreaker(options: AppendCircuitBreakerOptions | false): this; /** * Observes rejected or ambiguous batch outcomes without affecting the worker. * Async listeners are observed but not awaited; listener failures are ignored. */ onBatchFailure(listener: (event: AppendBatchFailureEvent) => void | PromiseLike): this; build(): AppendStream; } export declare class AppendStream { private readonly config; private readonly queue; private readonly pendingBytes; private readonly task; private readonly inFlight; private readonly fatalController; private rows; private currentBytes; private batchDeadlineMs; private fatal; private accepting; private workerDone; private shutdownOperation?; private interval; private readonly lifetime; private readonly droppedByReason; private reportedDroppedRows; private pendingRowCount; private lastFailure; private lastReport; private circuitState; private circuitOpenedUntil; private consecutiveFailures; private circuitProbeDone?; private circuitProbeAdmissionClaimed; private constructor(); /** * Attempts synchronous local admission. It never waits or throws; false means * the record was invalid, the bounded buffer was full, or the stream closed. */ trySend(record: unknown): boolean; /** * Serializes and enqueues one row. Completion means accepted by the local * stream, not yet committed; use `flush()` or `shutdown()` as a commit barrier. */ send(record: unknown, options?: AppendWaitOptions): Promise; /** Consumes a sync or async iterable one row at a time with bounded backpressure. */ sendAll(records: Iterable | AsyncIterable, options?: AppendWaitOptions): Promise; /** Dispatches rows accepted before this barrier and waits for their outcomes. */ flush(options?: AppendWaitOptions): Promise>; /** Flushes all accepted rows and permanently closes the stream. */ shutdown(options?: AppendWaitOptions): Promise>; stats(): Readonly; private flushInner; private shutdownInner; private runWorker; private nextBatchTimeout; private bufferRecord; private dispatchBuffered; private appendBatch; private waitForCapacity; private waitForInFlight; private waitForCircuit; private completeBarrier; private takeBarrierOutput; private takeDeliveryReport; private ensureAccepted; private recordBatchCommitted; private recordBatchFailure; private markLocalRowsFailed; private noteRetry; private noteDrop; private recordCircuitSuccess; private recordCircuitFailure; private closeCircuit; private emitBatchFailure; private setFatal; private addCommittedContextToFatal; private releaseBufferedAsFailed; private drainQueued; private disposeCommand; private checkUsable; private checkFatal; private closedOrFatalError; private mapPendingBytesError; } //# sourceMappingURL=append-stream.d.ts.map