@durable-streams/client 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +175 -5
- package/dist/index.cjs +510 -5
- package/dist/index.d.cts +254 -1
- package/dist/index.d.ts +254 -1
- package/dist/index.js +500 -5
- package/package.json +2 -2
- package/src/constants.ts +31 -0
- package/src/idempotent-producer.ts +642 -0
- package/src/index.ts +24 -0
- package/src/sse.ts +3 -0
- package/src/stream.ts +13 -1
- package/src/types.ts +111 -0
- package/src/utils.ts +120 -0
package/dist/index.d.cts
CHANGED
|
@@ -249,6 +249,14 @@ interface StreamOptions {
|
|
|
249
249
|
* fall back to long-polling mode.
|
|
250
250
|
*/
|
|
251
251
|
sseResilience?: SSEResilienceOptions;
|
|
252
|
+
/**
|
|
253
|
+
* Whether to warn when using HTTP (not HTTPS) URLs in browser environments.
|
|
254
|
+
* HTTP limits browsers to 6 concurrent connections (HTTP/1.1), which can
|
|
255
|
+
* cause slow streams and app freezes with multiple active streams.
|
|
256
|
+
*
|
|
257
|
+
* @default true
|
|
258
|
+
*/
|
|
259
|
+
warnOnHttp?: boolean;
|
|
252
260
|
}
|
|
253
261
|
/**
|
|
254
262
|
* Options for SSE connection resilience.
|
|
@@ -374,6 +382,14 @@ interface StreamHandleOptions {
|
|
|
374
382
|
* @default true
|
|
375
383
|
*/
|
|
376
384
|
batching?: boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Whether to warn when using HTTP (not HTTPS) URLs in browser environments.
|
|
387
|
+
* HTTP limits browsers to 6 concurrent connections (HTTP/1.1), which can
|
|
388
|
+
* cause slow streams and app freezes with multiple active streams.
|
|
389
|
+
*
|
|
390
|
+
* @default true
|
|
391
|
+
*/
|
|
392
|
+
warnOnHttp?: boolean;
|
|
377
393
|
}
|
|
378
394
|
/**
|
|
379
395
|
* Options for creating a new stream.
|
|
@@ -420,6 +436,23 @@ interface AppendOptions {
|
|
|
420
436
|
* AbortSignal for this operation.
|
|
421
437
|
*/
|
|
422
438
|
signal?: AbortSignal;
|
|
439
|
+
/**
|
|
440
|
+
* Producer ID for idempotent writes.
|
|
441
|
+
* Client-supplied stable identifier (e.g., "order-service-1").
|
|
442
|
+
* Must be provided together with producerEpoch and producerSeq.
|
|
443
|
+
*/
|
|
444
|
+
producerId?: string;
|
|
445
|
+
/**
|
|
446
|
+
* Producer epoch for idempotent writes.
|
|
447
|
+
* Client-declared, server-validated monotonically increasing.
|
|
448
|
+
* Increment on producer restart.
|
|
449
|
+
*/
|
|
450
|
+
producerEpoch?: number;
|
|
451
|
+
/**
|
|
452
|
+
* Producer sequence for idempotent writes.
|
|
453
|
+
* Monotonically increasing per epoch, per-batch.
|
|
454
|
+
*/
|
|
455
|
+
producerSeq?: number;
|
|
423
456
|
}
|
|
424
457
|
/**
|
|
425
458
|
* Legacy live mode type (internal use only).
|
|
@@ -682,6 +715,65 @@ interface StreamResponse<TJson = unknown> {
|
|
|
682
715
|
* - terminal error.
|
|
683
716
|
*/
|
|
684
717
|
readonly closed: Promise<void>;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Options for creating an IdempotentProducer.
|
|
721
|
+
*/
|
|
722
|
+
interface IdempotentProducerOptions {
|
|
723
|
+
/**
|
|
724
|
+
* Starting epoch (default: 0).
|
|
725
|
+
* Increment this on producer restart.
|
|
726
|
+
*/
|
|
727
|
+
epoch?: number;
|
|
728
|
+
/**
|
|
729
|
+
* On 403 Forbidden (stale epoch), automatically retry with epoch+1.
|
|
730
|
+
* Useful for serverless/ephemeral producers.
|
|
731
|
+
* @default false
|
|
732
|
+
*/
|
|
733
|
+
autoClaim?: boolean;
|
|
734
|
+
/**
|
|
735
|
+
* Maximum bytes before sending a batch.
|
|
736
|
+
* @default 1048576 (1MB)
|
|
737
|
+
*/
|
|
738
|
+
maxBatchBytes?: number;
|
|
739
|
+
/**
|
|
740
|
+
* Maximum time to wait for more messages before sending batch (ms).
|
|
741
|
+
* @default 5
|
|
742
|
+
*/
|
|
743
|
+
lingerMs?: number;
|
|
744
|
+
/**
|
|
745
|
+
* Maximum number of concurrent batches in flight.
|
|
746
|
+
* Higher values improve throughput at the cost of more memory.
|
|
747
|
+
* @default 5
|
|
748
|
+
*/
|
|
749
|
+
maxInFlight?: number;
|
|
750
|
+
/**
|
|
751
|
+
* Custom fetch implementation.
|
|
752
|
+
*/
|
|
753
|
+
fetch?: typeof globalThis.fetch;
|
|
754
|
+
/**
|
|
755
|
+
* AbortSignal for the producer lifecycle.
|
|
756
|
+
*/
|
|
757
|
+
signal?: AbortSignal;
|
|
758
|
+
/**
|
|
759
|
+
* Callback for batch errors in fire-and-forget mode.
|
|
760
|
+
* Since append() returns immediately, errors are reported via this callback.
|
|
761
|
+
* @param error - The error that occurred
|
|
762
|
+
*/
|
|
763
|
+
onError?: (error: Error) => void;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Result of an append operation from IdempotentProducer.
|
|
767
|
+
*/
|
|
768
|
+
interface IdempotentAppendResult {
|
|
769
|
+
/**
|
|
770
|
+
* The offset after this message was appended.
|
|
771
|
+
*/
|
|
772
|
+
offset: Offset;
|
|
773
|
+
/**
|
|
774
|
+
* Whether this was a duplicate (idempotent success).
|
|
775
|
+
*/
|
|
776
|
+
duplicate: boolean;
|
|
685
777
|
} //#endregion
|
|
686
778
|
//#region src/stream-api.d.ts
|
|
687
779
|
/**
|
|
@@ -944,6 +1036,145 @@ declare class DurableStream {
|
|
|
944
1036
|
stream<TJson = unknown>(options?: Omit<StreamOptions, `url`>): Promise<StreamResponse<TJson>>;
|
|
945
1037
|
}
|
|
946
1038
|
|
|
1039
|
+
//#endregion
|
|
1040
|
+
//#region src/utils.d.ts
|
|
1041
|
+
/**
|
|
1042
|
+
* Warn if using HTTP (not HTTPS) URL in a browser environment.
|
|
1043
|
+
* HTTP typically limits browsers to ~6 concurrent connections per origin under HTTP/1.1,
|
|
1044
|
+
* which can cause slow streams and app freezes with multiple active streams.
|
|
1045
|
+
*
|
|
1046
|
+
* Features:
|
|
1047
|
+
* - Warns only once per origin to prevent log spam
|
|
1048
|
+
* - Handles relative URLs by resolving against window.location.href
|
|
1049
|
+
* - Safe to call in Node.js environments (no-op)
|
|
1050
|
+
* - Skips warning during tests (NODE_ENV=test)
|
|
1051
|
+
*/
|
|
1052
|
+
declare function warnIfUsingHttpInBrowser(url: string | URL, warnOnHttp?: boolean): void;
|
|
1053
|
+
/**
|
|
1054
|
+
* Reset the HTTP warning state. Only exported for testing purposes.
|
|
1055
|
+
* @internal
|
|
1056
|
+
*/
|
|
1057
|
+
declare function _resetHttpWarningForTesting(): void;
|
|
1058
|
+
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region src/idempotent-producer.d.ts
|
|
1061
|
+
/**
|
|
1062
|
+
* Error thrown when a producer's epoch is stale (zombie fencing).
|
|
1063
|
+
*/
|
|
1064
|
+
declare class StaleEpochError extends Error {
|
|
1065
|
+
/**
|
|
1066
|
+
* The current epoch on the server.
|
|
1067
|
+
*/
|
|
1068
|
+
readonly currentEpoch: number;
|
|
1069
|
+
constructor(currentEpoch: number);
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Error thrown when an unrecoverable sequence gap is detected.
|
|
1073
|
+
*
|
|
1074
|
+
* With maxInFlight > 1, HTTP requests can arrive out of order at the server,
|
|
1075
|
+
* causing temporary 409 responses. The client automatically handles these
|
|
1076
|
+
* by waiting for earlier sequences to complete, then retrying.
|
|
1077
|
+
*
|
|
1078
|
+
* This error is only thrown when the gap cannot be resolved (e.g., the
|
|
1079
|
+
* expected sequence is >= our sequence, indicating a true protocol violation).
|
|
1080
|
+
*/
|
|
1081
|
+
declare class SequenceGapError extends Error {
|
|
1082
|
+
readonly expectedSeq: number;
|
|
1083
|
+
readonly receivedSeq: number;
|
|
1084
|
+
constructor(expectedSeq: number, receivedSeq: number);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* An idempotent producer for exactly-once writes to a durable stream.
|
|
1088
|
+
*
|
|
1089
|
+
* Features:
|
|
1090
|
+
* - Fire-and-forget: append() returns immediately, batches in background
|
|
1091
|
+
* - Exactly-once: server deduplicates using (producerId, epoch, seq)
|
|
1092
|
+
* - Batching: multiple appends batched into single HTTP request
|
|
1093
|
+
* - Pipelining: up to maxInFlight concurrent batches
|
|
1094
|
+
* - Zombie fencing: stale producers rejected via epoch validation
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* ```typescript
|
|
1098
|
+
* const stream = new DurableStream({ url: "https://..." });
|
|
1099
|
+
* const producer = new IdempotentProducer(stream, "order-service-1", {
|
|
1100
|
+
* epoch: 0,
|
|
1101
|
+
* autoClaim: true,
|
|
1102
|
+
* });
|
|
1103
|
+
*
|
|
1104
|
+
* // Fire-and-forget writes (synchronous, returns immediately)
|
|
1105
|
+
* producer.append("message 1");
|
|
1106
|
+
* producer.append("message 2");
|
|
1107
|
+
*
|
|
1108
|
+
* // Ensure all messages are delivered before shutdown
|
|
1109
|
+
* await producer.flush();
|
|
1110
|
+
* await producer.close();
|
|
1111
|
+
* ```
|
|
1112
|
+
*/
|
|
1113
|
+
declare class IdempotentProducer {
|
|
1114
|
+
#private;
|
|
1115
|
+
/**
|
|
1116
|
+
* Create an idempotent producer for a stream.
|
|
1117
|
+
*
|
|
1118
|
+
* @param stream - The DurableStream to write to
|
|
1119
|
+
* @param producerId - Stable identifier for this producer (e.g., "order-service-1")
|
|
1120
|
+
* @param opts - Producer options
|
|
1121
|
+
*/
|
|
1122
|
+
constructor(stream: DurableStream, producerId: string, opts?: IdempotentProducerOptions);
|
|
1123
|
+
/**
|
|
1124
|
+
* Append data to the stream.
|
|
1125
|
+
*
|
|
1126
|
+
* This is fire-and-forget: returns immediately after adding to the batch.
|
|
1127
|
+
* The message is batched and sent when:
|
|
1128
|
+
* - maxBatchBytes is reached
|
|
1129
|
+
* - lingerMs elapses
|
|
1130
|
+
* - flush() is called
|
|
1131
|
+
*
|
|
1132
|
+
* Errors are reported via onError callback if configured. Use flush() to
|
|
1133
|
+
* wait for all pending messages to be sent.
|
|
1134
|
+
*
|
|
1135
|
+
* For JSON streams, pass native objects (which will be serialized internally).
|
|
1136
|
+
* For byte streams, pass string or Uint8Array.
|
|
1137
|
+
*
|
|
1138
|
+
* @param body - Data to append (object for JSON streams, string or Uint8Array for byte streams)
|
|
1139
|
+
*/
|
|
1140
|
+
append(body: Uint8Array | string | unknown): void;
|
|
1141
|
+
/**
|
|
1142
|
+
* Send any pending batch immediately and wait for all in-flight batches.
|
|
1143
|
+
*
|
|
1144
|
+
* Call this before shutdown to ensure all messages are delivered.
|
|
1145
|
+
*/
|
|
1146
|
+
flush(): Promise<void>;
|
|
1147
|
+
/**
|
|
1148
|
+
* Flush pending messages and close the producer.
|
|
1149
|
+
*
|
|
1150
|
+
* After calling close(), further append() calls will throw.
|
|
1151
|
+
*/
|
|
1152
|
+
close(): Promise<void>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Increment epoch and reset sequence.
|
|
1155
|
+
*
|
|
1156
|
+
* Call this when restarting the producer to establish a new session.
|
|
1157
|
+
* Flushes any pending messages first.
|
|
1158
|
+
*/
|
|
1159
|
+
restart(): Promise<void>;
|
|
1160
|
+
/**
|
|
1161
|
+
* Current epoch for this producer.
|
|
1162
|
+
*/
|
|
1163
|
+
get epoch(): number;
|
|
1164
|
+
/**
|
|
1165
|
+
* Next sequence number to be assigned.
|
|
1166
|
+
*/
|
|
1167
|
+
get nextSeq(): number;
|
|
1168
|
+
/**
|
|
1169
|
+
* Number of messages in the current pending batch.
|
|
1170
|
+
*/
|
|
1171
|
+
get pendingCount(): number;
|
|
1172
|
+
/**
|
|
1173
|
+
* Number of batches currently in flight.
|
|
1174
|
+
*/
|
|
1175
|
+
get inFlightCount(): number;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
947
1178
|
//#endregion
|
|
948
1179
|
//#region src/error.d.ts
|
|
949
1180
|
/**
|
|
@@ -1041,6 +1272,28 @@ declare const STREAM_TTL_HEADER = "Stream-TTL";
|
|
|
1041
1272
|
*/
|
|
1042
1273
|
declare const STREAM_EXPIRES_AT_HEADER = "Stream-Expires-At";
|
|
1043
1274
|
/**
|
|
1275
|
+
* Request header for producer ID (client-supplied stable identifier).
|
|
1276
|
+
*/
|
|
1277
|
+
declare const PRODUCER_ID_HEADER = "Producer-Id";
|
|
1278
|
+
/**
|
|
1279
|
+
* Request/response header for producer epoch.
|
|
1280
|
+
* Client-declared, server-validated monotonically increasing.
|
|
1281
|
+
*/
|
|
1282
|
+
declare const PRODUCER_EPOCH_HEADER = "Producer-Epoch";
|
|
1283
|
+
/**
|
|
1284
|
+
* Request header for producer sequence number.
|
|
1285
|
+
* Monotonically increasing per epoch, per-batch (not per-message).
|
|
1286
|
+
*/
|
|
1287
|
+
declare const PRODUCER_SEQ_HEADER = "Producer-Seq";
|
|
1288
|
+
/**
|
|
1289
|
+
* Response header indicating expected sequence number on 409 Conflict.
|
|
1290
|
+
*/
|
|
1291
|
+
declare const PRODUCER_EXPECTED_SEQ_HEADER = "Producer-Expected-Seq";
|
|
1292
|
+
/**
|
|
1293
|
+
* Response header indicating received sequence number on 409 Conflict.
|
|
1294
|
+
*/
|
|
1295
|
+
declare const PRODUCER_RECEIVED_SEQ_HEADER = "Producer-Received-Seq";
|
|
1296
|
+
/**
|
|
1044
1297
|
* Query parameter for starting offset.
|
|
1045
1298
|
*/
|
|
1046
1299
|
declare const OFFSET_QUERY_PARAM = "offset";
|
|
@@ -1069,4 +1322,4 @@ declare const SSE_COMPATIBLE_CONTENT_TYPES: ReadonlyArray<string>;
|
|
|
1069
1322
|
declare const DURABLE_STREAM_PROTOCOL_QUERY_PARAMS: Array<string>;
|
|
1070
1323
|
|
|
1071
1324
|
//#endregion
|
|
1072
|
-
export { AppendOptions, BackoffDefaults, BackoffOptions, ByteChunk, CURSOR_QUERY_PARAM, CreateOptions, DURABLE_STREAM_PROTOCOL_QUERY_PARAMS, DurableStream, DurableStreamError, DurableStreamErrorCode, DurableStreamOptions, FetchBackoffAbortError, FetchError, HeadResult, HeadersRecord, InvalidSignalError, JsonBatch, JsonBatchMeta, LIVE_QUERY_PARAM, LegacyLiveMode, LiveMode, MaybePromise, MissingStreamUrlError, OFFSET_QUERY_PARAM, Offset, ParamsRecord, ReadOptions, ReadableStreamAsyncIterable, RetryOpts, SSEResilienceOptions, SSE_COMPATIBLE_CONTENT_TYPES, STREAM_CURSOR_HEADER, STREAM_EXPIRES_AT_HEADER, STREAM_OFFSET_HEADER, STREAM_SEQ_HEADER, STREAM_TTL_HEADER, STREAM_UP_TO_DATE_HEADER, StreamErrorHandler, StreamHandleOptions, StreamOptions, StreamResponse, TextChunk, asAsyncIterableReadableStream, createFetchWithBackoff, createFetchWithConsumedBody, stream };
|
|
1325
|
+
export { AppendOptions, BackoffDefaults, BackoffOptions, ByteChunk, CURSOR_QUERY_PARAM, CreateOptions, DURABLE_STREAM_PROTOCOL_QUERY_PARAMS, DurableStream, DurableStreamError, DurableStreamErrorCode, DurableStreamOptions, FetchBackoffAbortError, FetchError, HeadResult, HeadersRecord, IdempotentAppendResult, IdempotentProducer, IdempotentProducerOptions, InvalidSignalError, JsonBatch, JsonBatchMeta, LIVE_QUERY_PARAM, LegacyLiveMode, LiveMode, MaybePromise, MissingStreamUrlError, OFFSET_QUERY_PARAM, Offset, PRODUCER_EPOCH_HEADER, PRODUCER_EXPECTED_SEQ_HEADER, PRODUCER_ID_HEADER, PRODUCER_RECEIVED_SEQ_HEADER, PRODUCER_SEQ_HEADER, ParamsRecord, ReadOptions, ReadableStreamAsyncIterable, RetryOpts, SSEResilienceOptions, SSE_COMPATIBLE_CONTENT_TYPES, STREAM_CURSOR_HEADER, STREAM_EXPIRES_AT_HEADER, STREAM_OFFSET_HEADER, STREAM_SEQ_HEADER, STREAM_TTL_HEADER, STREAM_UP_TO_DATE_HEADER, SequenceGapError, StaleEpochError, StreamErrorHandler, StreamHandleOptions, StreamOptions, StreamResponse, TextChunk, _resetHttpWarningForTesting, asAsyncIterableReadableStream, createFetchWithBackoff, createFetchWithConsumedBody, stream, warnIfUsingHttpInBrowser };
|
package/dist/index.d.ts
CHANGED
|
@@ -249,6 +249,14 @@ interface StreamOptions {
|
|
|
249
249
|
* fall back to long-polling mode.
|
|
250
250
|
*/
|
|
251
251
|
sseResilience?: SSEResilienceOptions;
|
|
252
|
+
/**
|
|
253
|
+
* Whether to warn when using HTTP (not HTTPS) URLs in browser environments.
|
|
254
|
+
* HTTP limits browsers to 6 concurrent connections (HTTP/1.1), which can
|
|
255
|
+
* cause slow streams and app freezes with multiple active streams.
|
|
256
|
+
*
|
|
257
|
+
* @default true
|
|
258
|
+
*/
|
|
259
|
+
warnOnHttp?: boolean;
|
|
252
260
|
}
|
|
253
261
|
/**
|
|
254
262
|
* Options for SSE connection resilience.
|
|
@@ -374,6 +382,14 @@ interface StreamHandleOptions {
|
|
|
374
382
|
* @default true
|
|
375
383
|
*/
|
|
376
384
|
batching?: boolean;
|
|
385
|
+
/**
|
|
386
|
+
* Whether to warn when using HTTP (not HTTPS) URLs in browser environments.
|
|
387
|
+
* HTTP limits browsers to 6 concurrent connections (HTTP/1.1), which can
|
|
388
|
+
* cause slow streams and app freezes with multiple active streams.
|
|
389
|
+
*
|
|
390
|
+
* @default true
|
|
391
|
+
*/
|
|
392
|
+
warnOnHttp?: boolean;
|
|
377
393
|
}
|
|
378
394
|
/**
|
|
379
395
|
* Options for creating a new stream.
|
|
@@ -420,6 +436,23 @@ interface AppendOptions {
|
|
|
420
436
|
* AbortSignal for this operation.
|
|
421
437
|
*/
|
|
422
438
|
signal?: AbortSignal;
|
|
439
|
+
/**
|
|
440
|
+
* Producer ID for idempotent writes.
|
|
441
|
+
* Client-supplied stable identifier (e.g., "order-service-1").
|
|
442
|
+
* Must be provided together with producerEpoch and producerSeq.
|
|
443
|
+
*/
|
|
444
|
+
producerId?: string;
|
|
445
|
+
/**
|
|
446
|
+
* Producer epoch for idempotent writes.
|
|
447
|
+
* Client-declared, server-validated monotonically increasing.
|
|
448
|
+
* Increment on producer restart.
|
|
449
|
+
*/
|
|
450
|
+
producerEpoch?: number;
|
|
451
|
+
/**
|
|
452
|
+
* Producer sequence for idempotent writes.
|
|
453
|
+
* Monotonically increasing per epoch, per-batch.
|
|
454
|
+
*/
|
|
455
|
+
producerSeq?: number;
|
|
423
456
|
}
|
|
424
457
|
/**
|
|
425
458
|
* Legacy live mode type (internal use only).
|
|
@@ -682,6 +715,65 @@ interface StreamResponse<TJson = unknown> {
|
|
|
682
715
|
* - terminal error.
|
|
683
716
|
*/
|
|
684
717
|
readonly closed: Promise<void>;
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Options for creating an IdempotentProducer.
|
|
721
|
+
*/
|
|
722
|
+
interface IdempotentProducerOptions {
|
|
723
|
+
/**
|
|
724
|
+
* Starting epoch (default: 0).
|
|
725
|
+
* Increment this on producer restart.
|
|
726
|
+
*/
|
|
727
|
+
epoch?: number;
|
|
728
|
+
/**
|
|
729
|
+
* On 403 Forbidden (stale epoch), automatically retry with epoch+1.
|
|
730
|
+
* Useful for serverless/ephemeral producers.
|
|
731
|
+
* @default false
|
|
732
|
+
*/
|
|
733
|
+
autoClaim?: boolean;
|
|
734
|
+
/**
|
|
735
|
+
* Maximum bytes before sending a batch.
|
|
736
|
+
* @default 1048576 (1MB)
|
|
737
|
+
*/
|
|
738
|
+
maxBatchBytes?: number;
|
|
739
|
+
/**
|
|
740
|
+
* Maximum time to wait for more messages before sending batch (ms).
|
|
741
|
+
* @default 5
|
|
742
|
+
*/
|
|
743
|
+
lingerMs?: number;
|
|
744
|
+
/**
|
|
745
|
+
* Maximum number of concurrent batches in flight.
|
|
746
|
+
* Higher values improve throughput at the cost of more memory.
|
|
747
|
+
* @default 5
|
|
748
|
+
*/
|
|
749
|
+
maxInFlight?: number;
|
|
750
|
+
/**
|
|
751
|
+
* Custom fetch implementation.
|
|
752
|
+
*/
|
|
753
|
+
fetch?: typeof globalThis.fetch;
|
|
754
|
+
/**
|
|
755
|
+
* AbortSignal for the producer lifecycle.
|
|
756
|
+
*/
|
|
757
|
+
signal?: AbortSignal;
|
|
758
|
+
/**
|
|
759
|
+
* Callback for batch errors in fire-and-forget mode.
|
|
760
|
+
* Since append() returns immediately, errors are reported via this callback.
|
|
761
|
+
* @param error - The error that occurred
|
|
762
|
+
*/
|
|
763
|
+
onError?: (error: Error) => void;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Result of an append operation from IdempotentProducer.
|
|
767
|
+
*/
|
|
768
|
+
interface IdempotentAppendResult {
|
|
769
|
+
/**
|
|
770
|
+
* The offset after this message was appended.
|
|
771
|
+
*/
|
|
772
|
+
offset: Offset;
|
|
773
|
+
/**
|
|
774
|
+
* Whether this was a duplicate (idempotent success).
|
|
775
|
+
*/
|
|
776
|
+
duplicate: boolean;
|
|
685
777
|
} //#endregion
|
|
686
778
|
//#region src/stream-api.d.ts
|
|
687
779
|
/**
|
|
@@ -944,6 +1036,145 @@ declare class DurableStream {
|
|
|
944
1036
|
stream<TJson = unknown>(options?: Omit<StreamOptions, `url`>): Promise<StreamResponse<TJson>>;
|
|
945
1037
|
}
|
|
946
1038
|
|
|
1039
|
+
//#endregion
|
|
1040
|
+
//#region src/utils.d.ts
|
|
1041
|
+
/**
|
|
1042
|
+
* Warn if using HTTP (not HTTPS) URL in a browser environment.
|
|
1043
|
+
* HTTP typically limits browsers to ~6 concurrent connections per origin under HTTP/1.1,
|
|
1044
|
+
* which can cause slow streams and app freezes with multiple active streams.
|
|
1045
|
+
*
|
|
1046
|
+
* Features:
|
|
1047
|
+
* - Warns only once per origin to prevent log spam
|
|
1048
|
+
* - Handles relative URLs by resolving against window.location.href
|
|
1049
|
+
* - Safe to call in Node.js environments (no-op)
|
|
1050
|
+
* - Skips warning during tests (NODE_ENV=test)
|
|
1051
|
+
*/
|
|
1052
|
+
declare function warnIfUsingHttpInBrowser(url: string | URL, warnOnHttp?: boolean): void;
|
|
1053
|
+
/**
|
|
1054
|
+
* Reset the HTTP warning state. Only exported for testing purposes.
|
|
1055
|
+
* @internal
|
|
1056
|
+
*/
|
|
1057
|
+
declare function _resetHttpWarningForTesting(): void;
|
|
1058
|
+
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region src/idempotent-producer.d.ts
|
|
1061
|
+
/**
|
|
1062
|
+
* Error thrown when a producer's epoch is stale (zombie fencing).
|
|
1063
|
+
*/
|
|
1064
|
+
declare class StaleEpochError extends Error {
|
|
1065
|
+
/**
|
|
1066
|
+
* The current epoch on the server.
|
|
1067
|
+
*/
|
|
1068
|
+
readonly currentEpoch: number;
|
|
1069
|
+
constructor(currentEpoch: number);
|
|
1070
|
+
}
|
|
1071
|
+
/**
|
|
1072
|
+
* Error thrown when an unrecoverable sequence gap is detected.
|
|
1073
|
+
*
|
|
1074
|
+
* With maxInFlight > 1, HTTP requests can arrive out of order at the server,
|
|
1075
|
+
* causing temporary 409 responses. The client automatically handles these
|
|
1076
|
+
* by waiting for earlier sequences to complete, then retrying.
|
|
1077
|
+
*
|
|
1078
|
+
* This error is only thrown when the gap cannot be resolved (e.g., the
|
|
1079
|
+
* expected sequence is >= our sequence, indicating a true protocol violation).
|
|
1080
|
+
*/
|
|
1081
|
+
declare class SequenceGapError extends Error {
|
|
1082
|
+
readonly expectedSeq: number;
|
|
1083
|
+
readonly receivedSeq: number;
|
|
1084
|
+
constructor(expectedSeq: number, receivedSeq: number);
|
|
1085
|
+
}
|
|
1086
|
+
/**
|
|
1087
|
+
* An idempotent producer for exactly-once writes to a durable stream.
|
|
1088
|
+
*
|
|
1089
|
+
* Features:
|
|
1090
|
+
* - Fire-and-forget: append() returns immediately, batches in background
|
|
1091
|
+
* - Exactly-once: server deduplicates using (producerId, epoch, seq)
|
|
1092
|
+
* - Batching: multiple appends batched into single HTTP request
|
|
1093
|
+
* - Pipelining: up to maxInFlight concurrent batches
|
|
1094
|
+
* - Zombie fencing: stale producers rejected via epoch validation
|
|
1095
|
+
*
|
|
1096
|
+
* @example
|
|
1097
|
+
* ```typescript
|
|
1098
|
+
* const stream = new DurableStream({ url: "https://..." });
|
|
1099
|
+
* const producer = new IdempotentProducer(stream, "order-service-1", {
|
|
1100
|
+
* epoch: 0,
|
|
1101
|
+
* autoClaim: true,
|
|
1102
|
+
* });
|
|
1103
|
+
*
|
|
1104
|
+
* // Fire-and-forget writes (synchronous, returns immediately)
|
|
1105
|
+
* producer.append("message 1");
|
|
1106
|
+
* producer.append("message 2");
|
|
1107
|
+
*
|
|
1108
|
+
* // Ensure all messages are delivered before shutdown
|
|
1109
|
+
* await producer.flush();
|
|
1110
|
+
* await producer.close();
|
|
1111
|
+
* ```
|
|
1112
|
+
*/
|
|
1113
|
+
declare class IdempotentProducer {
|
|
1114
|
+
#private;
|
|
1115
|
+
/**
|
|
1116
|
+
* Create an idempotent producer for a stream.
|
|
1117
|
+
*
|
|
1118
|
+
* @param stream - The DurableStream to write to
|
|
1119
|
+
* @param producerId - Stable identifier for this producer (e.g., "order-service-1")
|
|
1120
|
+
* @param opts - Producer options
|
|
1121
|
+
*/
|
|
1122
|
+
constructor(stream: DurableStream, producerId: string, opts?: IdempotentProducerOptions);
|
|
1123
|
+
/**
|
|
1124
|
+
* Append data to the stream.
|
|
1125
|
+
*
|
|
1126
|
+
* This is fire-and-forget: returns immediately after adding to the batch.
|
|
1127
|
+
* The message is batched and sent when:
|
|
1128
|
+
* - maxBatchBytes is reached
|
|
1129
|
+
* - lingerMs elapses
|
|
1130
|
+
* - flush() is called
|
|
1131
|
+
*
|
|
1132
|
+
* Errors are reported via onError callback if configured. Use flush() to
|
|
1133
|
+
* wait for all pending messages to be sent.
|
|
1134
|
+
*
|
|
1135
|
+
* For JSON streams, pass native objects (which will be serialized internally).
|
|
1136
|
+
* For byte streams, pass string or Uint8Array.
|
|
1137
|
+
*
|
|
1138
|
+
* @param body - Data to append (object for JSON streams, string or Uint8Array for byte streams)
|
|
1139
|
+
*/
|
|
1140
|
+
append(body: Uint8Array | string | unknown): void;
|
|
1141
|
+
/**
|
|
1142
|
+
* Send any pending batch immediately and wait for all in-flight batches.
|
|
1143
|
+
*
|
|
1144
|
+
* Call this before shutdown to ensure all messages are delivered.
|
|
1145
|
+
*/
|
|
1146
|
+
flush(): Promise<void>;
|
|
1147
|
+
/**
|
|
1148
|
+
* Flush pending messages and close the producer.
|
|
1149
|
+
*
|
|
1150
|
+
* After calling close(), further append() calls will throw.
|
|
1151
|
+
*/
|
|
1152
|
+
close(): Promise<void>;
|
|
1153
|
+
/**
|
|
1154
|
+
* Increment epoch and reset sequence.
|
|
1155
|
+
*
|
|
1156
|
+
* Call this when restarting the producer to establish a new session.
|
|
1157
|
+
* Flushes any pending messages first.
|
|
1158
|
+
*/
|
|
1159
|
+
restart(): Promise<void>;
|
|
1160
|
+
/**
|
|
1161
|
+
* Current epoch for this producer.
|
|
1162
|
+
*/
|
|
1163
|
+
get epoch(): number;
|
|
1164
|
+
/**
|
|
1165
|
+
* Next sequence number to be assigned.
|
|
1166
|
+
*/
|
|
1167
|
+
get nextSeq(): number;
|
|
1168
|
+
/**
|
|
1169
|
+
* Number of messages in the current pending batch.
|
|
1170
|
+
*/
|
|
1171
|
+
get pendingCount(): number;
|
|
1172
|
+
/**
|
|
1173
|
+
* Number of batches currently in flight.
|
|
1174
|
+
*/
|
|
1175
|
+
get inFlightCount(): number;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
947
1178
|
//#endregion
|
|
948
1179
|
//#region src/error.d.ts
|
|
949
1180
|
/**
|
|
@@ -1041,6 +1272,28 @@ declare const STREAM_TTL_HEADER = "Stream-TTL";
|
|
|
1041
1272
|
*/
|
|
1042
1273
|
declare const STREAM_EXPIRES_AT_HEADER = "Stream-Expires-At";
|
|
1043
1274
|
/**
|
|
1275
|
+
* Request header for producer ID (client-supplied stable identifier).
|
|
1276
|
+
*/
|
|
1277
|
+
declare const PRODUCER_ID_HEADER = "Producer-Id";
|
|
1278
|
+
/**
|
|
1279
|
+
* Request/response header for producer epoch.
|
|
1280
|
+
* Client-declared, server-validated monotonically increasing.
|
|
1281
|
+
*/
|
|
1282
|
+
declare const PRODUCER_EPOCH_HEADER = "Producer-Epoch";
|
|
1283
|
+
/**
|
|
1284
|
+
* Request header for producer sequence number.
|
|
1285
|
+
* Monotonically increasing per epoch, per-batch (not per-message).
|
|
1286
|
+
*/
|
|
1287
|
+
declare const PRODUCER_SEQ_HEADER = "Producer-Seq";
|
|
1288
|
+
/**
|
|
1289
|
+
* Response header indicating expected sequence number on 409 Conflict.
|
|
1290
|
+
*/
|
|
1291
|
+
declare const PRODUCER_EXPECTED_SEQ_HEADER = "Producer-Expected-Seq";
|
|
1292
|
+
/**
|
|
1293
|
+
* Response header indicating received sequence number on 409 Conflict.
|
|
1294
|
+
*/
|
|
1295
|
+
declare const PRODUCER_RECEIVED_SEQ_HEADER = "Producer-Received-Seq";
|
|
1296
|
+
/**
|
|
1044
1297
|
* Query parameter for starting offset.
|
|
1045
1298
|
*/
|
|
1046
1299
|
declare const OFFSET_QUERY_PARAM = "offset";
|
|
@@ -1069,4 +1322,4 @@ declare const SSE_COMPATIBLE_CONTENT_TYPES: ReadonlyArray<string>;
|
|
|
1069
1322
|
declare const DURABLE_STREAM_PROTOCOL_QUERY_PARAMS: Array<string>;
|
|
1070
1323
|
|
|
1071
1324
|
//#endregion
|
|
1072
|
-
export { AppendOptions, BackoffDefaults, BackoffOptions, ByteChunk, CURSOR_QUERY_PARAM, CreateOptions, DURABLE_STREAM_PROTOCOL_QUERY_PARAMS, DurableStream, DurableStreamError, DurableStreamErrorCode, DurableStreamOptions, FetchBackoffAbortError, FetchError, HeadResult, HeadersRecord, InvalidSignalError, JsonBatch, JsonBatchMeta, LIVE_QUERY_PARAM, LegacyLiveMode, LiveMode, MaybePromise, MissingStreamUrlError, OFFSET_QUERY_PARAM, Offset, ParamsRecord, ReadOptions, ReadableStreamAsyncIterable, RetryOpts, SSEResilienceOptions, SSE_COMPATIBLE_CONTENT_TYPES, STREAM_CURSOR_HEADER, STREAM_EXPIRES_AT_HEADER, STREAM_OFFSET_HEADER, STREAM_SEQ_HEADER, STREAM_TTL_HEADER, STREAM_UP_TO_DATE_HEADER, StreamErrorHandler, StreamHandleOptions, StreamOptions, StreamResponse, TextChunk, asAsyncIterableReadableStream, createFetchWithBackoff, createFetchWithConsumedBody, stream };
|
|
1325
|
+
export { AppendOptions, BackoffDefaults, BackoffOptions, ByteChunk, CURSOR_QUERY_PARAM, CreateOptions, DURABLE_STREAM_PROTOCOL_QUERY_PARAMS, DurableStream, DurableStreamError, DurableStreamErrorCode, DurableStreamOptions, FetchBackoffAbortError, FetchError, HeadResult, HeadersRecord, IdempotentAppendResult, IdempotentProducer, IdempotentProducerOptions, InvalidSignalError, JsonBatch, JsonBatchMeta, LIVE_QUERY_PARAM, LegacyLiveMode, LiveMode, MaybePromise, MissingStreamUrlError, OFFSET_QUERY_PARAM, Offset, PRODUCER_EPOCH_HEADER, PRODUCER_EXPECTED_SEQ_HEADER, PRODUCER_ID_HEADER, PRODUCER_RECEIVED_SEQ_HEADER, PRODUCER_SEQ_HEADER, ParamsRecord, ReadOptions, ReadableStreamAsyncIterable, RetryOpts, SSEResilienceOptions, SSE_COMPATIBLE_CONTENT_TYPES, STREAM_CURSOR_HEADER, STREAM_EXPIRES_AT_HEADER, STREAM_OFFSET_HEADER, STREAM_SEQ_HEADER, STREAM_TTL_HEADER, STREAM_UP_TO_DATE_HEADER, SequenceGapError, StaleEpochError, StreamErrorHandler, StreamHandleOptions, StreamOptions, StreamResponse, TextChunk, _resetHttpWarningForTesting, asAsyncIterableReadableStream, createFetchWithBackoff, createFetchWithConsumedBody, stream, warnIfUsingHttpInBrowser };
|