@ferricstore/ferricstore 0.1.7 → 0.3.0
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 +35 -6
- package/dist/index.cjs +1379 -667
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -33
- package/dist/index.d.ts +83 -33
- package/dist/index.js +1384 -676
- package/dist/index.js.map +1 -1
- package/docs/api/assets/hierarchy.js +1 -1
- package/docs/api/assets/navigation.js +1 -1
- package/docs/api/assets/search.js +1 -1
- package/docs/api/classes/ClaimHydrationError.html +6 -3
- package/docs/api/classes/ConnectionClosedError.html +6 -3
- package/docs/api/classes/FerricStoreClient.html +4 -4
- package/docs/api/classes/FerricStoreError.html +6 -3
- package/docs/api/classes/FlowAlreadyExistsError.html +6 -3
- package/docs/api/classes/FlowBatchError.html +6 -3
- package/docs/api/classes/FlowNotFoundError.html +6 -3
- package/docs/api/classes/FlowWrongStateError.html +6 -3
- package/docs/api/classes/InvalidCommandError.html +6 -3
- package/docs/api/classes/KeyValueStore.html +2 -2
- package/docs/api/classes/LeaseRenewalError.html +1 -1
- package/docs/api/classes/LockHeldError.html +6 -3
- package/docs/api/classes/LockNotOwnedError.html +6 -3
- package/docs/api/classes/NativeAdapter.html +2 -2
- package/docs/api/classes/OverloadedError.html +6 -4
- package/docs/api/classes/QueueCompletionError.html +1 -1
- package/docs/api/classes/ReconnectingExecutor.html +4 -4
- package/docs/api/classes/RequestTimeoutError.html +6 -3
- package/docs/api/classes/RerouteError.html +6 -3
- package/docs/api/classes/StaleLeaseError.html +6 -3
- package/docs/api/classes/StalePolicyGenerationError.html +39 -0
- package/docs/api/classes/TDigestStore.html +2 -2
- package/docs/api/classes/TopKStore.html +1 -1
- package/docs/api/classes/TopologyNativeAdapterPool.html +3 -3
- package/docs/api/classes/Workflow.html +1 -1
- package/docs/api/classes/WorkflowWorker.html +2 -2
- package/docs/api/functions/classifyServerError.html +1 -1
- package/docs/api/functions/isReconnectableClosedConnectionError.html +1 -1
- package/docs/api/functions/mapException.html +1 -1
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +22 -8
- package/docs/api/interfaces/AdminListOptions.html +1 -1
- package/docs/api/interfaces/CancelOptions.html +2 -2
- package/docs/api/interfaces/ClaimDueOptions.html +3 -3
- package/docs/api/interfaces/CompleteJobsAndClaimJobsResult.html +6 -6
- package/docs/api/interfaces/CompleteManyOptions.html +2 -2
- package/docs/api/interfaces/CompleteOptions.html +2 -2
- package/docs/api/interfaces/CompleteOutcome.html +1 -1
- package/docs/api/interfaces/CreateManyOptions.html +1 -1
- package/docs/api/interfaces/EffectCompensateOptions.html +1 -1
- package/docs/api/interfaces/EffectConfirmOptions.html +1 -1
- package/docs/api/interfaces/EffectFailOptions.html +1 -1
- package/docs/api/interfaces/EffectStatusOptions.html +1 -1
- package/docs/api/interfaces/ExtendLeaseOptions.html +2 -2
- package/docs/api/interfaces/FailOptions.html +2 -2
- package/docs/api/interfaces/FailOutcome.html +1 -1
- package/docs/api/interfaces/FerricStoreClientFromUrlOptions.html +1 -1
- package/docs/api/interfaces/FerricStoreClientOptions.html +1 -1
- package/docs/api/interfaces/{FetchOrComputeLegacyResult.html → FetchOrComputeComputeResult.html} +2 -2
- package/docs/api/interfaces/FlowMaxActiveFailure.html +3 -0
- package/docs/api/interfaces/FlowPolicyBackoffSnapshot.html +5 -0
- package/docs/api/interfaces/FlowPolicyOptions.html +8 -4
- package/docs/api/interfaces/FlowPolicyRetentionSnapshot.html +3 -0
- package/docs/api/interfaces/FlowPolicyRetrySnapshot.html +4 -0
- package/docs/api/interfaces/FlowPolicySnapshot.html +17 -0
- package/docs/api/interfaces/FlowPolicyStateSnapshot.html +6 -0
- package/docs/api/interfaces/FlowRecord.html +4 -2
- package/docs/api/interfaces/FlowStatePolicy.html +2 -2
- package/docs/api/interfaces/HistoryOptions.html +2 -2
- package/docs/api/interfaces/InvocationCreateOptions.html +2 -2
- package/docs/api/interfaces/LeaseMutationOptions.html +2 -2
- package/docs/api/interfaces/LimitListOptions.html +1 -1
- package/docs/api/interfaces/MutateOptions.html +2 -2
- package/docs/api/interfaces/NamedValueMutation.html +1 -1
- package/docs/api/interfaces/ProtocolCommand.html +2 -2
- package/docs/api/interfaces/ReadOptions.html +2 -2
- package/docs/api/interfaces/ReclaimOptions.html +2 -2
- package/docs/api/interfaces/RequestContext.html +2 -2
- package/docs/api/interfaces/RequestContextOptions.html +2 -2
- package/docs/api/interfaces/RetryOptions.html +2 -2
- package/docs/api/interfaces/RetryOutcome.html +1 -1
- package/docs/api/interfaces/RunStepsItem.html +2 -2
- package/docs/api/interfaces/RunStepsManyOptions.html +2 -2
- package/docs/api/interfaces/SearchOptions.html +2 -2
- package/docs/api/interfaces/StartAndClaimOptions.html +4 -2
- package/docs/api/interfaces/StepContinueOptions.html +3 -3
- package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
- package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
- package/docs/api/interfaces/TransitionOptions.html +2 -2
- package/docs/api/interfaces/TransitionOutcome.html +1 -1
- package/docs/api/modules.html +1 -1
- package/docs/api/types/ConnectionRequestDisposition.html +1 -1
- package/docs/api/types/FetchOrComputeFencedResult.html +1 -0
- package/docs/api/types/FetchOrComputeResult.html +1 -1
- package/docs/api/types/FlowPolicyBackoffKind.html +1 -0
- package/docs/api/types/FlowStateMode.html +1 -1
- package/docs/api/types/FlowStatePolicyLike.html +1 -1
- package/docs/api/types/ManagementPairs.html +1 -1
- package/docs/api/types/RequestDisposition.html +1 -1
- package/docs/api/types/SearchStateMeta.html +1 -1
- package/docs/api/types/TopKReserveOptions.html +1 -1
- package/docs/api/variables/COMMAND_OPCODES.html +1 -1
- package/docs/api/variables/FERRICSTORE_MINIMUM_SERVER_VERSION.html +2 -0
- package/docs/api/variables/FERRICSTORE_NATIVE_PROTOCOL_VERSION.html +2 -0
- package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +2 -0
- package/docs/api/variables/MAX_FLOW_POLICY_GENERATION.html +1 -0
- package/package.json +6 -1
- package/docs/api/interfaces/FetchOrComputeFencedResult.html +0 -9
- package/docs/api/types/FetchOrComputeComputeResult.html +0 -1
- package/docs/api/variables/COMPACT_RESPONSE_OPCODES.html +0 -2
package/dist/index.cjs
CHANGED
|
@@ -33,11 +33,13 @@ __export(index_exports, {
|
|
|
33
33
|
BitmapStore: () => BitmapStore,
|
|
34
34
|
BloomFilterStore: () => BloomFilterStore,
|
|
35
35
|
COMMAND_OPCODES: () => COMMAND_OPCODES,
|
|
36
|
-
COMPACT_RESPONSE_OPCODES: () => COMPACT_RESPONSE_OPCODES,
|
|
37
36
|
ClaimHydrationError: () => ClaimHydrationError,
|
|
38
37
|
ConnectionClosedError: () => ConnectionClosedError,
|
|
39
38
|
CountMinSketchStore: () => CountMinSketchStore,
|
|
40
39
|
CuckooFilterStore: () => CuckooFilterStore,
|
|
40
|
+
FERRICSTORE_MINIMUM_SERVER_VERSION: () => FERRICSTORE_MINIMUM_SERVER_VERSION,
|
|
41
|
+
FERRICSTORE_NATIVE_PROTOCOL_VERSION: () => FERRICSTORE_NATIVE_PROTOCOL_VERSION,
|
|
42
|
+
FERRICSTORE_SDK_VERSION: () => FERRICSTORE_SDK_VERSION,
|
|
41
43
|
FerricStoreClient: () => FerricStoreClient,
|
|
42
44
|
FerricStoreError: () => FerricStoreError,
|
|
43
45
|
FlowAlreadyExistsError: () => FlowAlreadyExistsError,
|
|
@@ -54,6 +56,7 @@ __export(index_exports, {
|
|
|
54
56
|
ListStore: () => ListStore,
|
|
55
57
|
LockHeldError: () => LockHeldError,
|
|
56
58
|
LockNotOwnedError: () => LockNotOwnedError,
|
|
59
|
+
MAX_FLOW_POLICY_GENERATION: () => MAX_FLOW_POLICY_GENERATION,
|
|
57
60
|
NativeAdapter: () => NativeAdapter,
|
|
58
61
|
OverloadedError: () => OverloadedError,
|
|
59
62
|
Queue: () => Queue,
|
|
@@ -68,6 +71,7 @@ __export(index_exports, {
|
|
|
68
71
|
SetStore: () => SetStore,
|
|
69
72
|
SortedSetStore: () => SortedSetStore,
|
|
70
73
|
StaleLeaseError: () => StaleLeaseError,
|
|
74
|
+
StalePolicyGenerationError: () => StalePolicyGenerationError,
|
|
71
75
|
StreamStore: () => StreamStore,
|
|
72
76
|
TDigestStore: () => TDigestStore,
|
|
73
77
|
TopKStore: () => TopKStore,
|
|
@@ -100,16 +104,22 @@ function assertSafeVariadicDispatch(argumentCount, arrayCapability) {
|
|
|
100
104
|
// src/native-adapter.ts
|
|
101
105
|
var import_node_net3 = require("net");
|
|
102
106
|
var import_node_tls3 = require("tls");
|
|
103
|
-
var
|
|
107
|
+
var import_node_buffer26 = require("buffer");
|
|
104
108
|
|
|
105
109
|
// src/errors.ts
|
|
106
110
|
var FerricStoreError = class extends Error {
|
|
107
111
|
code = "ferricstore_error";
|
|
108
112
|
raw;
|
|
113
|
+
retryable;
|
|
114
|
+
safeToRetry;
|
|
115
|
+
retryAfterMs;
|
|
109
116
|
constructor(message, options = {}) {
|
|
110
117
|
super(message, { cause: options.cause });
|
|
111
118
|
this.name = new.target.name;
|
|
112
119
|
this.raw = options.raw;
|
|
120
|
+
this.retryable = options.retryable ?? structuredBooleanField(options.raw, "retryable");
|
|
121
|
+
this.safeToRetry = options.safeToRetry ?? structuredBooleanField(options.raw, "safe_to_retry");
|
|
122
|
+
this.retryAfterMs = options.retryAfterMs ?? structuredIntegerField(options.raw, "retry_after_ms");
|
|
113
123
|
}
|
|
114
124
|
};
|
|
115
125
|
var ConnectionClosedError = class extends FerricStoreError {
|
|
@@ -142,6 +152,9 @@ var FlowWrongStateError = class extends FerricStoreError {
|
|
|
142
152
|
var StaleLeaseError = class extends FerricStoreError {
|
|
143
153
|
code = "stale_lease";
|
|
144
154
|
};
|
|
155
|
+
var StalePolicyGenerationError = class extends FerricStoreError {
|
|
156
|
+
code = "stale_policy_generation";
|
|
157
|
+
};
|
|
145
158
|
var FlowAlreadyExistsError = class extends FerricStoreError {
|
|
146
159
|
code = "flow_already_exists";
|
|
147
160
|
};
|
|
@@ -156,11 +169,14 @@ var InvalidCommandError = class extends FerricStoreError {
|
|
|
156
169
|
};
|
|
157
170
|
var OverloadedError = class extends FerricStoreError {
|
|
158
171
|
code = "overloaded";
|
|
159
|
-
retryAfterMs;
|
|
160
172
|
reason;
|
|
161
173
|
constructor(message, options = {}) {
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
const local = options.raw == null;
|
|
175
|
+
super(message, {
|
|
176
|
+
...options,
|
|
177
|
+
retryable: options.retryable ?? (local ? true : void 0),
|
|
178
|
+
safeToRetry: options.safeToRetry ?? (local ? true : void 0)
|
|
179
|
+
});
|
|
164
180
|
this.reason = options.reason;
|
|
165
181
|
}
|
|
166
182
|
};
|
|
@@ -178,15 +194,21 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
178
194
|
const lower = message.toLowerCase();
|
|
179
195
|
const structuredCode = structuredStringField(raw, "code");
|
|
180
196
|
const code = structuredCode?.toLowerCase();
|
|
197
|
+
const retry2 = {
|
|
198
|
+
retryable: structuredBooleanField(raw, "retryable"),
|
|
199
|
+
safeToRetry: structuredBooleanField(raw, "safe_to_retry"),
|
|
200
|
+
retryAfterMs: structuredIntegerField(raw, "retry_after_ms") ?? intField(lower, "retry_after_ms")
|
|
201
|
+
};
|
|
181
202
|
if (isRerouteStatus(status) || code === "reroute") {
|
|
182
|
-
return new RerouteError(message, { cause, raw });
|
|
203
|
+
return new RerouteError(message, { cause, raw, ...definedRetryMetadata(retry2) });
|
|
183
204
|
}
|
|
184
205
|
if (isBusyStatus(status) || isOverloadCode(structuredCode) || overloadMessage(lower)) {
|
|
185
206
|
return new OverloadedError(message, {
|
|
186
207
|
cause,
|
|
187
208
|
raw,
|
|
209
|
+
...definedRetryMetadata(retry2),
|
|
188
210
|
reason: structuredStringField(raw, "reason") ?? structuredCode ?? stringField(lower, "reason"),
|
|
189
|
-
retryAfterMs:
|
|
211
|
+
retryAfterMs: retry2.retryAfterMs
|
|
190
212
|
});
|
|
191
213
|
}
|
|
192
214
|
if (code === "flow_already_exists" || lower.includes("flow") && lower.includes("already exists")) {
|
|
@@ -198,6 +220,9 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
198
220
|
if (code === "stale_lease" || code === "stale_flow_lease" || lower.includes("stale flow lease") || lower.includes("stale lease") || lower.includes("stale token")) {
|
|
199
221
|
return new StaleLeaseError(message, { cause, raw });
|
|
200
222
|
}
|
|
223
|
+
if (code === "stale_generation" || code === "stale_policy_generation" || code === "stale_flow_policy_generation" || lower.includes("stale flow policy generation") || lower.includes("stale policy generation")) {
|
|
224
|
+
return new StalePolicyGenerationError(message, { cause, raw });
|
|
225
|
+
}
|
|
201
226
|
if (code === "flow_not_found" || lower.includes("flow") && (lower.includes("not found") || lower.includes("does not exist"))) {
|
|
202
227
|
return new FlowNotFoundError(message, { cause, raw });
|
|
203
228
|
}
|
|
@@ -210,7 +235,7 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
210
235
|
if (code === "invalid_command" || lower.includes("wrong number of arguments") || lower.includes("syntax error")) {
|
|
211
236
|
return new InvalidCommandError(message, { cause, raw });
|
|
212
237
|
}
|
|
213
|
-
return new FerricStoreError(message, { cause, raw });
|
|
238
|
+
return new FerricStoreError(message, { cause, raw, ...definedRetryMetadata(retry2) });
|
|
214
239
|
}
|
|
215
240
|
function mapException(error) {
|
|
216
241
|
if (error instanceof FerricStoreError) {
|
|
@@ -250,8 +275,23 @@ function structuredIntegerField(raw, name) {
|
|
|
250
275
|
if (typeof value === "bigint") {
|
|
251
276
|
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
252
277
|
}
|
|
253
|
-
const
|
|
254
|
-
return
|
|
278
|
+
const text3 = binaryText(value);
|
|
279
|
+
return text3 == null ? void 0 : nonNegativeSafeIntegerText(text3);
|
|
280
|
+
}
|
|
281
|
+
function structuredBooleanField(raw, name) {
|
|
282
|
+
const value = structuredField(raw, name);
|
|
283
|
+
if (typeof value === "boolean") return value;
|
|
284
|
+
const text3 = binaryText(value)?.toLowerCase();
|
|
285
|
+
if (text3 === "true" || text3 === "1") return true;
|
|
286
|
+
if (text3 === "false" || text3 === "0") return false;
|
|
287
|
+
return void 0;
|
|
288
|
+
}
|
|
289
|
+
function definedRetryMetadata(metadata) {
|
|
290
|
+
return {
|
|
291
|
+
...metadata.retryable == null ? {} : { retryable: metadata.retryable },
|
|
292
|
+
...metadata.safeToRetry == null ? {} : { safeToRetry: metadata.safeToRetry },
|
|
293
|
+
...metadata.retryAfterMs == null ? {} : { retryAfterMs: metadata.retryAfterMs }
|
|
294
|
+
};
|
|
255
295
|
}
|
|
256
296
|
function nonNegativeSafeIntegerText(value) {
|
|
257
297
|
if (!/^[0-9]+$/u.test(value)) return void 0;
|
|
@@ -424,9 +464,6 @@ function mapDenseResponseArray(value, transform) {
|
|
|
424
464
|
return result;
|
|
425
465
|
}
|
|
426
466
|
|
|
427
|
-
// src/auto-partition.ts
|
|
428
|
-
var import_node_buffer2 = require("buffer");
|
|
429
|
-
|
|
430
467
|
// src/crc32.ts
|
|
431
468
|
var import_node_buffer = require("buffer");
|
|
432
469
|
var table = new Uint32Array(256);
|
|
@@ -444,12 +481,49 @@ function crc32(buffer) {
|
|
|
444
481
|
}
|
|
445
482
|
return (value ^ 4294967295) >>> 0;
|
|
446
483
|
}
|
|
484
|
+
function crc32Utf8(text3, start = 0, end = text3.length) {
|
|
485
|
+
let value = 4294967295;
|
|
486
|
+
for (let index = start; index < end; index += 1) {
|
|
487
|
+
const first = text3.charCodeAt(index);
|
|
488
|
+
let point = first;
|
|
489
|
+
if (first >= 55296 && first <= 56319) {
|
|
490
|
+
const second = index + 1 < end ? text3.charCodeAt(index + 1) : 0;
|
|
491
|
+
if (second >= 56320 && second <= 57343) {
|
|
492
|
+
point = 65536 + (first - 55296 << 10) + second - 56320;
|
|
493
|
+
index += 1;
|
|
494
|
+
} else {
|
|
495
|
+
point = 65533;
|
|
496
|
+
}
|
|
497
|
+
} else if (first >= 56320 && first <= 57343) {
|
|
498
|
+
point = 65533;
|
|
499
|
+
}
|
|
500
|
+
if (point < 128) {
|
|
501
|
+
value = updateCrc32(value, point);
|
|
502
|
+
} else if (point < 2048) {
|
|
503
|
+
value = updateCrc32(value, 192 | point >>> 6);
|
|
504
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
505
|
+
} else if (point < 65536) {
|
|
506
|
+
value = updateCrc32(value, 224 | point >>> 12);
|
|
507
|
+
value = updateCrc32(value, 128 | point >>> 6 & 63);
|
|
508
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
509
|
+
} else {
|
|
510
|
+
value = updateCrc32(value, 240 | point >>> 18);
|
|
511
|
+
value = updateCrc32(value, 128 | point >>> 12 & 63);
|
|
512
|
+
value = updateCrc32(value, 128 | point >>> 6 & 63);
|
|
513
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return (value ^ 4294967295) >>> 0;
|
|
517
|
+
}
|
|
518
|
+
function updateCrc32(value, byte) {
|
|
519
|
+
return value >>> 8 ^ (table[(value ^ byte) & 255] ?? 0);
|
|
520
|
+
}
|
|
447
521
|
|
|
448
522
|
// src/auto-partition.ts
|
|
449
523
|
var AUTO_PARTITION_PREFIX = "__flow_auto__:";
|
|
450
524
|
var AUTO_PARTITION_BUCKETS = 256;
|
|
451
525
|
function autoPartitionKeyForId(id) {
|
|
452
|
-
return `${AUTO_PARTITION_PREFIX}${
|
|
526
|
+
return `${AUTO_PARTITION_PREFIX}${crc32Utf8(id) % AUTO_PARTITION_BUCKETS}`;
|
|
453
527
|
}
|
|
454
528
|
|
|
455
529
|
// src/flow-argument-helpers.ts
|
|
@@ -842,7 +916,7 @@ function coerceDiagnosticValue(value) {
|
|
|
842
916
|
// src/native-connection.ts
|
|
843
917
|
var import_node_net = __toESM(require("net"), 1);
|
|
844
918
|
var import_node_tls = __toESM(require("tls"), 1);
|
|
845
|
-
var
|
|
919
|
+
var import_node_buffer2 = require("buffer");
|
|
846
920
|
function parseFerricUrl(value) {
|
|
847
921
|
const url = new URL(value);
|
|
848
922
|
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
@@ -968,7 +1042,7 @@ function nonNegativeSafeInteger(value) {
|
|
|
968
1042
|
if (typeof value === "bigint") {
|
|
969
1043
|
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
970
1044
|
}
|
|
971
|
-
const source =
|
|
1045
|
+
const source = import_node_buffer2.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer2.Buffer.from(value).toString("utf8") : value;
|
|
972
1046
|
if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
|
|
973
1047
|
return void 0;
|
|
974
1048
|
}
|
|
@@ -1202,10 +1276,10 @@ var NativeHeartbeat = class {
|
|
|
1202
1276
|
};
|
|
1203
1277
|
|
|
1204
1278
|
// src/protocol.ts
|
|
1205
|
-
var
|
|
1279
|
+
var import_node_buffer22 = require("buffer");
|
|
1206
1280
|
|
|
1207
1281
|
// src/command-grammar.ts
|
|
1208
|
-
var
|
|
1282
|
+
var import_node_buffer3 = require("buffer");
|
|
1209
1283
|
|
|
1210
1284
|
// src/command-metadata-flow.ts
|
|
1211
1285
|
var flowStateIdCommands = /* @__PURE__ */ new Set([
|
|
@@ -1652,8 +1726,8 @@ var secondKeySubcommands = /* @__PURE__ */ new Map([
|
|
|
1652
1726
|
]);
|
|
1653
1727
|
function commandToken(value) {
|
|
1654
1728
|
if (typeof value === "string") return value.toUpperCase();
|
|
1655
|
-
if (
|
|
1656
|
-
return
|
|
1729
|
+
if (import_node_buffer3.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
1730
|
+
return import_node_buffer3.Buffer.from(value).toString("utf8").toUpperCase();
|
|
1657
1731
|
}
|
|
1658
1732
|
return void 0;
|
|
1659
1733
|
}
|
|
@@ -1756,7 +1830,7 @@ function safeIntegerArgument(value) {
|
|
|
1756
1830
|
if (typeof value === "bigint") {
|
|
1757
1831
|
return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
1758
1832
|
}
|
|
1759
|
-
const source = typeof value === "string" ? value :
|
|
1833
|
+
const source = typeof value === "string" ? value : import_node_buffer3.Buffer.isBuffer(value) || value instanceof Uint8Array ? import_node_buffer3.Buffer.from(value).toString("utf8") : void 0;
|
|
1760
1834
|
if (source == null || !/^[+-]?\d+$/u.test(source)) return void 0;
|
|
1761
1835
|
const parsed = BigInt(source);
|
|
1762
1836
|
return parsed >= BigInt(Number.MIN_SAFE_INTEGER) && parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : void 0;
|
|
@@ -1809,10 +1883,10 @@ function hasOwnCommandArgument(args, index, end, section) {
|
|
|
1809
1883
|
}
|
|
1810
1884
|
|
|
1811
1885
|
// src/protocol-core.ts
|
|
1812
|
-
var
|
|
1886
|
+
var import_node_buffer7 = require("buffer");
|
|
1813
1887
|
|
|
1814
1888
|
// src/protocol-constants.ts
|
|
1815
|
-
var
|
|
1889
|
+
var import_node_buffer4 = require("buffer");
|
|
1816
1890
|
|
|
1817
1891
|
// src/native-protocol-manifest.json
|
|
1818
1892
|
var native_protocol_manifest_default = {
|
|
@@ -2017,80 +2091,30 @@ var OPCODES = {
|
|
|
2017
2091
|
flowFail: COMMAND_OPCODES["FLOW.FAIL"],
|
|
2018
2092
|
flowValuePut: COMMAND_OPCODES["FLOW.VALUE.PUT"],
|
|
2019
2093
|
flowValueMGet: COMMAND_OPCODES["FLOW.VALUE.MGET"],
|
|
2094
|
+
flowSignal: COMMAND_OPCODES["FLOW.SIGNAL"],
|
|
2020
2095
|
flowCreateMany: COMMAND_OPCODES["FLOW.CREATE_MANY"],
|
|
2021
2096
|
flowCompleteMany: COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
|
|
2022
2097
|
flowTransitionMany: COMMAND_OPCODES["FLOW.TRANSITION_MANY"],
|
|
2023
2098
|
flowRetryMany: COMMAND_OPCODES["FLOW.RETRY_MANY"],
|
|
2024
2099
|
flowFailMany: COMMAND_OPCODES["FLOW.FAIL_MANY"],
|
|
2025
2100
|
flowReclaim: COMMAND_OPCODES["FLOW.RECLAIM"],
|
|
2101
|
+
flowPolicySet: COMMAND_OPCODES["FLOW.POLICY.SET"],
|
|
2102
|
+
flowPolicyGet: COMMAND_OPCODES["FLOW.POLICY.GET"],
|
|
2026
2103
|
flowSpawnChildren: COMMAND_OPCODES["FLOW.SPAWN_CHILDREN"],
|
|
2027
2104
|
flowStepContinue: COMMAND_OPCODES["FLOW.STEP_CONTINUE"],
|
|
2028
2105
|
flowStartAndClaim: COMMAND_OPCODES["FLOW.START_AND_CLAIM"],
|
|
2029
2106
|
flowRunStepsMany: COMMAND_OPCODES["FLOW.RUN_STEPS_MANY"],
|
|
2030
2107
|
flowSearch: COMMAND_OPCODES["FLOW.SEARCH"]
|
|
2031
2108
|
};
|
|
2032
|
-
var COMPACT_RESPONSE_OPCODES = {
|
|
2033
|
-
flow_claim_jobs_v1: [COMMAND_OPCODES["FLOW.CLAIM_DUE"]],
|
|
2034
|
-
flow_record_list_v1: [
|
|
2035
|
-
COMMAND_OPCODES["FLOW.LIST"],
|
|
2036
|
-
COMMAND_OPCODES["FLOW.TERMINALS"],
|
|
2037
|
-
COMMAND_OPCODES["FLOW.FAILURES"],
|
|
2038
|
-
COMMAND_OPCODES["FLOW.BY_PARENT"],
|
|
2039
|
-
COMMAND_OPCODES["FLOW.BY_ROOT"],
|
|
2040
|
-
COMMAND_OPCODES["FLOW.BY_CORRELATION"],
|
|
2041
|
-
COMMAND_OPCODES["FLOW.STUCK"]
|
|
2042
|
-
],
|
|
2043
|
-
flow_record_v1: [COMMAND_OPCODES["FLOW.GET"]],
|
|
2044
|
-
kv_get_v1: [COMMAND_OPCODES.GET],
|
|
2045
|
-
kv_mget_v1: [COMMAND_OPCODES.MGET, COMMAND_OPCODES["FLOW.VALUE.MGET"]],
|
|
2046
|
-
ok_list_v1: [
|
|
2047
|
-
COMMAND_OPCODES.SET,
|
|
2048
|
-
COMMAND_OPCODES.MSET,
|
|
2049
|
-
COMMAND_OPCODES["FLOW.CREATE_MANY"],
|
|
2050
|
-
COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
|
|
2051
|
-
COMMAND_OPCODES["FLOW.RETRY_MANY"],
|
|
2052
|
-
COMMAND_OPCODES["FLOW.FAIL_MANY"],
|
|
2053
|
-
COMMAND_OPCODES["FLOW.CANCEL_MANY"]
|
|
2054
|
-
],
|
|
2055
|
-
pipeline_v1: [COMMAND_OPCODES.PIPELINE]
|
|
2056
|
-
};
|
|
2057
|
-
var COMPACT_KIND_FLOW_CLAIM_JOBS = 1 << 0;
|
|
2058
|
-
var COMPACT_KIND_FLOW_RECORD = 1 << 1;
|
|
2059
|
-
var COMPACT_KIND_FLOW_RECORD_LIST = 1 << 2;
|
|
2060
|
-
var COMPACT_KIND_KV_GET = 1 << 3;
|
|
2061
|
-
var COMPACT_KIND_KV_MGET = 1 << 4;
|
|
2062
|
-
var COMPACT_KIND_OK_LIST = 1 << 5;
|
|
2063
|
-
var COMPACT_KIND_PIPELINE = 1 << 6;
|
|
2064
|
-
var compactResponseOpcodeKinds = new Uint8Array(
|
|
2065
|
-
Math.max(...Object.values(COMPACT_RESPONSE_OPCODES).flat()) + 1
|
|
2066
|
-
);
|
|
2067
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_CLAIM_JOBS, COMPACT_RESPONSE_OPCODES.flow_claim_jobs_v1);
|
|
2068
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD, COMPACT_RESPONSE_OPCODES.flow_record_v1);
|
|
2069
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD_LIST, COMPACT_RESPONSE_OPCODES.flow_record_list_v1);
|
|
2070
|
-
registerCompactResponseOpcodes(COMPACT_KIND_KV_GET, COMPACT_RESPONSE_OPCODES.kv_get_v1);
|
|
2071
|
-
registerCompactResponseOpcodes(COMPACT_KIND_KV_MGET, [
|
|
2072
|
-
...COMPACT_RESPONSE_OPCODES.kv_mget_v1,
|
|
2073
|
-
COMMAND_OPCODES.PIPELINE
|
|
2074
|
-
]);
|
|
2075
|
-
registerCompactResponseOpcodes(COMPACT_KIND_OK_LIST, [
|
|
2076
|
-
...COMPACT_RESPONSE_OPCODES.ok_list_v1,
|
|
2077
|
-
COMMAND_OPCODES.PIPELINE
|
|
2078
|
-
]);
|
|
2079
|
-
registerCompactResponseOpcodes(COMPACT_KIND_PIPELINE, COMPACT_RESPONSE_OPCODES.pipeline_v1);
|
|
2080
|
-
function registerCompactResponseOpcodes(kind, opcodes) {
|
|
2081
|
-
for (const opcode of opcodes) {
|
|
2082
|
-
compactResponseOpcodeKinds[opcode] = (compactResponseOpcodeKinds[opcode] ?? 0) | kind;
|
|
2083
|
-
}
|
|
2084
|
-
}
|
|
2085
|
-
function compactResponseOpcodeSupports(opcode, kind) {
|
|
2086
|
-
return ((compactResponseOpcodeKinds[opcode] ?? 0) & kind) !== 0;
|
|
2087
|
-
}
|
|
2088
2109
|
var COMPACT_FLOW_CLAIM_JOBS = 128;
|
|
2089
2110
|
var COMPACT_OK_LIST = 129;
|
|
2090
2111
|
var COMPACT_KV_GET = 130;
|
|
2091
2112
|
var COMPACT_KV_MGET = 131;
|
|
2092
2113
|
var COMPACT_FLOW_RECORD = 132;
|
|
2093
2114
|
var COMPACT_FLOW_RECORD_LIST = 133;
|
|
2115
|
+
var COMPACT_BINARY_LIST_LIST = 134;
|
|
2116
|
+
var COMPACT_BINARY_MAP_LIST = 135;
|
|
2117
|
+
var COMPACT_INTEGER_LIST = 136;
|
|
2094
2118
|
var COMPACT_KV_MGET_FIXED = 137;
|
|
2095
2119
|
var COMPACT_FLOW_CREATE_MANY_REQUEST = 144;
|
|
2096
2120
|
var COMPACT_FLOW_CLAIM_DUE_REQUEST = 145;
|
|
@@ -2160,16 +2184,16 @@ var FLOW_RECORD_FIELD_KEYS = [
|
|
|
2160
2184
|
];
|
|
2161
2185
|
|
|
2162
2186
|
// src/protocol-text.ts
|
|
2163
|
-
var
|
|
2187
|
+
var import_node_buffer5 = require("buffer");
|
|
2164
2188
|
function toBuffer(value) {
|
|
2165
|
-
if (
|
|
2166
|
-
if (value instanceof Uint8Array) return
|
|
2167
|
-
if (typeof value === "string") return
|
|
2189
|
+
if (import_node_buffer5.Buffer.isBuffer(value)) return value;
|
|
2190
|
+
if (value instanceof Uint8Array) return import_node_buffer5.Buffer.from(value);
|
|
2191
|
+
if (typeof value === "string") return import_node_buffer5.Buffer.from(value);
|
|
2168
2192
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2169
|
-
return
|
|
2193
|
+
return import_node_buffer5.Buffer.from(String(value));
|
|
2170
2194
|
}
|
|
2171
|
-
if (typeof value === "symbol") return
|
|
2172
|
-
if (value == null) return
|
|
2195
|
+
if (typeof value === "symbol") return import_node_buffer5.Buffer.from(value.description ?? value.toString());
|
|
2196
|
+
if (value == null) return import_node_buffer5.Buffer.alloc(0);
|
|
2173
2197
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2174
2198
|
}
|
|
2175
2199
|
function asText(value) {
|
|
@@ -2177,14 +2201,14 @@ function asText(value) {
|
|
|
2177
2201
|
}
|
|
2178
2202
|
function optionalText(value) {
|
|
2179
2203
|
if (value == null || value === "") return void 0;
|
|
2180
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ||
|
|
2204
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || import_node_buffer5.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
2181
2205
|
return asText(value);
|
|
2182
2206
|
}
|
|
2183
2207
|
return void 0;
|
|
2184
2208
|
}
|
|
2185
2209
|
function commandTokenIs(value, expected) {
|
|
2186
2210
|
if (typeof value === "string") return value.toUpperCase() === expected;
|
|
2187
|
-
if (
|
|
2211
|
+
if (import_node_buffer5.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
2188
2212
|
return asText(value).toUpperCase() === expected;
|
|
2189
2213
|
}
|
|
2190
2214
|
return false;
|
|
@@ -2198,7 +2222,7 @@ function commandNameIs(value, expected) {
|
|
|
2198
2222
|
}
|
|
2199
2223
|
|
|
2200
2224
|
// src/request-context.ts
|
|
2201
|
-
var
|
|
2225
|
+
var import_node_buffer6 = require("buffer");
|
|
2202
2226
|
var requestContextCommands = /* @__PURE__ */ new Set([
|
|
2203
2227
|
"INVOCATION.CREATE",
|
|
2204
2228
|
"INVOCATION.DEFINITION.GET",
|
|
@@ -2253,9 +2277,9 @@ function requestContextCommandToken(value) {
|
|
|
2253
2277
|
const upper = value.toUpperCase();
|
|
2254
2278
|
return isRequestContextCommand(upper) ? upper : void 0;
|
|
2255
2279
|
}
|
|
2256
|
-
if (
|
|
2280
|
+
if (import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
2257
2281
|
if (value[0] !== 73 && value[0] !== 105) return void 0;
|
|
2258
|
-
const command =
|
|
2282
|
+
const command = import_node_buffer6.Buffer.from(value).toString("utf8").toUpperCase();
|
|
2259
2283
|
return isRequestContextCommand(command) ? command : void 0;
|
|
2260
2284
|
}
|
|
2261
2285
|
return void 0;
|
|
@@ -2286,12 +2310,12 @@ function requestContextText(context, fieldName) {
|
|
|
2286
2310
|
return value;
|
|
2287
2311
|
}
|
|
2288
2312
|
function isPlainObject(value) {
|
|
2289
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2313
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer6.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2290
2314
|
}
|
|
2291
2315
|
function commandToken2(value) {
|
|
2292
2316
|
if (typeof value === "string") return value.toUpperCase();
|
|
2293
|
-
if (
|
|
2294
|
-
return
|
|
2317
|
+
if (import_node_buffer6.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
2318
|
+
return import_node_buffer6.Buffer.from(value).toString("utf8").toUpperCase();
|
|
2295
2319
|
}
|
|
2296
2320
|
return "";
|
|
2297
2321
|
}
|
|
@@ -2381,17 +2405,17 @@ function requestFrameTooLarge(maxBytes) {
|
|
|
2381
2405
|
);
|
|
2382
2406
|
}
|
|
2383
2407
|
function binaryValueByteLength(value) {
|
|
2384
|
-
if (
|
|
2385
|
-
if (typeof value === "string") return
|
|
2408
|
+
if (import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
|
|
2409
|
+
if (typeof value === "string") return import_node_buffer7.Buffer.byteLength(value);
|
|
2386
2410
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2387
|
-
return
|
|
2411
|
+
return import_node_buffer7.Buffer.byteLength(String(value));
|
|
2388
2412
|
}
|
|
2389
|
-
if (typeof value === "symbol") return
|
|
2413
|
+
if (typeof value === "symbol") return import_node_buffer7.Buffer.byteLength(value.description ?? value.toString());
|
|
2390
2414
|
if (value == null) return 0;
|
|
2391
2415
|
return toBuffer(value).byteLength;
|
|
2392
2416
|
}
|
|
2393
2417
|
function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
2394
|
-
if (
|
|
2418
|
+
if (import_node_buffer7.Buffer.isBuffer(value)) {
|
|
2395
2419
|
value.copy(output, offset);
|
|
2396
2420
|
return;
|
|
2397
2421
|
}
|
|
@@ -2400,17 +2424,17 @@ function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
|
2400
2424
|
return;
|
|
2401
2425
|
}
|
|
2402
2426
|
if (value == null) return;
|
|
2403
|
-
let
|
|
2427
|
+
let text3;
|
|
2404
2428
|
if (typeof value === "string") {
|
|
2405
|
-
|
|
2429
|
+
text3 = value;
|
|
2406
2430
|
} else if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2407
|
-
|
|
2431
|
+
text3 = String(value);
|
|
2408
2432
|
} else if (typeof value === "symbol") {
|
|
2409
|
-
|
|
2433
|
+
text3 = value.description ?? value.toString();
|
|
2410
2434
|
} else {
|
|
2411
2435
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2412
2436
|
}
|
|
2413
|
-
output.write(
|
|
2437
|
+
output.write(text3, offset, knownByteLength ?? import_node_buffer7.Buffer.byteLength(text3), "utf8");
|
|
2414
2438
|
}
|
|
2415
2439
|
function compactBinaryEncodedLength(value) {
|
|
2416
2440
|
return 4 + compactBinaryByteLength(value);
|
|
@@ -2423,10 +2447,10 @@ function compactBinaryByteLength(value) {
|
|
|
2423
2447
|
return byteLength;
|
|
2424
2448
|
}
|
|
2425
2449
|
function isCompactBinaryArgument(value) {
|
|
2426
|
-
return typeof value === "string" ||
|
|
2450
|
+
return typeof value === "string" || import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
2427
2451
|
}
|
|
2428
2452
|
function isCompactBinaryScalar(value) {
|
|
2429
|
-
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" ||
|
|
2453
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || import_node_buffer7.Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
2430
2454
|
}
|
|
2431
2455
|
function compactOptionalBinaryEncodedLength(value) {
|
|
2432
2456
|
return value == null ? 4 : compactBinaryEncodedLength(value);
|
|
@@ -2509,13 +2533,13 @@ function i64Arg(value) {
|
|
|
2509
2533
|
}
|
|
2510
2534
|
function boolArg(value) {
|
|
2511
2535
|
if (typeof value === "boolean") return value;
|
|
2512
|
-
const
|
|
2513
|
-
return
|
|
2536
|
+
const text3 = asText(value).toUpperCase();
|
|
2537
|
+
return text3 === "1" || text3 === "TRUE" || text3 === "YES" || text3 === "ON";
|
|
2514
2538
|
}
|
|
2515
2539
|
function isBoolToken(value) {
|
|
2516
2540
|
if (typeof value === "boolean") return true;
|
|
2517
|
-
const
|
|
2518
|
-
return
|
|
2541
|
+
const text3 = asText(value).toUpperCase();
|
|
2542
|
+
return text3 === "1" || text3 === "0" || text3 === "TRUE" || text3 === "FALSE" || text3 === "YES" || text3 === "NO" || text3 === "ON" || text3 === "OFF";
|
|
2519
2543
|
}
|
|
2520
2544
|
function independentMode(value) {
|
|
2521
2545
|
if (value === true) return 2;
|
|
@@ -2557,7 +2581,23 @@ function setOwnValue2(target, key, value) {
|
|
|
2557
2581
|
}
|
|
2558
2582
|
|
|
2559
2583
|
// src/protocol-flow-options.ts
|
|
2560
|
-
var
|
|
2584
|
+
var import_node_buffer8 = require("buffer");
|
|
2585
|
+
|
|
2586
|
+
// src/protocol-flow-option-value.ts
|
|
2587
|
+
function setFlowOptionValue(payload, field2, value, repeat) {
|
|
2588
|
+
if (!repeat || !Object.hasOwn(payload, field2)) {
|
|
2589
|
+
setOwnValue2(payload, field2, value);
|
|
2590
|
+
return;
|
|
2591
|
+
}
|
|
2592
|
+
const previous = payload[field2];
|
|
2593
|
+
setOwnValue2(
|
|
2594
|
+
payload,
|
|
2595
|
+
field2,
|
|
2596
|
+
Array.isArray(previous) ? [...previous, value] : [previous, value]
|
|
2597
|
+
);
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
// src/protocol-flow-options.ts
|
|
2561
2601
|
var OPTION_FIELDS = {
|
|
2562
2602
|
CONSISTENT_PROJECTION: "consistent_projection",
|
|
2563
2603
|
COUNT: "count",
|
|
@@ -2632,7 +2672,7 @@ function normalizeFlowSearchStateMeta(payload) {
|
|
|
2632
2672
|
payload.state_meta = { [asText(state)]: stateMeta };
|
|
2633
2673
|
}
|
|
2634
2674
|
function isPlainObject2(value) {
|
|
2635
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2675
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer8.Buffer.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2636
2676
|
}
|
|
2637
2677
|
function parseFlowOptions(args, start, end, config) {
|
|
2638
2678
|
const payload = {};
|
|
@@ -2726,8 +2766,9 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2726
2766
|
case "TRANSITION_TO":
|
|
2727
2767
|
case "TO_EVENT":
|
|
2728
2768
|
case "EXPECT_STATE": {
|
|
2729
|
-
const field2 = token.toLowerCase();
|
|
2730
|
-
if (!
|
|
2769
|
+
const field2 = token === "IDEMPOTENCY" ? "idempotency_key" : token.toLowerCase();
|
|
2770
|
+
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2771
|
+
setFlowOptionValue(payload, field2, args[index + 1], token === "IF_STATE");
|
|
2731
2772
|
index += 2;
|
|
2732
2773
|
break;
|
|
2733
2774
|
}
|
|
@@ -3017,6 +3058,7 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
3017
3058
|
LEASE_MS: "lease_ms",
|
|
3018
3059
|
LEASE_TOKEN: "lease_token",
|
|
3019
3060
|
LIMIT: "limit",
|
|
3061
|
+
MAX_ACTIVE_MS: "max_active_ms",
|
|
3020
3062
|
MAX_FIRES: "max_fires",
|
|
3021
3063
|
MAXBYTES: "payload_max_bytes",
|
|
3022
3064
|
NOW: "now_ms",
|
|
@@ -3026,7 +3068,6 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
3026
3068
|
OVERLAP_RETRY_MS: "overlap_retry_ms",
|
|
3027
3069
|
OVERWRITE: "overwrite",
|
|
3028
3070
|
PARENT_FLOW_ID: "parent_flow_id",
|
|
3029
|
-
PARENT_ID: "parent_id",
|
|
3030
3071
|
PARTITION: "partition_key",
|
|
3031
3072
|
PAYLOAD: "payload",
|
|
3032
3073
|
PAYLOAD_MAX_BYTES: "payload_max_bytes",
|
|
@@ -3041,7 +3082,6 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
3041
3082
|
REV: "rev",
|
|
3042
3083
|
RETURN: "return",
|
|
3043
3084
|
ROOT_FLOW_ID: "root_flow_id",
|
|
3044
|
-
ROOT_ID: "root_id",
|
|
3045
3085
|
SCOPE: "scope",
|
|
3046
3086
|
SHARD_ID: "shard_id",
|
|
3047
3087
|
START_AT_MS: "start_at_ms",
|
|
@@ -3178,7 +3218,7 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3178
3218
|
}
|
|
3179
3219
|
|
|
3180
3220
|
// src/protocol-flow-compact.ts
|
|
3181
|
-
var
|
|
3221
|
+
var import_node_buffer10 = require("buffer");
|
|
3182
3222
|
|
|
3183
3223
|
// src/protocol-flow-compact-common.ts
|
|
3184
3224
|
function compactManyRequestTag(value, regularTag, okOnSuccessTag) {
|
|
@@ -3287,7 +3327,7 @@ function parseNamedCountMap(values, start) {
|
|
|
3287
3327
|
}
|
|
3288
3328
|
|
|
3289
3329
|
// src/protocol-flow-compact-transition.ts
|
|
3290
|
-
var
|
|
3330
|
+
var import_node_buffer9 = require("buffer");
|
|
3291
3331
|
function compactFlowTransitionManyPayload(partition, fromState, toState, rawItems, mixed, options, maxBodyBytes) {
|
|
3292
3332
|
if ("payload" in options || "priority" in options || "state_meta" in options || "values" in options || "value_refs" in options || "drop_values" in options || "override_values" in options || "attributes_merge" in options || "attributes_delete" in options || typeof options.now_ms !== "number" || !Number.isSafeInteger(options.now_ms) || options.now_ms < 0) {
|
|
3293
3333
|
return void 0;
|
|
@@ -3339,7 +3379,7 @@ function compactFlowTransitionManyPayload(partition, fromState, toState, rawItem
|
|
|
3339
3379
|
total += 4 + idLength + 4 + itemPartitionLength + 8 + 4 + leaseLength;
|
|
3340
3380
|
}
|
|
3341
3381
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3342
|
-
const out =
|
|
3382
|
+
const out = import_node_buffer9.Buffer.allocUnsafe(total);
|
|
3343
3383
|
let offset = 0;
|
|
3344
3384
|
out.writeUInt8(tag, offset);
|
|
3345
3385
|
offset += 1;
|
|
@@ -3397,7 +3437,7 @@ function compactFlowCreateManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3397
3437
|
}
|
|
3398
3438
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3399
3439
|
const tag = mixed ? COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST : auto ? COMPACT_FLOW_CREATE_MANY_REQUEST : COMPACT_FLOW_CREATE_MANY_PARTITION_REQUEST;
|
|
3400
|
-
const out =
|
|
3440
|
+
const out = import_node_buffer10.Buffer.allocUnsafe(total);
|
|
3401
3441
|
let offset = 0;
|
|
3402
3442
|
out.writeUInt8(tag, offset++);
|
|
3403
3443
|
offset = writeBinary(out, offset, toBuffer(options.type));
|
|
@@ -3442,7 +3482,7 @@ function compactFlowClaimDuePayload(type, options, maxBodyBytes) {
|
|
|
3442
3482
|
total += 1;
|
|
3443
3483
|
}
|
|
3444
3484
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3445
|
-
const out =
|
|
3485
|
+
const out = import_node_buffer10.Buffer.allocUnsafe(total);
|
|
3446
3486
|
let offset = 0;
|
|
3447
3487
|
out.writeUInt8(COMPACT_FLOW_CLAIM_DUE_REQUEST, offset++);
|
|
3448
3488
|
offset = writeBinary(out, offset, toBuffer(type));
|
|
@@ -3496,7 +3536,7 @@ function compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto
|
|
|
3496
3536
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3497
3537
|
}
|
|
3498
3538
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3499
|
-
const out =
|
|
3539
|
+
const out = import_node_buffer10.Buffer.allocUnsafe(total);
|
|
3500
3540
|
let offset = 0;
|
|
3501
3541
|
out.writeUInt8(
|
|
3502
3542
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_COMPLETE_MANY_OK_REQUEST : COMPACT_FLOW_COMPLETE_MANY_REQUEST,
|
|
@@ -3543,7 +3583,7 @@ function compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3543
3583
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3544
3584
|
}
|
|
3545
3585
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3546
|
-
const out =
|
|
3586
|
+
const out = import_node_buffer10.Buffer.allocUnsafe(total);
|
|
3547
3587
|
let offset = 0;
|
|
3548
3588
|
out.writeUInt8(
|
|
3549
3589
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_RETRY_MANY_OK_REQUEST : COMPACT_FLOW_RETRY_MANY_REQUEST,
|
|
@@ -3631,7 +3671,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3631
3671
|
total += 4 + idLength + 4 + itemPartitionLength + 8;
|
|
3632
3672
|
}
|
|
3633
3673
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3634
|
-
const out =
|
|
3674
|
+
const out = import_node_buffer10.Buffer.allocUnsafe(total);
|
|
3635
3675
|
let offset = 0;
|
|
3636
3676
|
out.writeUInt8(tag, offset);
|
|
3637
3677
|
offset += 1;
|
|
@@ -3667,7 +3707,7 @@ function isOptionalSafeIntegerNumber(value) {
|
|
|
3667
3707
|
}
|
|
3668
3708
|
|
|
3669
3709
|
// src/protocol-flow-compact-single.ts
|
|
3670
|
-
var
|
|
3710
|
+
var import_node_buffer11 = require("buffer");
|
|
3671
3711
|
function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
3672
3712
|
if (refs.length > 4294967295 || maxBytes != null && (typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 0)) return void 0;
|
|
3673
3713
|
const minimum = 13 + refs.length * 4;
|
|
@@ -3684,7 +3724,7 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3684
3724
|
total += 4 + byteLength;
|
|
3685
3725
|
}
|
|
3686
3726
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3687
|
-
const out =
|
|
3727
|
+
const out = import_node_buffer11.Buffer.allocUnsafe(total);
|
|
3688
3728
|
let offset = 0;
|
|
3689
3729
|
out.writeUInt8(COMPACT_FLOW_VALUE_MGET_REQUEST, offset);
|
|
3690
3730
|
offset += 1;
|
|
@@ -3727,7 +3767,7 @@ function compactFlowListPayload(args, maxBodyBytes) {
|
|
|
3727
3767
|
const stateLength = state == null ? 0 : compactBinaryByteLength(state);
|
|
3728
3768
|
const total = 1 + 4 + typeLength + 4 + stateLength + 8 + 1;
|
|
3729
3769
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3730
|
-
const out =
|
|
3770
|
+
const out = import_node_buffer11.Buffer.allocUnsafe(total);
|
|
3731
3771
|
let offset = 0;
|
|
3732
3772
|
out.writeUInt8(COMPACT_FLOW_LIST_REQUEST, offset);
|
|
3733
3773
|
offset += 1;
|
|
@@ -4170,6 +4210,7 @@ function flowSpawnChildrenPayload(args) {
|
|
|
4170
4210
|
"FROM_STATE",
|
|
4171
4211
|
"ON_CHILD_FAILED",
|
|
4172
4212
|
"ON_PARENT_CLOSED",
|
|
4213
|
+
"MAX_ACTIVE_MS",
|
|
4173
4214
|
"VALUE",
|
|
4174
4215
|
"VALUE_REF"
|
|
4175
4216
|
])
|
|
@@ -4200,6 +4241,185 @@ function flowSearchPayload(args) {
|
|
|
4200
4241
|
return { opcode: OPCODES.flowSearch, payload: { type: args[0], ...payload } };
|
|
4201
4242
|
}
|
|
4202
4243
|
|
|
4244
|
+
// src/protocol-flow-signal.ts
|
|
4245
|
+
function flowSignalPayload(args) {
|
|
4246
|
+
if (args.length < 3) return void 0;
|
|
4247
|
+
const options = parseFlowOptions(args, 1, args.length, {
|
|
4248
|
+
allowed: /* @__PURE__ */ new Set([
|
|
4249
|
+
"SIGNAL",
|
|
4250
|
+
"PARTITION",
|
|
4251
|
+
"IDEMPOTENCY",
|
|
4252
|
+
"IF_STATE",
|
|
4253
|
+
"TRANSITION_TO",
|
|
4254
|
+
"RUN_AT",
|
|
4255
|
+
"NOW",
|
|
4256
|
+
"VALUE",
|
|
4257
|
+
"VALUE_REF",
|
|
4258
|
+
"DROP_VALUE",
|
|
4259
|
+
"OVERRIDE_VALUE"
|
|
4260
|
+
]),
|
|
4261
|
+
required: /* @__PURE__ */ new Set(["SIGNAL"])
|
|
4262
|
+
});
|
|
4263
|
+
if (options == null) return void 0;
|
|
4264
|
+
return { opcode: OPCODES.flowSignal, payload: { id: args[0], ...options } };
|
|
4265
|
+
}
|
|
4266
|
+
|
|
4267
|
+
// src/protocol-flow-policy.ts
|
|
4268
|
+
var import_node_buffer12 = require("buffer");
|
|
4269
|
+
var BACKOFF_FIELDS = {
|
|
4270
|
+
BASE_MS: "base_ms",
|
|
4271
|
+
MAX_MS: "max_ms",
|
|
4272
|
+
JITTER_PCT: "jitter_pct"
|
|
4273
|
+
};
|
|
4274
|
+
var RETENTION_FIELDS = {
|
|
4275
|
+
RETENTION_TTL: "ttl_ms",
|
|
4276
|
+
RETENTION_TTL_MS: "ttl_ms",
|
|
4277
|
+
HISTORY_MAX_EVENTS: "history_max_events"
|
|
4278
|
+
};
|
|
4279
|
+
function flowPolicySetPayload(args) {
|
|
4280
|
+
if (!hasOwnCommandArgument(args, 0, args.length, "Flow policy arguments")) return void 0;
|
|
4281
|
+
if (!isBinaryArgument(args[0])) return void 0;
|
|
4282
|
+
const payload = { type: args[0] };
|
|
4283
|
+
const states = {};
|
|
4284
|
+
let target = payload;
|
|
4285
|
+
for (let index = 1; index < args.length; index += 2) {
|
|
4286
|
+
if (!hasOwnCommandArgument(args, index, args.length, "Flow policy arguments") || !hasOwnCommandArgument(args, index + 1, args.length, "Flow policy arguments")) return void 0;
|
|
4287
|
+
const token = optionalText(args[index])?.toUpperCase();
|
|
4288
|
+
const value = args[index + 1];
|
|
4289
|
+
if (token == null || value == null) return void 0;
|
|
4290
|
+
if (token === "STATE") {
|
|
4291
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4292
|
+
const state = asText(value);
|
|
4293
|
+
target = {};
|
|
4294
|
+
setOwnValue2(states, state, target);
|
|
4295
|
+
setOwnValue2(payload, "states", states);
|
|
4296
|
+
continue;
|
|
4297
|
+
}
|
|
4298
|
+
if (token === "MODE") {
|
|
4299
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4300
|
+
const mode = optionalText(value)?.toLowerCase();
|
|
4301
|
+
if (target === payload || mode !== "fifo" && mode !== "parallel") return void 0;
|
|
4302
|
+
setOwnValue2(target, "mode", mode);
|
|
4303
|
+
continue;
|
|
4304
|
+
}
|
|
4305
|
+
if (token === "EXPECTED_GENERATION") {
|
|
4306
|
+
if (target !== payload) return void 0;
|
|
4307
|
+
const generation = integerOption(value);
|
|
4308
|
+
if (generation == null || generation < 0) return void 0;
|
|
4309
|
+
setOwnValue2(payload, "expected_generation", generation);
|
|
4310
|
+
continue;
|
|
4311
|
+
}
|
|
4312
|
+
if (token === "REPLACE") {
|
|
4313
|
+
if (target !== payload || !isBoolToken(value)) return void 0;
|
|
4314
|
+
setOwnValue2(payload, "replace", boolArg(value));
|
|
4315
|
+
continue;
|
|
4316
|
+
}
|
|
4317
|
+
if (token === "MAX_ACTIVE_MS") {
|
|
4318
|
+
if (target !== payload) return void 0;
|
|
4319
|
+
const maxActiveMs = maxActiveOption(value);
|
|
4320
|
+
if (maxActiveMs == null) return void 0;
|
|
4321
|
+
setOwnValue2(payload, "max_active_ms", maxActiveMs);
|
|
4322
|
+
continue;
|
|
4323
|
+
}
|
|
4324
|
+
if (token === "INDEXED_STATE_META") {
|
|
4325
|
+
if (target !== payload || !isBinaryArgument(value)) return void 0;
|
|
4326
|
+
setOwnValue2(payload, "indexed_state_meta", value);
|
|
4327
|
+
continue;
|
|
4328
|
+
}
|
|
4329
|
+
if (token === "INDEXED_ATTRIBUTES") {
|
|
4330
|
+
if (target !== payload) return void 0;
|
|
4331
|
+
const names = indexedAttributes(value);
|
|
4332
|
+
if (names == null) return void 0;
|
|
4333
|
+
setOwnValue2(payload, "indexed_attributes", names);
|
|
4334
|
+
continue;
|
|
4335
|
+
}
|
|
4336
|
+
if (token === "MAX_RETRIES") {
|
|
4337
|
+
const parsed = integerOption(value);
|
|
4338
|
+
if (parsed == null) return void 0;
|
|
4339
|
+
setOwnValue2(objectField(target, "retry"), "max_retries", parsed);
|
|
4340
|
+
continue;
|
|
4341
|
+
}
|
|
4342
|
+
if (token === "EXHAUSTED_TO") {
|
|
4343
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4344
|
+
setOwnValue2(objectField(target, "retry"), "exhausted_to", value);
|
|
4345
|
+
continue;
|
|
4346
|
+
}
|
|
4347
|
+
const backoffField = BACKOFF_FIELDS[token];
|
|
4348
|
+
if (backoffField != null) {
|
|
4349
|
+
const parsed = integerOption(value);
|
|
4350
|
+
if (parsed == null) return void 0;
|
|
4351
|
+
setOwnValue2(objectField(objectField(target, "retry"), "backoff"), backoffField, parsed);
|
|
4352
|
+
continue;
|
|
4353
|
+
}
|
|
4354
|
+
if (token === "BACKOFF") {
|
|
4355
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4356
|
+
const kind = optionalText(value)?.toLowerCase();
|
|
4357
|
+
if (kind == null) return void 0;
|
|
4358
|
+
setOwnValue2(objectField(objectField(target, "retry"), "backoff"), "kind", kind);
|
|
4359
|
+
continue;
|
|
4360
|
+
}
|
|
4361
|
+
const retentionField = RETENTION_FIELDS[token];
|
|
4362
|
+
if (retentionField != null) {
|
|
4363
|
+
if (target === payload) return void 0;
|
|
4364
|
+
const parsed = integerOption(value);
|
|
4365
|
+
if (parsed == null) return void 0;
|
|
4366
|
+
setOwnValue2(objectField(target, "retention"), retentionField, parsed);
|
|
4367
|
+
continue;
|
|
4368
|
+
}
|
|
4369
|
+
return void 0;
|
|
4370
|
+
}
|
|
4371
|
+
return { opcode: OPCODES.flowPolicySet, payload };
|
|
4372
|
+
}
|
|
4373
|
+
function flowPolicyGetPayload(args) {
|
|
4374
|
+
if (!hasOwnCommandArgument(args, 0, args.length, "Flow policy arguments")) return void 0;
|
|
4375
|
+
if (!isBinaryArgument(args[0])) return void 0;
|
|
4376
|
+
if (args.length !== 1 && args.length !== 3) return void 0;
|
|
4377
|
+
const payload = { type: args[0] };
|
|
4378
|
+
if (args.length === 3) {
|
|
4379
|
+
if (!hasOwnCommandArgument(args, 1, args.length, "Flow policy arguments") || !hasOwnCommandArgument(args, 2, args.length, "Flow policy arguments") || optionalText(args[1])?.toUpperCase() !== "STATE" || !isBinaryArgument(args[2])) return void 0;
|
|
4380
|
+
setOwnValue2(payload, "state", args[2]);
|
|
4381
|
+
}
|
|
4382
|
+
return { opcode: OPCODES.flowPolicyGet, payload };
|
|
4383
|
+
}
|
|
4384
|
+
function integerOption(value) {
|
|
4385
|
+
try {
|
|
4386
|
+
return safeIntegerNumberArg(value);
|
|
4387
|
+
} catch {
|
|
4388
|
+
return void 0;
|
|
4389
|
+
}
|
|
4390
|
+
}
|
|
4391
|
+
function maxActiveOption(value) {
|
|
4392
|
+
if (isBinaryArgument(value) && asText(value).toLowerCase() === "infinity") {
|
|
4393
|
+
return "infinity";
|
|
4394
|
+
}
|
|
4395
|
+
return integerOption(value);
|
|
4396
|
+
}
|
|
4397
|
+
function isBinaryArgument(value) {
|
|
4398
|
+
return typeof value === "string" || import_node_buffer12.Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
4399
|
+
}
|
|
4400
|
+
function objectField(target, name) {
|
|
4401
|
+
const existing = Object.hasOwn(target, name) ? target[name] : void 0;
|
|
4402
|
+
if (typeof existing === "object" && existing != null && !Array.isArray(existing)) {
|
|
4403
|
+
return existing;
|
|
4404
|
+
}
|
|
4405
|
+
const value = {};
|
|
4406
|
+
setOwnValue2(target, name, value);
|
|
4407
|
+
return value;
|
|
4408
|
+
}
|
|
4409
|
+
function indexedAttributes(value) {
|
|
4410
|
+
if (Array.isArray(value)) {
|
|
4411
|
+
return value.every((item) => typeof item === "string") ? value : void 0;
|
|
4412
|
+
}
|
|
4413
|
+
const source = optionalText(value);
|
|
4414
|
+
if (source == null) return void 0;
|
|
4415
|
+
try {
|
|
4416
|
+
const parsed = JSON.parse(source);
|
|
4417
|
+
return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
|
|
4418
|
+
} catch {
|
|
4419
|
+
return void 0;
|
|
4420
|
+
}
|
|
4421
|
+
}
|
|
4422
|
+
|
|
4203
4423
|
// src/protocol-connection-policy.ts
|
|
4204
4424
|
function assertCommandDoesNotRequirePinnedConnection(args) {
|
|
4205
4425
|
const outer = commandName(args[0]);
|
|
@@ -4391,7 +4611,7 @@ function compactArgumentsEligible(args, sparseMessage) {
|
|
|
4391
4611
|
}
|
|
4392
4612
|
return true;
|
|
4393
4613
|
}
|
|
4394
|
-
function compactPipelineEligible(commands,
|
|
4614
|
+
function compactPipelineEligible(commands, commandName5, argumentCount) {
|
|
4395
4615
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4396
4616
|
const command = commands[index];
|
|
4397
4617
|
if (!Object.hasOwn(commands, index) || !Array.isArray(command)) {
|
|
@@ -4403,7 +4623,7 @@ function compactPipelineEligible(commands, commandName4, argumentCount) {
|
|
|
4403
4623
|
throw new TypeError("pipeline command arguments must be dense");
|
|
4404
4624
|
}
|
|
4405
4625
|
}
|
|
4406
|
-
if (!commandNameIs(command[0],
|
|
4626
|
+
if (!commandNameIs(command[0], commandName5)) return false;
|
|
4407
4627
|
for (let argumentIndex = 1; argumentIndex < argumentCount; argumentIndex += 1) {
|
|
4408
4628
|
if (!isCompactBinaryScalar(command[argumentIndex])) return false;
|
|
4409
4629
|
}
|
|
@@ -4566,15 +4786,20 @@ function fetchOrComputeCommand(args) {
|
|
|
4566
4786
|
};
|
|
4567
4787
|
}
|
|
4568
4788
|
function fetchOrComputeResultCommand(args) {
|
|
4569
|
-
if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]))
|
|
4789
|
+
if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) {
|
|
4790
|
+
throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT requires key, ownership token, value, and ttl_ms");
|
|
4791
|
+
}
|
|
4570
4792
|
const ttlMs = positiveSafeInteger2(args[3]);
|
|
4571
|
-
|
|
4793
|
+
if (ttlMs == null) throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT ttl_ms must be positive");
|
|
4794
|
+
return {
|
|
4572
4795
|
opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_RESULT,
|
|
4573
4796
|
payload: { key: args[0], token: args[1], ttl_ms: ttlMs, value: args[2] }
|
|
4574
4797
|
};
|
|
4575
4798
|
}
|
|
4576
4799
|
function fetchOrComputeErrorCommand(args) {
|
|
4577
|
-
if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2]))
|
|
4800
|
+
if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2])) {
|
|
4801
|
+
throw new FerricStoreError("FETCH_OR_COMPUTE_ERROR requires key, ownership token, and message");
|
|
4802
|
+
}
|
|
4578
4803
|
return {
|
|
4579
4804
|
opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_ERROR,
|
|
4580
4805
|
payload: { key: args[0], message: args[2], token: args[1] }
|
|
@@ -4931,58 +5156,458 @@ function requireAvailable(data, offset, size) {
|
|
|
4931
5156
|
}
|
|
4932
5157
|
}
|
|
4933
5158
|
|
|
4934
|
-
// src/
|
|
5159
|
+
// src/key-slot-validation.ts
|
|
4935
5160
|
var import_node_buffer17 = require("buffer");
|
|
4936
5161
|
|
|
4937
|
-
// src/
|
|
5162
|
+
// src/topology-utilities.ts
|
|
4938
5163
|
var import_node_buffer16 = require("buffer");
|
|
4939
|
-
function
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
if (
|
|
4944
|
-
const
|
|
4945
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
5164
|
+
function isPlainObject3(value) {
|
|
5165
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer16.Buffer.isBuffer(value);
|
|
5166
|
+
}
|
|
5167
|
+
function getField(source, ...keys) {
|
|
5168
|
+
if (source instanceof Map) {
|
|
5169
|
+
for (const key of keys) {
|
|
5170
|
+
if (source.has(key)) return source.get(key);
|
|
5171
|
+
const bufferKey = import_node_buffer16.Buffer.from(key);
|
|
5172
|
+
for (const [itemKey, value] of source.entries()) {
|
|
5173
|
+
if (import_node_buffer16.Buffer.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
return void 0;
|
|
4949
5177
|
}
|
|
4950
|
-
if ((
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
};
|
|
5178
|
+
if (isPlainObject3(source)) {
|
|
5179
|
+
for (const key of keys) {
|
|
5180
|
+
if (Object.hasOwn(source, key)) return source[key];
|
|
5181
|
+
}
|
|
4955
5182
|
}
|
|
4956
|
-
|
|
4957
|
-
|
|
5183
|
+
return void 0;
|
|
5184
|
+
}
|
|
5185
|
+
function textOrUndefined(value) {
|
|
5186
|
+
if (typeof value === "string") return value;
|
|
5187
|
+
if (import_node_buffer16.Buffer.isBuffer(value)) return value.toString("utf8");
|
|
5188
|
+
return void 0;
|
|
5189
|
+
}
|
|
5190
|
+
function numberOrUndefined(value) {
|
|
5191
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
5192
|
+
}
|
|
5193
|
+
function nativeEventName(event) {
|
|
5194
|
+
return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
|
|
5195
|
+
}
|
|
5196
|
+
function endpointFromRange(item) {
|
|
5197
|
+
const endpointValue = getField(item, "endpoint");
|
|
5198
|
+
if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
|
|
5199
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4958
5200
|
}
|
|
4959
|
-
|
|
4960
|
-
|
|
5201
|
+
const raw = endpointValue ?? item;
|
|
5202
|
+
const host = textOrUndefined(getField(raw, "host", "native_host"));
|
|
5203
|
+
const nativePort = numberOrUndefined(getField(raw, "native_port"));
|
|
5204
|
+
if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
|
|
5205
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4961
5206
|
}
|
|
4962
|
-
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
5207
|
+
const nativeTlsPortValue = getField(raw, "native_tls_port");
|
|
5208
|
+
const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
|
|
5209
|
+
if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
|
|
5210
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4966
5211
|
}
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
5212
|
+
return {
|
|
5213
|
+
host,
|
|
5214
|
+
nativePort,
|
|
5215
|
+
node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
|
|
5216
|
+
...nativeTlsPort == null ? {} : { nativeTlsPort }
|
|
5217
|
+
};
|
|
5218
|
+
}
|
|
5219
|
+
function validEndpointHost(host) {
|
|
5220
|
+
if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
|
|
5221
|
+
const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
5222
|
+
try {
|
|
5223
|
+
const url = new URL(`ferric://${authorityHost}:6388`);
|
|
5224
|
+
return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
|
|
5225
|
+
} catch {
|
|
5226
|
+
return false;
|
|
4971
5227
|
}
|
|
4972
|
-
return { found: false, value: void 0 };
|
|
4973
5228
|
}
|
|
4974
|
-
function
|
|
4975
|
-
return
|
|
5229
|
+
function sameEndpoint(left, right) {
|
|
5230
|
+
return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
|
|
4976
5231
|
}
|
|
4977
|
-
function
|
|
4978
|
-
|
|
5232
|
+
function parseFerricUrl2(value) {
|
|
5233
|
+
const url = new URL(value);
|
|
5234
|
+
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
5235
|
+
throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
|
|
5236
|
+
}
|
|
5237
|
+
return {
|
|
5238
|
+
host: normalizeFerricUrlHost(url.hostname),
|
|
5239
|
+
...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
|
|
5240
|
+
port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
|
|
5241
|
+
tls: url.protocol === "ferrics:",
|
|
5242
|
+
...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
|
|
5243
|
+
};
|
|
4979
5244
|
}
|
|
4980
|
-
function
|
|
4981
|
-
|
|
4982
|
-
|
|
5245
|
+
function endpointKeyFor(endpoint) {
|
|
5246
|
+
return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
|
|
5247
|
+
}
|
|
5248
|
+
function connectionKeyForEndpoint(endpoint, useTls) {
|
|
5249
|
+
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
5250
|
+
return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
|
|
5251
|
+
}
|
|
5252
|
+
function connectionKeyFromUrl(url) {
|
|
5253
|
+
const parsed = parseFerricUrl2(url);
|
|
5254
|
+
return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
|
|
5255
|
+
}
|
|
5256
|
+
function normalizedEndpointHost(host) {
|
|
5257
|
+
const lower = host.toLowerCase();
|
|
5258
|
+
return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
|
|
5259
|
+
}
|
|
5260
|
+
function urlFromEndpoint(endpoint, useTls) {
|
|
5261
|
+
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
5262
|
+
const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
|
|
5263
|
+
return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
|
|
5264
|
+
}
|
|
5265
|
+
async function mapSettledWithConcurrency(items, concurrency, operation) {
|
|
5266
|
+
const results = new Array(items.length);
|
|
5267
|
+
let nextIndex = 0;
|
|
5268
|
+
const worker = async () => {
|
|
5269
|
+
while (nextIndex < items.length) {
|
|
5270
|
+
const index = nextIndex++;
|
|
5271
|
+
const item = items[index];
|
|
5272
|
+
try {
|
|
5273
|
+
results[index] = { status: "fulfilled", value: await operation(item, index) };
|
|
5274
|
+
} catch (reason) {
|
|
5275
|
+
results[index] = { status: "rejected", reason };
|
|
5276
|
+
}
|
|
5277
|
+
}
|
|
5278
|
+
};
|
|
5279
|
+
await Promise.all(Array.from(
|
|
5280
|
+
{ length: Math.min(concurrency, items.length) },
|
|
5281
|
+
async () => await worker()
|
|
5282
|
+
));
|
|
5283
|
+
return results;
|
|
5284
|
+
}
|
|
5285
|
+
function throwFirstRejected(results) {
|
|
5286
|
+
for (const result of results) {
|
|
5287
|
+
if (result.status === "rejected") throw result.reason;
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
var TaskConcurrencyLimiter = class {
|
|
5291
|
+
constructor(concurrency) {
|
|
5292
|
+
this.concurrency = concurrency;
|
|
5293
|
+
}
|
|
5294
|
+
concurrency;
|
|
5295
|
+
active = 0;
|
|
5296
|
+
head = 0;
|
|
5297
|
+
pending = [];
|
|
5298
|
+
async run(operation) {
|
|
5299
|
+
await this.acquire();
|
|
5300
|
+
try {
|
|
5301
|
+
return await operation();
|
|
5302
|
+
} finally {
|
|
5303
|
+
this.release();
|
|
5304
|
+
}
|
|
5305
|
+
}
|
|
5306
|
+
acquire() {
|
|
5307
|
+
if (this.active < this.concurrency) {
|
|
5308
|
+
this.active += 1;
|
|
5309
|
+
return Promise.resolve();
|
|
5310
|
+
}
|
|
5311
|
+
return new Promise((resolve) => this.pending.push(resolve));
|
|
5312
|
+
}
|
|
5313
|
+
release() {
|
|
5314
|
+
const next = this.pending[this.head];
|
|
5315
|
+
if (next == null) {
|
|
5316
|
+
this.active -= 1;
|
|
5317
|
+
return;
|
|
5318
|
+
}
|
|
5319
|
+
this.head += 1;
|
|
5320
|
+
next();
|
|
5321
|
+
if (this.head === this.pending.length) {
|
|
5322
|
+
this.pending.length = 0;
|
|
5323
|
+
this.head = 0;
|
|
5324
|
+
} else if (this.head >= 1024 && this.head * 2 >= this.pending.length) {
|
|
5325
|
+
this.pending.splice(0, this.head);
|
|
5326
|
+
this.head = 0;
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5329
|
+
};
|
|
5330
|
+
function normalizedHostSet(hosts) {
|
|
5331
|
+
return new Set(
|
|
5332
|
+
hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
|
|
5333
|
+
);
|
|
5334
|
+
}
|
|
5335
|
+
var OPEN_BRACE = "{".charCodeAt(0);
|
|
5336
|
+
var CLOSE_BRACE = "}".charCodeAt(0);
|
|
5337
|
+
function hashTagOrKey(key) {
|
|
5338
|
+
const start = key.indexOf(OPEN_BRACE);
|
|
5339
|
+
if (start < 0) return key;
|
|
5340
|
+
const end = key.indexOf(CLOSE_BRACE, start + 1);
|
|
5341
|
+
return end > start + 1 ? key.subarray(start + 1, end) : key;
|
|
5342
|
+
}
|
|
5343
|
+
var ROUTE_SLOT_MASK = 1023;
|
|
5344
|
+
function routingSlotForKey(key) {
|
|
5345
|
+
if (typeof key === "string") {
|
|
5346
|
+
const [start, end] = stringHashRange(key);
|
|
5347
|
+
return crc32Utf8(key, start, end) & ROUTE_SLOT_MASK;
|
|
5348
|
+
}
|
|
5349
|
+
const keyBytes = key;
|
|
5350
|
+
return crc32(hashTagOrKey(keyBytes)) & ROUTE_SLOT_MASK;
|
|
5351
|
+
}
|
|
5352
|
+
function stringHashRange(key) {
|
|
5353
|
+
const startBrace = key.indexOf("{");
|
|
5354
|
+
const endBrace = startBrace < 0 ? -1 : key.indexOf("}", startBrace + 1);
|
|
5355
|
+
return endBrace > startBrace + 1 ? [startBrace + 1, endBrace] : [0, key.length];
|
|
5356
|
+
}
|
|
5357
|
+
|
|
5358
|
+
// src/key-slot-validation.ts
|
|
5359
|
+
var validatedCommands = /* @__PURE__ */ new WeakSet();
|
|
5360
|
+
function assertAtomicKeyValueCommandSharesSlot(args) {
|
|
5361
|
+
const value = args[0];
|
|
5362
|
+
const command = (typeof value === "string" ? value : import_node_buffer17.Buffer.isBuffer(value) ? value.toString("utf8") : "").toUpperCase();
|
|
5363
|
+
if (command === "MSET" || command === "MSETNX") {
|
|
5364
|
+
assertKeyValueCommandSharesSlot(args, command);
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
function assertKeyValueCommandSharesSlot(args, command) {
|
|
5368
|
+
if (validatedCommands.has(args) || args.length < 3 || args.length % 2 === 0) return;
|
|
5369
|
+
let expectedSlot;
|
|
5370
|
+
for (let index = 1; index < args.length; index += 2) {
|
|
5371
|
+
const key = args[index];
|
|
5372
|
+
if (typeof key !== "string" && !import_node_buffer17.Buffer.isBuffer(key)) return;
|
|
5373
|
+
const slot = routingSlotForKey(key);
|
|
5374
|
+
expectedSlot ??= slot;
|
|
5375
|
+
if (slot !== expectedSlot) {
|
|
5376
|
+
throw new TypeError(`${command} keys must share a slot`);
|
|
5377
|
+
}
|
|
5378
|
+
}
|
|
5379
|
+
validatedCommands.add(args);
|
|
5380
|
+
}
|
|
5381
|
+
|
|
5382
|
+
// src/protocol-response.ts
|
|
5383
|
+
var import_node_buffer21 = require("buffer");
|
|
5384
|
+
|
|
5385
|
+
// src/protocol-compact-response.ts
|
|
5386
|
+
var import_node_buffer20 = require("buffer");
|
|
5387
|
+
|
|
5388
|
+
// src/native-negotiation.ts
|
|
5389
|
+
var import_node_buffer18 = require("buffer");
|
|
5390
|
+
var EMPTY_COMPACT_RESPONSE_OPCODES = /* @__PURE__ */ new Map();
|
|
5391
|
+
function nativeNegotiation(value) {
|
|
5392
|
+
const capabilities = field(value, "capabilities") ?? value;
|
|
5393
|
+
const limits = field(capabilities, "limits");
|
|
5394
|
+
const responseCodecs = field(capabilities, "response_codecs");
|
|
5395
|
+
const maxResponseBytes = positiveSafeInteger3(field(limits, "max_response_bytes"));
|
|
5396
|
+
return {
|
|
5397
|
+
compactResponseOpcodes: parseCompactResponseOpcodes(
|
|
5398
|
+
field(responseCodecs, "compact_response_opcodes")
|
|
5399
|
+
),
|
|
5400
|
+
...maxResponseBytes == null ? {} : { maxResponseBytes }
|
|
5401
|
+
};
|
|
5402
|
+
}
|
|
5403
|
+
function compactResponseOpcodeSupports(capabilities, codec, opcode) {
|
|
5404
|
+
return capabilities?.get(codec)?.has(opcode) === true;
|
|
5405
|
+
}
|
|
5406
|
+
function parseCompactResponseOpcodes(value) {
|
|
5407
|
+
const entries = mapEntries(value);
|
|
5408
|
+
if (entries == null) return EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
5409
|
+
const result = /* @__PURE__ */ new Map();
|
|
5410
|
+
for (const [rawName, rawOpcodes] of entries) {
|
|
5411
|
+
const name = text2(rawName);
|
|
5412
|
+
if (name == null || name.length === 0 || !Array.isArray(rawOpcodes)) continue;
|
|
5413
|
+
const opcodes = /* @__PURE__ */ new Set();
|
|
5414
|
+
let valid = true;
|
|
5415
|
+
for (let index = 0; index < rawOpcodes.length; index += 1) {
|
|
5416
|
+
if (!Object.hasOwn(rawOpcodes, index)) {
|
|
5417
|
+
valid = false;
|
|
5418
|
+
break;
|
|
5419
|
+
}
|
|
5420
|
+
const opcode = unsigned16(rawOpcodes[index]);
|
|
5421
|
+
if (opcode == null) {
|
|
5422
|
+
valid = false;
|
|
5423
|
+
break;
|
|
5424
|
+
}
|
|
5425
|
+
opcodes.add(opcode);
|
|
5426
|
+
}
|
|
5427
|
+
if (valid) result.set(name, opcodes);
|
|
5428
|
+
}
|
|
5429
|
+
return result;
|
|
5430
|
+
}
|
|
5431
|
+
function mapEntries(value) {
|
|
5432
|
+
if (value instanceof Map) return [...value.entries()];
|
|
5433
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return void 0;
|
|
5434
|
+
return Object.entries(value);
|
|
5435
|
+
}
|
|
5436
|
+
function unsigned16(value) {
|
|
5437
|
+
const parsed = nonNegativeSafeInteger2(value);
|
|
5438
|
+
return parsed != null && parsed <= 65535 ? parsed : void 0;
|
|
5439
|
+
}
|
|
5440
|
+
function positiveSafeInteger3(value) {
|
|
5441
|
+
const parsed = nonNegativeSafeInteger2(value);
|
|
5442
|
+
return parsed != null && parsed > 0 ? parsed : void 0;
|
|
5443
|
+
}
|
|
5444
|
+
function nonNegativeSafeInteger2(value) {
|
|
5445
|
+
if (typeof value === "bigint") {
|
|
5446
|
+
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
5447
|
+
}
|
|
5448
|
+
const source = text2(value) ?? value;
|
|
5449
|
+
if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
|
|
5450
|
+
return void 0;
|
|
5451
|
+
}
|
|
5452
|
+
const parsed = Number(source);
|
|
5453
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
|
|
5454
|
+
}
|
|
5455
|
+
function text2(value) {
|
|
5456
|
+
if (typeof value === "string") return value;
|
|
5457
|
+
if (import_node_buffer18.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
5458
|
+
return import_node_buffer18.Buffer.from(value).toString("utf8");
|
|
5459
|
+
}
|
|
5460
|
+
return void 0;
|
|
5461
|
+
}
|
|
5462
|
+
|
|
5463
|
+
// src/protocol-compact-collections.ts
|
|
5464
|
+
var import_node_buffer19 = require("buffer");
|
|
5465
|
+
function decodeCompactIntegerList(data, budget) {
|
|
5466
|
+
requireAvailable(data, 0, 5);
|
|
5467
|
+
const count = data.readUInt32BE(1);
|
|
4983
5468
|
requireCompactContainer(count, budget);
|
|
5469
|
+
if (data.byteLength !== 5 + count * 8) {
|
|
5470
|
+
throw new FerricStoreError("invalid compact integer list response");
|
|
5471
|
+
}
|
|
5472
|
+
const values = new Array(count);
|
|
5473
|
+
for (let index = 0, offset = 5; index < count; index += 1, offset += 8) {
|
|
5474
|
+
const value = data.readBigInt64BE(offset);
|
|
5475
|
+
values[index] = value <= MAX_SAFE_INTEGER_BIGINT && value >= MIN_SAFE_INTEGER_BIGINT ? Number(value) : value;
|
|
5476
|
+
}
|
|
5477
|
+
return values;
|
|
5478
|
+
}
|
|
5479
|
+
function decodeCompactBinaryListList(data, budget) {
|
|
5480
|
+
requireAvailable(data, 0, 5);
|
|
5481
|
+
const count = data.readUInt32BE(1);
|
|
5482
|
+
requireCompactContainer(count, budget);
|
|
5483
|
+
let offset = 5;
|
|
5484
|
+
const values = new Array(count);
|
|
5485
|
+
for (let index = 0; index < count; index += 1) {
|
|
5486
|
+
const read = readCompactBinaryList(data, offset, budget);
|
|
5487
|
+
values[index] = read.value;
|
|
5488
|
+
offset = read.offset;
|
|
5489
|
+
}
|
|
5490
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary list-list bytes");
|
|
5491
|
+
return values;
|
|
5492
|
+
}
|
|
5493
|
+
function decodeCompactBinaryMapList(data, budget) {
|
|
5494
|
+
requireAvailable(data, 0, 5);
|
|
5495
|
+
const count = data.readUInt32BE(1);
|
|
5496
|
+
requireCompactContainer(count, budget);
|
|
5497
|
+
let offset = 5;
|
|
5498
|
+
const values = new Array(count);
|
|
5499
|
+
for (let index = 0; index < count; index += 1) {
|
|
5500
|
+
const read = readCompactBinaryMap(data, offset, budget);
|
|
5501
|
+
values[index] = read.value;
|
|
5502
|
+
offset = read.offset;
|
|
5503
|
+
}
|
|
5504
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary map-list bytes");
|
|
5505
|
+
return values;
|
|
5506
|
+
}
|
|
5507
|
+
function readCompactBinaryList(data, offset, budget) {
|
|
5508
|
+
requireAvailable(data, offset, 4);
|
|
5509
|
+
const count = data.readUInt32BE(offset);
|
|
5510
|
+
requireCompactContainer(count, budget);
|
|
5511
|
+
offset += 4;
|
|
5512
|
+
const values = new Array(count);
|
|
5513
|
+
for (let index = 0; index < count; index += 1) {
|
|
5514
|
+
const read = readBinary(data, offset);
|
|
5515
|
+
values[index] = read.value;
|
|
5516
|
+
offset = read.offset;
|
|
5517
|
+
}
|
|
5518
|
+
return { value: values, offset };
|
|
5519
|
+
}
|
|
5520
|
+
function readCompactBinaryMap(data, offset, budget) {
|
|
5521
|
+
requireAvailable(data, offset, 4);
|
|
5522
|
+
const count = data.readUInt32BE(offset);
|
|
5523
|
+
requireCompactContainer(count, budget);
|
|
5524
|
+
offset += 4;
|
|
5525
|
+
const values = {};
|
|
5526
|
+
for (let index = 0; index < count; index += 1) {
|
|
5527
|
+
const key = readBinary(data, offset);
|
|
5528
|
+
const value = readBinary(data, key.offset);
|
|
5529
|
+
setOwnValue2(values, key.value.toString("utf8"), value.value);
|
|
5530
|
+
offset = value.offset;
|
|
5531
|
+
}
|
|
5532
|
+
return { value: values, offset };
|
|
5533
|
+
}
|
|
5534
|
+
function markCompactPipelineDecoded(values) {
|
|
5535
|
+
Object.defineProperty(values, COMPACT_PIPELINE_DECODED, { value: true });
|
|
5536
|
+
return values;
|
|
5537
|
+
}
|
|
5538
|
+
function requireCompactContainer(count, budget) {
|
|
5539
|
+
if (count > DEFAULT_MAX_VALUE_ITEMS) {
|
|
5540
|
+
throw new FerricStoreError("native compact response container exceeds max items");
|
|
5541
|
+
}
|
|
5542
|
+
consumeDecodeItems(count, budget);
|
|
5543
|
+
}
|
|
5544
|
+
|
|
5545
|
+
// src/protocol-compact-response.ts
|
|
5546
|
+
function tryDecodeCompactResponse(opcode, body, hints) {
|
|
5547
|
+
if (body.byteLength === 0) return { found: false, value: void 0 };
|
|
5548
|
+
const budget = { remainingItems: DEFAULT_MAX_VALUE_ITEMS };
|
|
5549
|
+
const tag = body.readUInt8(0);
|
|
5550
|
+
const pipelineValues = opcode === OPCODES.pipeline && supports(hints, "pipeline_v1", opcode);
|
|
5551
|
+
if (tag === COMPACT_OK_LIST && (supports(hints, "ok_list_v1", opcode) || pipelineValues)) {
|
|
5552
|
+
const values = decodeCompactOkList(body, budget);
|
|
5553
|
+
return {
|
|
5554
|
+
found: true,
|
|
5555
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values.length === 1 ? "OK" : values
|
|
5556
|
+
};
|
|
5557
|
+
}
|
|
5558
|
+
if (tag === COMPACT_KV_GET && supports(hints, "kv_get_v1", opcode)) {
|
|
5559
|
+
return { found: true, value: decodeCompactKvGet(body) };
|
|
5560
|
+
}
|
|
5561
|
+
if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && (supports(hints, "kv_mget_v1", opcode) || pipelineValues)) {
|
|
5562
|
+
const values = tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget);
|
|
5563
|
+
return {
|
|
5564
|
+
found: true,
|
|
5565
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5566
|
+
};
|
|
5567
|
+
}
|
|
5568
|
+
if (tag === COMPACT_INTEGER_LIST && pipelineValues) {
|
|
5569
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactIntegerList(body, budget)) };
|
|
5570
|
+
}
|
|
5571
|
+
if (tag === COMPACT_BINARY_LIST_LIST && pipelineValues) {
|
|
5572
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryListList(body, budget)) };
|
|
5573
|
+
}
|
|
5574
|
+
if (tag === COMPACT_BINARY_MAP_LIST && pipelineValues) {
|
|
5575
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryMapList(body, budget)) };
|
|
5576
|
+
}
|
|
5577
|
+
if (tag === COMPACT_PIPELINE_RESPONSE && pipelineValues) {
|
|
5578
|
+
return { found: true, value: decodeCompactPipeline(body, budget, hints.pipelineClaimModes) };
|
|
5579
|
+
}
|
|
5580
|
+
if (tag === COMPACT_FLOW_CLAIM_JOBS && (supports(hints, "flow_claim_jobs_v1", opcode) || pipelineValues)) {
|
|
5581
|
+
const values = decodeCompactClaimJobs(body, budget, hints.compactClaimMode);
|
|
5582
|
+
return {
|
|
5583
|
+
found: true,
|
|
5584
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5585
|
+
};
|
|
5586
|
+
}
|
|
5587
|
+
if (tag === COMPACT_FLOW_RECORD && supports(hints, "flow_record_v1", opcode)) {
|
|
5588
|
+
const read = readCompactFlowRecord(body, 0, budget);
|
|
5589
|
+
if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record bytes");
|
|
5590
|
+
return { found: true, value: read.value };
|
|
5591
|
+
}
|
|
5592
|
+
if (tag === COMPACT_FLOW_RECORD_LIST && (supports(hints, "flow_record_list_v1", opcode) || pipelineValues)) {
|
|
5593
|
+
const read = readCompactFlowRecordList(body, 0, budget);
|
|
5594
|
+
if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record list bytes");
|
|
5595
|
+
return {
|
|
5596
|
+
found: true,
|
|
5597
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(read.value) : read.value
|
|
5598
|
+
};
|
|
5599
|
+
}
|
|
5600
|
+
return { found: false, value: void 0 };
|
|
5601
|
+
}
|
|
5602
|
+
function supports(hints, codec, opcode) {
|
|
5603
|
+
return compactResponseOpcodeSupports(hints.compactResponseOpcodes, codec, opcode);
|
|
5604
|
+
}
|
|
5605
|
+
function decodeCompactOkList(data, budget) {
|
|
5606
|
+
requireAvailable(data, 0, 5);
|
|
5607
|
+
const count = data.readUInt32BE(1);
|
|
5608
|
+
requireCompactContainer2(count, budget);
|
|
4984
5609
|
if (data.byteLength !== 5) throw new FerricStoreError("invalid compact OK list response");
|
|
4985
|
-
return Array.from({ length: count }, () =>
|
|
5610
|
+
return Array.from({ length: count }, () => import_node_buffer20.Buffer.from("OK"));
|
|
4986
5611
|
}
|
|
4987
5612
|
function decodeCompactKvGet(data) {
|
|
4988
5613
|
requireAvailable(data, 0, 2);
|
|
@@ -4999,7 +5624,7 @@ function decodeCompactKvGet(data) {
|
|
|
4999
5624
|
function decodeCompactMget(data, budget) {
|
|
5000
5625
|
requireAvailable(data, 0, 5);
|
|
5001
5626
|
const count = data.readUInt32BE(1);
|
|
5002
|
-
|
|
5627
|
+
requireCompactContainer2(count, budget);
|
|
5003
5628
|
let offset = 5;
|
|
5004
5629
|
const values = [];
|
|
5005
5630
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -5023,12 +5648,12 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
5023
5648
|
requireAvailable(data, 0, 9);
|
|
5024
5649
|
const count = data.readUInt32BE(1);
|
|
5025
5650
|
const size = data.readUInt32BE(5);
|
|
5026
|
-
|
|
5651
|
+
requireCompactContainer2(count, budget);
|
|
5027
5652
|
const expected = 9 + count * size;
|
|
5028
5653
|
if (size === NULL_U32 || data.byteLength !== expected) {
|
|
5029
5654
|
throw new FerricStoreError("invalid compact fixed MGET response");
|
|
5030
5655
|
}
|
|
5031
|
-
if (size === 0) return new Array(count).fill(
|
|
5656
|
+
if (size === 0) return new Array(count).fill(import_node_buffer20.Buffer.alloc(0));
|
|
5032
5657
|
const values = new Array(count);
|
|
5033
5658
|
for (let index = 0, offset = 9; index < count; index += 1, offset += size) {
|
|
5034
5659
|
values[index] = data.subarray(offset, offset + size);
|
|
@@ -5038,7 +5663,7 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
5038
5663
|
function decodeCompactPipeline(data, budget, claimModes) {
|
|
5039
5664
|
requireAvailable(data, 0, 5);
|
|
5040
5665
|
const count = data.readUInt32BE(1);
|
|
5041
|
-
|
|
5666
|
+
requireCompactContainer2(count, budget);
|
|
5042
5667
|
if (count > Math.floor((data.byteLength - 5) / 2)) {
|
|
5043
5668
|
throw new FerricStoreError("compact pipeline item count exceeds response bytes");
|
|
5044
5669
|
}
|
|
@@ -5100,13 +5725,12 @@ function decodeCompactPipeline(data, budget, claimModes) {
|
|
|
5100
5725
|
}
|
|
5101
5726
|
}
|
|
5102
5727
|
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact pipeline bytes");
|
|
5103
|
-
|
|
5104
|
-
return values;
|
|
5728
|
+
return markCompactPipelineDecoded(values);
|
|
5105
5729
|
}
|
|
5106
5730
|
function decodeCompactClaimJobs(data, budget, mode) {
|
|
5107
5731
|
requireAvailable(data, 0, 5);
|
|
5108
5732
|
const count = data.readUInt32BE(1);
|
|
5109
|
-
|
|
5733
|
+
requireCompactContainer2(count, budget);
|
|
5110
5734
|
if (mode != null) {
|
|
5111
5735
|
const values = [];
|
|
5112
5736
|
let offset = 5;
|
|
@@ -5190,7 +5814,7 @@ function readCompactFlowRecord(data, offset, budget = { remainingItems: DEFAULT_
|
|
|
5190
5814
|
if (data.readUInt8(offset) !== COMPACT_FLOW_RECORD) throw new FerricStoreError("expected compact Flow record");
|
|
5191
5815
|
offset += 1;
|
|
5192
5816
|
const count = data.readUInt32BE(offset);
|
|
5193
|
-
|
|
5817
|
+
requireCompactContainer2(count, budget);
|
|
5194
5818
|
offset += 4;
|
|
5195
5819
|
const record = {};
|
|
5196
5820
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -5218,7 +5842,7 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
|
|
|
5218
5842
|
}
|
|
5219
5843
|
offset += 1;
|
|
5220
5844
|
const count = data.readUInt32BE(offset);
|
|
5221
|
-
|
|
5845
|
+
requireCompactContainer2(count, budget);
|
|
5222
5846
|
offset += 4;
|
|
5223
5847
|
const records = [];
|
|
5224
5848
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -5228,33 +5852,6 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
|
|
|
5228
5852
|
}
|
|
5229
5853
|
return { value: records, offset };
|
|
5230
5854
|
}
|
|
5231
|
-
function readCompactBinaryList(data, offset, budget) {
|
|
5232
|
-
requireAvailable(data, offset, 4);
|
|
5233
|
-
const count = data.readUInt32BE(offset);
|
|
5234
|
-
requireCompactContainer(count, budget);
|
|
5235
|
-
offset += 4;
|
|
5236
|
-
const values = [];
|
|
5237
|
-
for (let index = 0; index < count; index += 1) {
|
|
5238
|
-
const read = readBinary(data, offset);
|
|
5239
|
-
values.push(read.value);
|
|
5240
|
-
offset = read.offset;
|
|
5241
|
-
}
|
|
5242
|
-
return { value: values, offset };
|
|
5243
|
-
}
|
|
5244
|
-
function readCompactBinaryMap(data, offset, budget) {
|
|
5245
|
-
requireAvailable(data, offset, 4);
|
|
5246
|
-
const count = data.readUInt32BE(offset);
|
|
5247
|
-
requireCompactContainer(count, budget);
|
|
5248
|
-
offset += 4;
|
|
5249
|
-
const values = {};
|
|
5250
|
-
for (let index = 0; index < count; index += 1) {
|
|
5251
|
-
const key = readBinary(data, offset);
|
|
5252
|
-
const value = readBinary(data, key.offset);
|
|
5253
|
-
setOwnValue2(values, key.value.toString("utf8"), value.value);
|
|
5254
|
-
offset = value.offset;
|
|
5255
|
-
}
|
|
5256
|
-
return { value: values, offset };
|
|
5257
|
-
}
|
|
5258
5855
|
function readOptionalBinary(data, offset) {
|
|
5259
5856
|
requireAvailable(data, offset, 4);
|
|
5260
5857
|
const size = data.readUInt32BE(offset);
|
|
@@ -5263,7 +5860,7 @@ function readOptionalBinary(data, offset) {
|
|
|
5263
5860
|
requireAvailable(data, offset, size);
|
|
5264
5861
|
return { value: data.subarray(offset, offset + size), offset: offset + size };
|
|
5265
5862
|
}
|
|
5266
|
-
function
|
|
5863
|
+
function requireCompactContainer2(count, budget) {
|
|
5267
5864
|
if (count > DEFAULT_MAX_VALUE_ITEMS) {
|
|
5268
5865
|
throw new FerricStoreError("native compact response container exceeds max items");
|
|
5269
5866
|
}
|
|
@@ -5271,7 +5868,7 @@ function requireCompactContainer(count, budget) {
|
|
|
5271
5868
|
}
|
|
5272
5869
|
function errorMessage(status, value) {
|
|
5273
5870
|
if (typeof value === "string") return value;
|
|
5274
|
-
if (
|
|
5871
|
+
if (import_node_buffer20.Buffer.isBuffer(value)) return value.toString("utf8");
|
|
5275
5872
|
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5276
5873
|
const message = value.message;
|
|
5277
5874
|
return typeof message === "string" ? message : String(message);
|
|
@@ -5351,7 +5948,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5351
5948
|
return out;
|
|
5352
5949
|
}
|
|
5353
5950
|
function pipelineStatus(value) {
|
|
5354
|
-
if (typeof value !== "string" && !
|
|
5951
|
+
if (typeof value !== "string" && !import_node_buffer21.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) return null;
|
|
5355
5952
|
const status = asText(value).toLowerCase();
|
|
5356
5953
|
return status === "ok" || status === "busy" || status === "error" ? status : null;
|
|
5357
5954
|
}
|
|
@@ -5366,7 +5963,7 @@ function decodeResponseValue(opcode, body, hints) {
|
|
|
5366
5963
|
}
|
|
5367
5964
|
function errorMessage2(status, value) {
|
|
5368
5965
|
if (typeof value === "string") return value;
|
|
5369
|
-
if (
|
|
5966
|
+
if (import_node_buffer21.Buffer.isBuffer(value)) return value.toString("utf8");
|
|
5370
5967
|
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5371
5968
|
const message = value.message;
|
|
5372
5969
|
return typeof message === "string" ? message : String(message);
|
|
@@ -5382,7 +5979,7 @@ function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGE
|
|
|
5382
5979
|
const bodyLength = customPayload ? binaryValueByteLength(command.payload) : plan?.byteLength ?? 0;
|
|
5383
5980
|
if (bodyLength > bodyLimit) throw requestFrameTooLarge(bodyLimit);
|
|
5384
5981
|
const flags = command.flags ?? 0;
|
|
5385
|
-
const frame =
|
|
5982
|
+
const frame = import_node_buffer22.Buffer.allocUnsafe(HEADER_SIZE + bodyLength);
|
|
5386
5983
|
frame.write(MAGIC, 0, "ascii");
|
|
5387
5984
|
frame.writeUInt8(REQUEST_VERSION, 4);
|
|
5388
5985
|
frame.writeUInt8(flags, 5);
|
|
@@ -5433,6 +6030,9 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5433
6030
|
}
|
|
5434
6031
|
const command = asText(args[0]).toUpperCase();
|
|
5435
6032
|
assertNormalizedCommandDoesNotRequirePinnedConnection(args, command);
|
|
6033
|
+
if (command === "MSET" || command === "MSETNX") {
|
|
6034
|
+
assertKeyValueCommandSharesSlot(args, command);
|
|
6035
|
+
}
|
|
5436
6036
|
const commandArgs2 = args.slice(1);
|
|
5437
6037
|
if (command === "COMMAND_EXEC" && commandArgs2.length >= 1) {
|
|
5438
6038
|
return commandExec(commandArgs2);
|
|
@@ -5504,6 +6104,12 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5504
6104
|
if (command === "FLOW.LIST") {
|
|
5505
6105
|
return (allowCustomPayload ? compactFlowListPayload(commandArgs2, maxBodyBytes) : void 0) ?? commandExec(args);
|
|
5506
6106
|
}
|
|
6107
|
+
if (command === "FLOW.POLICY.SET") {
|
|
6108
|
+
return flowPolicySetPayload(commandArgs2) ?? commandExec(args);
|
|
6109
|
+
}
|
|
6110
|
+
if (command === "FLOW.POLICY.GET") {
|
|
6111
|
+
return flowPolicyGetPayload(commandArgs2) ?? commandExec(args);
|
|
6112
|
+
}
|
|
5507
6113
|
const flowAdmin = FLOW_ADMIN_COMMANDS[command];
|
|
5508
6114
|
if (flowAdmin != null) {
|
|
5509
6115
|
return flowAdminPayload(flowAdmin.opcode, commandArgs2, flowAdmin.leadingFields) ?? commandExec(args);
|
|
@@ -5564,26 +6170,13 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5564
6170
|
"VALUE",
|
|
5565
6171
|
"VALUE_REF",
|
|
5566
6172
|
"DROP_VALUE",
|
|
5567
|
-
"OVERRIDE_VALUE",
|
|
5568
|
-
"ATTRIBUTE_MERGE",
|
|
5569
|
-
"ATTRIBUTE_DELETE"
|
|
5570
|
-
])) ?? commandExec(args);
|
|
5571
|
-
}
|
|
5572
|
-
if (command === "FLOW.SIGNAL") {
|
|
5573
|
-
return
|
|
5574
|
-
"SIGNAL",
|
|
5575
|
-
"PARTITION",
|
|
5576
|
-
"IDEMPOTENCY",
|
|
5577
|
-
"IF_STATE",
|
|
5578
|
-
"TRANSITION_TO",
|
|
5579
|
-
"RUN_AT",
|
|
5580
|
-
"NOW",
|
|
5581
|
-
"PRIORITY",
|
|
5582
|
-
"VALUE",
|
|
5583
|
-
"VALUE_REF",
|
|
5584
|
-
"DROP_VALUE",
|
|
5585
|
-
"OVERRIDE_VALUE"
|
|
5586
|
-
]));
|
|
6173
|
+
"OVERRIDE_VALUE",
|
|
6174
|
+
"ATTRIBUTE_MERGE",
|
|
6175
|
+
"ATTRIBUTE_DELETE"
|
|
6176
|
+
])) ?? commandExec(args);
|
|
6177
|
+
}
|
|
6178
|
+
if (command === "FLOW.SIGNAL") {
|
|
6179
|
+
return flowSignalPayload(commandArgs2) ?? commandExec(args);
|
|
5587
6180
|
}
|
|
5588
6181
|
if (command === "FLOW.CANCEL") {
|
|
5589
6182
|
return flowCommandExecWithRouting(command, commandArgs2, 1, /* @__PURE__ */ new Set([
|
|
@@ -5752,6 +6345,7 @@ var DEFAULT_MAX_PENDING_CONTROL_REQUESTS = 4096;
|
|
|
5752
6345
|
var DEFAULT_MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
|
|
5753
6346
|
var DEFAULT_MAX_QUEUED_REQUESTS = 65536;
|
|
5754
6347
|
var DEFAULT_MAX_QUEUED_WRITE_BYTES = 64 * 1024 * 1024;
|
|
6348
|
+
var UNAUTHENTICATED_MAX_FRAME_BYTES = 64 * 1024;
|
|
5755
6349
|
function assertNativeAdapterOptions(options) {
|
|
5756
6350
|
const supplied = options;
|
|
5757
6351
|
for (const name of ["autoReconnect", "haRouting", "seeds"]) {
|
|
@@ -5771,7 +6365,7 @@ var import_node_net2 = require("net");
|
|
|
5771
6365
|
var import_node_tls2 = require("tls");
|
|
5772
6366
|
|
|
5773
6367
|
// src/client-native-options.ts
|
|
5774
|
-
var
|
|
6368
|
+
var import_node_buffer23 = require("buffer");
|
|
5775
6369
|
|
|
5776
6370
|
// src/string-array-snapshot.ts
|
|
5777
6371
|
function snapshotOwnStringArray(values, name) {
|
|
@@ -5854,7 +6448,7 @@ function snapshotTlsOptions(options) {
|
|
|
5854
6448
|
return Object.freeze(snapshot);
|
|
5855
6449
|
}
|
|
5856
6450
|
function snapshotTlsValue(value, name) {
|
|
5857
|
-
if (
|
|
6451
|
+
if (import_node_buffer23.Buffer.isBuffer(value)) return import_node_buffer23.Buffer.from(value);
|
|
5858
6452
|
if (value instanceof Uint8Array) return value.slice();
|
|
5859
6453
|
if (Array.isArray(value)) {
|
|
5860
6454
|
const snapshot = new Array(value.length);
|
|
@@ -6324,6 +6918,9 @@ var NativeChunkAssembler = class {
|
|
|
6324
6918
|
framesByKey = /* @__PURE__ */ new Map();
|
|
6325
6919
|
totalBytes = 0;
|
|
6326
6920
|
totalFrames = 0;
|
|
6921
|
+
updateMaxResponseBytes(limit) {
|
|
6922
|
+
this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
|
|
6923
|
+
}
|
|
6327
6924
|
assemble(frame) {
|
|
6328
6925
|
const key = `${frame.requestId}:${frame.opcode}:${frame.laneId}`;
|
|
6329
6926
|
const previous = this.chunks.get(key);
|
|
@@ -6406,7 +7003,7 @@ var NativeChunkAssembler = class {
|
|
|
6406
7003
|
};
|
|
6407
7004
|
|
|
6408
7005
|
// src/native-response-handler.ts
|
|
6409
|
-
var
|
|
7006
|
+
var import_node_buffer24 = require("buffer");
|
|
6410
7007
|
|
|
6411
7008
|
// src/native-receive-buffer.ts
|
|
6412
7009
|
var FRAME_ASSEMBLY_PAGE_BYTES = 64 * 1024;
|
|
@@ -6568,12 +7165,18 @@ var NativeReceiveBuffer = class {
|
|
|
6568
7165
|
var NativeResponseHandler = class {
|
|
6569
7166
|
constructor(options) {
|
|
6570
7167
|
this.options = options;
|
|
7168
|
+
this.maxResponseBytes = options.maxResponseBytes;
|
|
6571
7169
|
}
|
|
6572
7170
|
options;
|
|
6573
7171
|
receiveBuffer = new NativeReceiveBuffer();
|
|
6574
7172
|
drainScheduled = false;
|
|
6575
7173
|
paused = false;
|
|
6576
7174
|
stopped = false;
|
|
7175
|
+
maxResponseBytes;
|
|
7176
|
+
updateMaxResponseBytes(limit) {
|
|
7177
|
+
this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
|
|
7178
|
+
this.options.chunkAssembler.updateMaxResponseBytes(this.maxResponseBytes);
|
|
7179
|
+
}
|
|
6577
7180
|
onData(chunk) {
|
|
6578
7181
|
if (this.stopped) return;
|
|
6579
7182
|
try {
|
|
@@ -6655,15 +7258,18 @@ var NativeResponseHandler = class {
|
|
|
6655
7258
|
}
|
|
6656
7259
|
const completeFrame = this.options.chunkAssembler.assemble(frame);
|
|
6657
7260
|
if (completeFrame == null) return;
|
|
6658
|
-
if (completeFrame.body.byteLength > this.
|
|
7261
|
+
if (completeFrame.body.byteLength > this.maxResponseBytes) {
|
|
6659
7262
|
throw new FerricStoreError(
|
|
6660
|
-
`native protocol response exceeded ${this.
|
|
7263
|
+
`native protocol response exceeded ${this.maxResponseBytes} bytes`
|
|
6661
7264
|
);
|
|
6662
7265
|
}
|
|
6663
7266
|
let value;
|
|
6664
7267
|
let responseError;
|
|
6665
7268
|
try {
|
|
6666
|
-
value = decodeResponse(completeFrame, pending.opcode,
|
|
7269
|
+
value = decodeResponse(completeFrame, pending.opcode, {
|
|
7270
|
+
...pending,
|
|
7271
|
+
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7272
|
+
});
|
|
6667
7273
|
if (pending.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
6668
7274
|
} catch (error) {
|
|
6669
7275
|
responseError = error;
|
|
@@ -6679,7 +7285,7 @@ var NativeResponseHandler = class {
|
|
|
6679
7285
|
pending.discardedResponseBytes = discardedResponseBytes;
|
|
6680
7286
|
pending.discardedResponseFrames = discardedResponseFrames;
|
|
6681
7287
|
const chunked = discardedResponseFrames > 1 || (frame.flags & FLAG_MORE_CHUNKS) !== 0;
|
|
6682
|
-
if (discardedResponseBytes > this.
|
|
7288
|
+
if (discardedResponseBytes > this.maxResponseBytes || chunked && discardedResponseBytes > this.options.maxChunkBytes) {
|
|
6683
7289
|
throw new FerricStoreError("native protocol discarded response exceeded configured byte limits");
|
|
6684
7290
|
}
|
|
6685
7291
|
if (discardedResponseFrames > this.options.maxChunkFrames) {
|
|
@@ -6688,12 +7294,14 @@ var NativeResponseHandler = class {
|
|
|
6688
7294
|
if ((frame.flags & FLAG_MORE_CHUNKS) === 0) this.options.takePending(frame.requestId);
|
|
6689
7295
|
}
|
|
6690
7296
|
handleManagementFrame(frame) {
|
|
6691
|
-
if (frame.body.byteLength > this.
|
|
7297
|
+
if (frame.body.byteLength > this.maxResponseBytes) {
|
|
6692
7298
|
throw new FerricStoreError(
|
|
6693
|
-
`native protocol response exceeded ${this.
|
|
7299
|
+
`native protocol response exceeded ${this.maxResponseBytes} bytes`
|
|
6694
7300
|
);
|
|
6695
7301
|
}
|
|
6696
|
-
const value = decodeResponse(frame, frame.opcode
|
|
7302
|
+
const value = decodeResponse(frame, frame.opcode, {
|
|
7303
|
+
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7304
|
+
});
|
|
6697
7305
|
if (frame.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
6698
7306
|
const event = {
|
|
6699
7307
|
flags: frame.flags,
|
|
@@ -6730,7 +7338,7 @@ var NativeRequestScheduler = class {
|
|
|
6730
7338
|
};
|
|
6731
7339
|
|
|
6732
7340
|
// src/native-write-queue.ts
|
|
6733
|
-
var
|
|
7341
|
+
var import_node_buffer25 = require("buffer");
|
|
6734
7342
|
var NativeWriteQueue = class {
|
|
6735
7343
|
constructor(socket, maxQueuedWriteBytes, isClosed, hasPending, rejectPending) {
|
|
6736
7344
|
this.socket = socket;
|
|
@@ -6858,6 +7466,40 @@ var NativeWriteQueue = class {
|
|
|
6858
7466
|
}
|
|
6859
7467
|
};
|
|
6860
7468
|
|
|
7469
|
+
// src/native-connection-capabilities.ts
|
|
7470
|
+
var NativeConnectionCapabilities = class {
|
|
7471
|
+
constructor(configuredRequestFrameBytes) {
|
|
7472
|
+
this.configuredRequestFrameBytes = configuredRequestFrameBytes;
|
|
7473
|
+
this.negotiatedRequestFrameBytes = configuredRequestFrameBytes;
|
|
7474
|
+
this.requestFrameBytes = Math.min(configuredRequestFrameBytes, UNAUTHENTICATED_MAX_FRAME_BYTES);
|
|
7475
|
+
}
|
|
7476
|
+
configuredRequestFrameBytes;
|
|
7477
|
+
compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
7478
|
+
requestFrameBytes;
|
|
7479
|
+
negotiatedRequestFrameBytes;
|
|
7480
|
+
apply(value) {
|
|
7481
|
+
const limits = startupLimits(value);
|
|
7482
|
+
const negotiation = nativeNegotiation(value);
|
|
7483
|
+
this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
|
|
7484
|
+
if (limits.frameBytes != null) {
|
|
7485
|
+
this.negotiatedRequestFrameBytes = Math.min(
|
|
7486
|
+
this.configuredRequestFrameBytes,
|
|
7487
|
+
limits.frameBytes
|
|
7488
|
+
);
|
|
7489
|
+
this.requestFrameBytes = Math.min(this.requestFrameBytes, this.negotiatedRequestFrameBytes);
|
|
7490
|
+
}
|
|
7491
|
+
return {
|
|
7492
|
+
...limits.laneQueue == null ? {} : { laneQueue: limits.laneQueue },
|
|
7493
|
+
...limits.lanes == null ? {} : { lanes: limits.lanes },
|
|
7494
|
+
...negotiation.maxResponseBytes == null ? {} : { maxResponseBytes: negotiation.maxResponseBytes },
|
|
7495
|
+
...limits.pipelineCommands == null ? {} : { pipelineCommands: limits.pipelineCommands }
|
|
7496
|
+
};
|
|
7497
|
+
}
|
|
7498
|
+
activateAuthenticated() {
|
|
7499
|
+
this.requestFrameBytes = this.negotiatedRequestFrameBytes;
|
|
7500
|
+
}
|
|
7501
|
+
};
|
|
7502
|
+
|
|
6861
7503
|
// src/native-adapter.ts
|
|
6862
7504
|
var NativeAdapter = class _NativeAdapter {
|
|
6863
7505
|
socket;
|
|
@@ -6866,9 +7508,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6866
7508
|
closedWaiters = /* @__PURE__ */ new Set();
|
|
6867
7509
|
chunkAssembler;
|
|
6868
7510
|
closed = false;
|
|
7511
|
+
capabilities;
|
|
6869
7512
|
protocolLanes;
|
|
6870
7513
|
maxPipelineCommands = Number.MAX_SAFE_INTEGER;
|
|
6871
|
-
maxRequestFrameBytes;
|
|
6872
7514
|
pendingControlRequests = 0;
|
|
6873
7515
|
maxPendingControlRequests;
|
|
6874
7516
|
heartbeat;
|
|
@@ -6883,7 +7525,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6883
7525
|
const normalizedMaxChunkBytes = normalizePositiveLimit(maxChunkBytes, DEFAULT_MAX_CHUNK_BYTES);
|
|
6884
7526
|
const normalizedMaxChunkFrames = normalizePositiveLimit(maxChunkFrames, DEFAULT_MAX_CHUNK_FRAMES);
|
|
6885
7527
|
const normalizedMaxFrameBytes = normalizePositiveLimit(maxFrameBytes, DEFAULT_MAX_FRAME_BYTES);
|
|
6886
|
-
this.
|
|
7528
|
+
this.capabilities = new NativeConnectionCapabilities(normalizedMaxFrameBytes);
|
|
6887
7529
|
const normalizedMaxResponseBytes = normalizePositiveLimit(maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES);
|
|
6888
7530
|
this.chunkAssembler = new NativeChunkAssembler(
|
|
6889
7531
|
normalizedMaxChunkBytes,
|
|
@@ -6910,7 +7552,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6910
7552
|
this.heartbeat = new NativeHeartbeat(
|
|
6911
7553
|
this.heartbeatIntervalMs,
|
|
6912
7554
|
async () => {
|
|
6913
|
-
await this.request(buildProtocolCommand(["PING"], this.
|
|
7555
|
+
await this.request(buildProtocolCommand(["PING"], this.capabilities.requestFrameBytes), true);
|
|
6914
7556
|
},
|
|
6915
7557
|
(error) => {
|
|
6916
7558
|
this.failAll(new FerricStoreError("FerricStore protocol heartbeat failed", { cause: error }), true);
|
|
@@ -6921,6 +7563,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6921
7563
|
applyFlowControlLimits: (value) => this.applyFlowControlLimits(value),
|
|
6922
7564
|
beginDraining: () => this.beginDraining(),
|
|
6923
7565
|
chunkAssembler: this.chunkAssembler,
|
|
7566
|
+
compactResponseOpcodes: () => this.capabilities.compactResponseOpcodes,
|
|
6924
7567
|
destroy: (error) => this.socket.destroy(error),
|
|
6925
7568
|
failAll: (reason, connectionClosed, message) => this.failAll(reason, connectionClosed, message),
|
|
6926
7569
|
heartbeat: this.heartbeat,
|
|
@@ -6946,6 +7589,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6946
7589
|
adapter,
|
|
6947
7590
|
auth: async (username, password) => {
|
|
6948
7591
|
await adapter.request({ laneId: 0, opcode: OPCODES.auth, payload: { password, username } });
|
|
7592
|
+
adapter.capabilities.activateAuthenticated();
|
|
6949
7593
|
},
|
|
6950
7594
|
close: async () => {
|
|
6951
7595
|
await adapter.close();
|
|
@@ -6963,13 +7607,13 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6963
7607
|
return await this.executeCommandArgs(args);
|
|
6964
7608
|
}
|
|
6965
7609
|
async executeCommandArgs(args) {
|
|
6966
|
-
const command = buildProtocolCommand(args, this.
|
|
7610
|
+
const command = buildProtocolCommand(args, this.capabilities.requestFrameBytes);
|
|
6967
7611
|
return await this.request(command);
|
|
6968
7612
|
}
|
|
6969
7613
|
/** @internal Execute raw command arguments on a topology-selected lane. */
|
|
6970
7614
|
async executeCommandOnLane(args, laneId) {
|
|
6971
7615
|
return await this.executeProtocolCommand(
|
|
6972
|
-
buildProtocolCommand(args, this.
|
|
7616
|
+
buildProtocolCommand(args, this.capabilities.requestFrameBytes),
|
|
6973
7617
|
laneId
|
|
6974
7618
|
);
|
|
6975
7619
|
}
|
|
@@ -6991,7 +7635,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6991
7635
|
laneId,
|
|
6992
7636
|
options,
|
|
6993
7637
|
this.maxPipelineCommands,
|
|
6994
|
-
this.
|
|
7638
|
+
this.capabilities.requestFrameBytes
|
|
6995
7639
|
);
|
|
6996
7640
|
}
|
|
6997
7641
|
/** @internal Execute an ordered pipeline on a topology-selected lane. */
|
|
@@ -7002,13 +7646,11 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7002
7646
|
laneId,
|
|
7003
7647
|
options,
|
|
7004
7648
|
this.maxPipelineCommands,
|
|
7005
|
-
this.
|
|
7649
|
+
this.capabilities.requestFrameBytes
|
|
7006
7650
|
);
|
|
7007
7651
|
}
|
|
7008
7652
|
async close() {
|
|
7009
|
-
if (this.closed)
|
|
7010
|
-
return;
|
|
7011
|
-
}
|
|
7653
|
+
if (this.closed) return;
|
|
7012
7654
|
this.failAll(new FerricStoreError("FerricStore connection closed"), true);
|
|
7013
7655
|
this.socket.destroy();
|
|
7014
7656
|
}
|
|
@@ -7026,7 +7668,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7026
7668
|
});
|
|
7027
7669
|
this.applyStartupLimits(response);
|
|
7028
7670
|
const authRequired = field(response, "auth_required");
|
|
7029
|
-
|
|
7671
|
+
const required = authRequired == null ? false : booleanResponse(authRequired);
|
|
7672
|
+
if (authRequired != null && !required) this.capabilities.activateAuthenticated();
|
|
7673
|
+
return required;
|
|
7030
7674
|
}
|
|
7031
7675
|
request(command, allowWhileDraining = false) {
|
|
7032
7676
|
if (this.closed || this.draining && !allowWhileDraining) {
|
|
@@ -7067,7 +7711,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7067
7711
|
let frame;
|
|
7068
7712
|
try {
|
|
7069
7713
|
requestId = this.requestScheduler.nextRequestId();
|
|
7070
|
-
frame = encodeRequest(command, requestId, this.
|
|
7714
|
+
frame = encodeRequest(command, requestId, this.capabilities.requestFrameBytes);
|
|
7071
7715
|
} catch (error) {
|
|
7072
7716
|
if (hasFlowControlCredit) this.flowControl.release(laneId);
|
|
7073
7717
|
return Promise.reject(error instanceof Error ? error : new FerricStoreError(String(error), { raw: error }));
|
|
@@ -7121,9 +7765,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7121
7765
|
this.resolveClosedWaiters();
|
|
7122
7766
|
}
|
|
7123
7767
|
failAll(reason, connectionClosed = false, dispatchedMessage) {
|
|
7124
|
-
if (this.closed)
|
|
7125
|
-
return;
|
|
7126
|
-
}
|
|
7768
|
+
if (this.closed) return;
|
|
7127
7769
|
this.closed = true;
|
|
7128
7770
|
this.responseHandler.stop();
|
|
7129
7771
|
this.resolveClosedWaiters();
|
|
@@ -7189,18 +7831,18 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7189
7831
|
}
|
|
7190
7832
|
applyStartupLimits(value) {
|
|
7191
7833
|
this.applyFlowControlLimits(value);
|
|
7192
|
-
const
|
|
7193
|
-
if (
|
|
7194
|
-
this.
|
|
7834
|
+
const capabilities = this.capabilities.apply(value);
|
|
7835
|
+
if (capabilities.maxResponseBytes != null) {
|
|
7836
|
+
this.responseHandler.updateMaxResponseBytes(capabilities.maxResponseBytes);
|
|
7195
7837
|
}
|
|
7196
|
-
if (
|
|
7197
|
-
this.
|
|
7838
|
+
if (capabilities.laneQueue != null) {
|
|
7839
|
+
this.flowControl.updateLaneQueueLimit(capabilities.laneQueue);
|
|
7198
7840
|
}
|
|
7199
|
-
if (
|
|
7200
|
-
this.
|
|
7841
|
+
if (capabilities.lanes != null) {
|
|
7842
|
+
this.protocolLanes = Math.min(this.protocolLanes, capabilities.lanes);
|
|
7201
7843
|
}
|
|
7202
|
-
if (
|
|
7203
|
-
this.
|
|
7844
|
+
if (capabilities.pipelineCommands != null) {
|
|
7845
|
+
this.maxPipelineCommands = capabilities.pipelineCommands;
|
|
7204
7846
|
}
|
|
7205
7847
|
}
|
|
7206
7848
|
};
|
|
@@ -7213,7 +7855,30 @@ function executeCommandArgs(executor, args) {
|
|
|
7213
7855
|
}
|
|
7214
7856
|
|
|
7215
7857
|
// src/reconnecting-executor.ts
|
|
7216
|
-
var
|
|
7858
|
+
var import_node_buffer28 = require("buffer");
|
|
7859
|
+
|
|
7860
|
+
// src/command-retry-policy.ts
|
|
7861
|
+
var import_node_buffer27 = require("buffer");
|
|
7862
|
+
function isCasMutation(args) {
|
|
7863
|
+
const offset = commandName2(args[0]) === "COMMAND_EXEC" ? 1 : 0;
|
|
7864
|
+
const name = commandName2(args[offset]);
|
|
7865
|
+
if (name === "CAS") return true;
|
|
7866
|
+
if (name !== "FLOW.POLICY.SET") return false;
|
|
7867
|
+
for (let index = offset + 2; index < args.length; index += 2) {
|
|
7868
|
+
if (!Object.hasOwn(args, index)) return false;
|
|
7869
|
+
if (commandName2(args[index]) === "EXPECTED_GENERATION") return true;
|
|
7870
|
+
}
|
|
7871
|
+
return false;
|
|
7872
|
+
}
|
|
7873
|
+
function commandName2(value) {
|
|
7874
|
+
if (typeof value === "string") return value.toUpperCase();
|
|
7875
|
+
if (import_node_buffer27.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
7876
|
+
return import_node_buffer27.Buffer.from(value).toString("utf8").toUpperCase();
|
|
7877
|
+
}
|
|
7878
|
+
return void 0;
|
|
7879
|
+
}
|
|
7880
|
+
|
|
7881
|
+
// src/reconnecting-executor.ts
|
|
7217
7882
|
var ReconnectingExecutor = class {
|
|
7218
7883
|
constructor(createExecutor, options = {}) {
|
|
7219
7884
|
this.createExecutor = createExecutor;
|
|
@@ -7244,7 +7909,12 @@ var ReconnectingExecutor = class {
|
|
|
7244
7909
|
async executeCommandArgs(args) {
|
|
7245
7910
|
const snapshot = snapshotCommandArguments(args);
|
|
7246
7911
|
assertCommandHasStableConnectionState(snapshot);
|
|
7247
|
-
|
|
7912
|
+
const casMutation = isCasMutation(snapshot);
|
|
7913
|
+
return await this.withReconnect(
|
|
7914
|
+
(executor) => executeCommandArgs(executor, snapshot),
|
|
7915
|
+
casMutation ? isClosedConnectionError : isReconnectableClosedConnectionError,
|
|
7916
|
+
!casMutation
|
|
7917
|
+
);
|
|
7248
7918
|
}
|
|
7249
7919
|
async ready() {
|
|
7250
7920
|
await this.executorPromise;
|
|
@@ -7314,311 +7984,112 @@ var ReconnectingExecutor = class {
|
|
|
7314
7984
|
this.retryAbortController.abort(new FerricStoreError("FerricStore client is closed"));
|
|
7315
7985
|
const executorPromise = this.executorPromise;
|
|
7316
7986
|
const reconnectPromise = this.reconnectPromise;
|
|
7317
|
-
this.closePromise = (async () => {
|
|
7318
|
-
let closeError;
|
|
7319
|
-
let closeFailed = false;
|
|
7320
|
-
const executor = await executorPromise.catch(() => void 0);
|
|
7321
|
-
try {
|
|
7322
|
-
await Promise.resolve(executor?.close?.());
|
|
7323
|
-
} catch (error) {
|
|
7324
|
-
closeFailed = true;
|
|
7325
|
-
closeError = error;
|
|
7326
|
-
}
|
|
7327
|
-
await reconnectPromise?.catch(() => void 0);
|
|
7328
|
-
if (closeFailed) throw closeError;
|
|
7329
|
-
})();
|
|
7330
|
-
await this.closePromise;
|
|
7331
|
-
}
|
|
7332
|
-
async withReconnect(operation, reconnectable = isReconnectableClosedConnectionError) {
|
|
7333
|
-
let executor = await this.executorPromise;
|
|
7334
|
-
let retries = 0;
|
|
7335
|
-
for (; ; ) {
|
|
7336
|
-
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
7337
|
-
try {
|
|
7338
|
-
return await operation(executor);
|
|
7339
|
-
} catch (error) {
|
|
7340
|
-
if (this.closed || retries >= this.maxRetries || !reconnectable(error)) throw error;
|
|
7341
|
-
for (; ; ) {
|
|
7342
|
-
retries += 1;
|
|
7343
|
-
try {
|
|
7344
|
-
executor = await this.reconnect(executor);
|
|
7345
|
-
break;
|
|
7346
|
-
} catch (reconnectError) {
|
|
7347
|
-
if (this.closed || retries >= this.maxRetries) throw reconnectError;
|
|
7348
|
-
await this.waitBeforeReconnect(retries);
|
|
7349
|
-
}
|
|
7350
|
-
}
|
|
7351
|
-
}
|
|
7352
|
-
}
|
|
7353
|
-
}
|
|
7354
|
-
async waitBeforeReconnect(failedAttempts) {
|
|
7355
|
-
const exponent = Math.min(30, Math.max(0, failedAttempts - 1));
|
|
7356
|
-
const base = Math.min(this.maxDelayMs, this.baseDelayMs * 2 ** exponent);
|
|
7357
|
-
const jitter = base * (this.jitterPct / 100) * Math.random();
|
|
7358
|
-
try {
|
|
7359
|
-
await sleep(Math.min(this.maxDelayMs, base + jitter), this.retryAbortController.signal);
|
|
7360
|
-
} catch (error) {
|
|
7361
|
-
if (this.closed) throw new FerricStoreError("FerricStore client is closed", { cause: error });
|
|
7362
|
-
throw error;
|
|
7363
|
-
}
|
|
7364
|
-
}
|
|
7365
|
-
async reconnect(staleExecutor) {
|
|
7366
|
-
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
7367
|
-
const competingReconnect = this.reconnectPromise;
|
|
7368
|
-
if (competingReconnect != null) return await competingReconnect;
|
|
7369
|
-
const observedExecutorPromise = this.executorPromise;
|
|
7370
|
-
const currentExecutor = await observedExecutorPromise.catch(() => void 0);
|
|
7371
|
-
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
7372
|
-
if (this.reconnectPromise != null) return await this.reconnectPromise;
|
|
7373
|
-
if (this.executorPromise !== observedExecutorPromise) return await this.executorPromise;
|
|
7374
|
-
if (currentExecutor != null && currentExecutor !== staleExecutor) return currentExecutor;
|
|
7375
|
-
this.reconnectPromise = (async () => {
|
|
7376
|
-
await Promise.resolve(staleExecutor.close?.()).catch(() => void 0);
|
|
7377
|
-
const nextExecutor = await this.createExecutor(this.retryAbortController.signal);
|
|
7378
|
-
if (this.closed) {
|
|
7379
|
-
await Promise.resolve(nextExecutor.close?.()).catch(() => void 0);
|
|
7380
|
-
throw new FerricStoreError("FerricStore client is closed");
|
|
7381
|
-
}
|
|
7382
|
-
this.executorPromise = Promise.resolve(nextExecutor);
|
|
7383
|
-
return nextExecutor;
|
|
7384
|
-
})().finally(() => {
|
|
7385
|
-
this.reconnectPromise = void 0;
|
|
7386
|
-
});
|
|
7387
|
-
return await this.reconnectPromise;
|
|
7388
|
-
}
|
|
7389
|
-
};
|
|
7390
|
-
function isReconnectableClosedConnectionError(error) {
|
|
7391
|
-
return error instanceof ConnectionClosedError && error.requestDisposition === "unsent";
|
|
7392
|
-
}
|
|
7393
|
-
function isReadOnlyReconnectableClosedConnectionError(error) {
|
|
7394
|
-
const pending = [error];
|
|
7395
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7396
|
-
for (let visited = 0; visited < 16 && pending.length > 0; visited += 1) {
|
|
7397
|
-
const current = pending.pop();
|
|
7398
|
-
if (isReconnectableClosedConnectionError(current)) return true;
|
|
7399
|
-
if (current == null || typeof current !== "object" && typeof current !== "function" || seen.has(current)) continue;
|
|
7400
|
-
seen.add(current);
|
|
7401
|
-
if (current instanceof Error && current.cause != null) pending.push(current.cause);
|
|
7402
|
-
if (current instanceof FerricStoreError && current.raw != null) pending.push(current.raw);
|
|
7403
|
-
}
|
|
7404
|
-
return false;
|
|
7405
|
-
}
|
|
7406
|
-
function normalizeNonNegativeInteger2(value, fallback) {
|
|
7407
|
-
return Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : fallback;
|
|
7408
|
-
}
|
|
7409
|
-
|
|
7410
|
-
// src/topology.ts
|
|
7411
|
-
var import_node_buffer26 = require("buffer");
|
|
7412
|
-
|
|
7413
|
-
// src/topology-routing.ts
|
|
7414
|
-
var import_node_buffer25 = require("buffer");
|
|
7415
|
-
var import_node_crypto = require("crypto");
|
|
7416
|
-
|
|
7417
|
-
// src/topology-utilities.ts
|
|
7418
|
-
var import_node_buffer24 = require("buffer");
|
|
7419
|
-
function isPlainObject3(value) {
|
|
7420
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer24.Buffer.isBuffer(value);
|
|
7421
|
-
}
|
|
7422
|
-
function getField(source, ...keys) {
|
|
7423
|
-
if (source instanceof Map) {
|
|
7424
|
-
for (const key of keys) {
|
|
7425
|
-
if (source.has(key)) return source.get(key);
|
|
7426
|
-
const bufferKey = import_node_buffer24.Buffer.from(key);
|
|
7427
|
-
for (const [itemKey, value] of source.entries()) {
|
|
7428
|
-
if (import_node_buffer24.Buffer.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
7429
|
-
}
|
|
7430
|
-
}
|
|
7431
|
-
return void 0;
|
|
7432
|
-
}
|
|
7433
|
-
if (isPlainObject3(source)) {
|
|
7434
|
-
for (const key of keys) {
|
|
7435
|
-
if (Object.hasOwn(source, key)) return source[key];
|
|
7436
|
-
}
|
|
7437
|
-
}
|
|
7438
|
-
return void 0;
|
|
7439
|
-
}
|
|
7440
|
-
function textOrUndefined(value) {
|
|
7441
|
-
if (typeof value === "string") return value;
|
|
7442
|
-
if (import_node_buffer24.Buffer.isBuffer(value)) return value.toString("utf8");
|
|
7443
|
-
return void 0;
|
|
7444
|
-
}
|
|
7445
|
-
function numberOrUndefined(value) {
|
|
7446
|
-
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
7447
|
-
}
|
|
7448
|
-
function nativeEventName(event) {
|
|
7449
|
-
return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
|
|
7450
|
-
}
|
|
7451
|
-
function endpointFromRange(item) {
|
|
7452
|
-
const endpointValue = getField(item, "endpoint");
|
|
7453
|
-
if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
|
|
7454
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7455
|
-
}
|
|
7456
|
-
const raw = endpointValue ?? item;
|
|
7457
|
-
const host = textOrUndefined(getField(raw, "host", "native_host"));
|
|
7458
|
-
const nativePort = numberOrUndefined(getField(raw, "native_port"));
|
|
7459
|
-
if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
|
|
7460
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7461
|
-
}
|
|
7462
|
-
const nativeTlsPortValue = getField(raw, "native_tls_port");
|
|
7463
|
-
const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
|
|
7464
|
-
if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
|
|
7465
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7466
|
-
}
|
|
7467
|
-
return {
|
|
7468
|
-
host,
|
|
7469
|
-
nativePort,
|
|
7470
|
-
node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
|
|
7471
|
-
...nativeTlsPort == null ? {} : { nativeTlsPort }
|
|
7472
|
-
};
|
|
7473
|
-
}
|
|
7474
|
-
function validEndpointHost(host) {
|
|
7475
|
-
if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
|
|
7476
|
-
const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
7477
|
-
try {
|
|
7478
|
-
const url = new URL(`ferric://${authorityHost}:6388`);
|
|
7479
|
-
return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
|
|
7480
|
-
} catch {
|
|
7481
|
-
return false;
|
|
7482
|
-
}
|
|
7483
|
-
}
|
|
7484
|
-
function sameEndpoint(left, right) {
|
|
7485
|
-
return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
|
|
7486
|
-
}
|
|
7487
|
-
function parseFerricUrl2(value) {
|
|
7488
|
-
const url = new URL(value);
|
|
7489
|
-
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
7490
|
-
throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
|
|
7491
|
-
}
|
|
7492
|
-
return {
|
|
7493
|
-
host: normalizeFerricUrlHost(url.hostname),
|
|
7494
|
-
...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
|
|
7495
|
-
port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
|
|
7496
|
-
tls: url.protocol === "ferrics:",
|
|
7497
|
-
...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
|
|
7498
|
-
};
|
|
7499
|
-
}
|
|
7500
|
-
function endpointKeyFor(endpoint) {
|
|
7501
|
-
return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
|
|
7502
|
-
}
|
|
7503
|
-
function connectionKeyForEndpoint(endpoint, useTls) {
|
|
7504
|
-
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
7505
|
-
return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
|
|
7506
|
-
}
|
|
7507
|
-
function connectionKeyFromUrl(url) {
|
|
7508
|
-
const parsed = parseFerricUrl2(url);
|
|
7509
|
-
return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
|
|
7510
|
-
}
|
|
7511
|
-
function normalizedEndpointHost(host) {
|
|
7512
|
-
const lower = host.toLowerCase();
|
|
7513
|
-
return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
|
|
7514
|
-
}
|
|
7515
|
-
function urlFromEndpoint(endpoint, useTls) {
|
|
7516
|
-
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
7517
|
-
const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
|
|
7518
|
-
return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
|
|
7519
|
-
}
|
|
7520
|
-
async function mapSettledWithConcurrency(items, concurrency, operation) {
|
|
7521
|
-
const results = new Array(items.length);
|
|
7522
|
-
let nextIndex = 0;
|
|
7523
|
-
const worker = async () => {
|
|
7524
|
-
while (nextIndex < items.length) {
|
|
7525
|
-
const index = nextIndex++;
|
|
7526
|
-
const item = items[index];
|
|
7987
|
+
this.closePromise = (async () => {
|
|
7988
|
+
let closeError;
|
|
7989
|
+
let closeFailed = false;
|
|
7990
|
+
const executor = await executorPromise.catch(() => void 0);
|
|
7527
7991
|
try {
|
|
7528
|
-
|
|
7529
|
-
} catch (
|
|
7530
|
-
|
|
7992
|
+
await Promise.resolve(executor?.close?.());
|
|
7993
|
+
} catch (error) {
|
|
7994
|
+
closeFailed = true;
|
|
7995
|
+
closeError = error;
|
|
7531
7996
|
}
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
async () => await worker()
|
|
7537
|
-
));
|
|
7538
|
-
return results;
|
|
7539
|
-
}
|
|
7540
|
-
function throwFirstRejected(results) {
|
|
7541
|
-
for (const result of results) {
|
|
7542
|
-
if (result.status === "rejected") throw result.reason;
|
|
7543
|
-
}
|
|
7544
|
-
}
|
|
7545
|
-
var TaskConcurrencyLimiter = class {
|
|
7546
|
-
constructor(concurrency) {
|
|
7547
|
-
this.concurrency = concurrency;
|
|
7997
|
+
await reconnectPromise?.catch(() => void 0);
|
|
7998
|
+
if (closeFailed) throw closeError;
|
|
7999
|
+
})();
|
|
8000
|
+
await this.closePromise;
|
|
7548
8001
|
}
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
7552
|
-
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
7557
|
-
|
|
7558
|
-
|
|
8002
|
+
async withReconnect(operation, reconnectable = isReconnectableClosedConnectionError, replayAllowed = true) {
|
|
8003
|
+
let executor = await this.executorPromise;
|
|
8004
|
+
let retries = 0;
|
|
8005
|
+
for (; ; ) {
|
|
8006
|
+
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
8007
|
+
try {
|
|
8008
|
+
return await operation(executor);
|
|
8009
|
+
} catch (error) {
|
|
8010
|
+
if (this.closed || retries >= this.maxRetries || !reconnectable(error)) throw error;
|
|
8011
|
+
if (!replayAllowed) {
|
|
8012
|
+
await this.reconnect(executor).catch(() => void 0);
|
|
8013
|
+
throw error;
|
|
8014
|
+
}
|
|
8015
|
+
for (; ; ) {
|
|
8016
|
+
retries += 1;
|
|
8017
|
+
try {
|
|
8018
|
+
executor = await this.reconnect(executor);
|
|
8019
|
+
break;
|
|
8020
|
+
} catch (reconnectError) {
|
|
8021
|
+
if (this.closed || retries >= this.maxRetries) throw reconnectError;
|
|
8022
|
+
await this.waitBeforeReconnect(retries);
|
|
8023
|
+
}
|
|
8024
|
+
}
|
|
8025
|
+
}
|
|
7559
8026
|
}
|
|
7560
8027
|
}
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
8028
|
+
async waitBeforeReconnect(failedAttempts) {
|
|
8029
|
+
const exponent = Math.min(30, Math.max(0, failedAttempts - 1));
|
|
8030
|
+
const base = Math.min(this.maxDelayMs, this.baseDelayMs * 2 ** exponent);
|
|
8031
|
+
const jitter = base * (this.jitterPct / 100) * Math.random();
|
|
8032
|
+
try {
|
|
8033
|
+
await sleep(Math.min(this.maxDelayMs, base + jitter), this.retryAbortController.signal);
|
|
8034
|
+
} catch (error) {
|
|
8035
|
+
if (this.closed) throw new FerricStoreError("FerricStore client is closed", { cause: error });
|
|
8036
|
+
throw error;
|
|
7565
8037
|
}
|
|
7566
|
-
return new Promise((resolve) => this.pending.push(resolve));
|
|
7567
8038
|
}
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
this.
|
|
7575
|
-
|
|
7576
|
-
if (this.
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
this.
|
|
7581
|
-
this.
|
|
7582
|
-
|
|
8039
|
+
async reconnect(staleExecutor) {
|
|
8040
|
+
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
8041
|
+
const competingReconnect = this.reconnectPromise;
|
|
8042
|
+
if (competingReconnect != null) return await competingReconnect;
|
|
8043
|
+
const observedExecutorPromise = this.executorPromise;
|
|
8044
|
+
const currentExecutor = await observedExecutorPromise.catch(() => void 0);
|
|
8045
|
+
if (this.closed) throw new FerricStoreError("FerricStore client is closed");
|
|
8046
|
+
if (this.reconnectPromise != null) return await this.reconnectPromise;
|
|
8047
|
+
if (this.executorPromise !== observedExecutorPromise) return await this.executorPromise;
|
|
8048
|
+
if (currentExecutor != null && currentExecutor !== staleExecutor) return currentExecutor;
|
|
8049
|
+
this.reconnectPromise = (async () => {
|
|
8050
|
+
await Promise.resolve(staleExecutor.close?.()).catch(() => void 0);
|
|
8051
|
+
const nextExecutor = await this.createExecutor(this.retryAbortController.signal);
|
|
8052
|
+
if (this.closed) {
|
|
8053
|
+
await Promise.resolve(nextExecutor.close?.()).catch(() => void 0);
|
|
8054
|
+
throw new FerricStoreError("FerricStore client is closed");
|
|
8055
|
+
}
|
|
8056
|
+
this.executorPromise = Promise.resolve(nextExecutor);
|
|
8057
|
+
return nextExecutor;
|
|
8058
|
+
})().finally(() => {
|
|
8059
|
+
this.reconnectPromise = void 0;
|
|
8060
|
+
});
|
|
8061
|
+
return await this.reconnectPromise;
|
|
7583
8062
|
}
|
|
7584
8063
|
};
|
|
7585
|
-
function
|
|
7586
|
-
return
|
|
7587
|
-
hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
|
|
7588
|
-
);
|
|
7589
|
-
}
|
|
7590
|
-
function bufferStartsWith(value, prefix) {
|
|
7591
|
-
return value.byteLength >= prefix.byteLength && value.subarray(0, prefix.byteLength).equals(prefix);
|
|
7592
|
-
}
|
|
7593
|
-
var OPEN_BRACE = "{".charCodeAt(0);
|
|
7594
|
-
var CLOSE_BRACE = "}".charCodeAt(0);
|
|
7595
|
-
function hashTagOrKey(key) {
|
|
7596
|
-
const start = key.indexOf(OPEN_BRACE);
|
|
7597
|
-
if (start < 0) return key;
|
|
7598
|
-
const end = key.indexOf(CLOSE_BRACE, start + 1);
|
|
7599
|
-
return end > start + 1 ? key.subarray(start + 1, end) : key;
|
|
8064
|
+
function isReconnectableClosedConnectionError(error) {
|
|
8065
|
+
return error instanceof ConnectionClosedError && error.requestDisposition === "unsent";
|
|
7600
8066
|
}
|
|
7601
|
-
function
|
|
7602
|
-
|
|
7603
|
-
return end > 0 ? rest.subarray(0, end) : hashTagOrKey(fallbackKey);
|
|
8067
|
+
function isClosedConnectionError(error) {
|
|
8068
|
+
return error instanceof ConnectionClosedError;
|
|
7604
8069
|
}
|
|
7605
|
-
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
} else {
|
|
7616
|
-
hashInput = hashTagOrKey(keyBytes);
|
|
8070
|
+
function isReadOnlyReconnectableClosedConnectionError(error) {
|
|
8071
|
+
const pending = [error];
|
|
8072
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8073
|
+
for (let visited = 0; visited < 16 && pending.length > 0; visited += 1) {
|
|
8074
|
+
const current = pending.pop();
|
|
8075
|
+
if (isReconnectableClosedConnectionError(current)) return true;
|
|
8076
|
+
if (current == null || typeof current !== "object" && typeof current !== "function" || seen.has(current)) continue;
|
|
8077
|
+
seen.add(current);
|
|
8078
|
+
if (current instanceof Error && current.cause != null) pending.push(current.cause);
|
|
8079
|
+
if (current instanceof FerricStoreError && current.raw != null) pending.push(current.raw);
|
|
7617
8080
|
}
|
|
7618
|
-
return
|
|
8081
|
+
return false;
|
|
8082
|
+
}
|
|
8083
|
+
function normalizeNonNegativeInteger2(value, fallback) {
|
|
8084
|
+
return Number.isFinite(value) ? Math.max(0, Math.trunc(value)) : fallback;
|
|
7619
8085
|
}
|
|
7620
8086
|
|
|
8087
|
+
// src/topology.ts
|
|
8088
|
+
var import_node_buffer30 = require("buffer");
|
|
8089
|
+
|
|
7621
8090
|
// src/topology-routing.ts
|
|
8091
|
+
var import_node_buffer29 = require("buffer");
|
|
8092
|
+
var import_node_crypto = require("crypto");
|
|
7622
8093
|
var FLOW_PARTITION_ROUTE_CACHE_MAX = 1024;
|
|
7623
8094
|
var flowPartitionRouteCache = /* @__PURE__ */ new Map();
|
|
7624
8095
|
function routingKeyFromProtocolPayload(name, command) {
|
|
@@ -7626,9 +8097,18 @@ function routingKeyFromProtocolPayload(name, command) {
|
|
|
7626
8097
|
return void 0;
|
|
7627
8098
|
}
|
|
7628
8099
|
if (isPlainObject3(command.payload)) {
|
|
7629
|
-
for (const field2 of [
|
|
8100
|
+
for (const field2 of [
|
|
8101
|
+
"key",
|
|
8102
|
+
"partition_key",
|
|
8103
|
+
"id",
|
|
8104
|
+
"owner_flow_id",
|
|
8105
|
+
"parent_flow_id",
|
|
8106
|
+
"root_flow_id",
|
|
8107
|
+
"correlation_id",
|
|
8108
|
+
"scope"
|
|
8109
|
+
]) {
|
|
7630
8110
|
const value = getField(command.payload, field2);
|
|
7631
|
-
if (typeof value === "string" ||
|
|
8111
|
+
if (typeof value === "string" || import_node_buffer29.Buffer.isBuffer(value)) {
|
|
7632
8112
|
return value;
|
|
7633
8113
|
}
|
|
7634
8114
|
}
|
|
@@ -7675,9 +8155,9 @@ function flowRoutingData(name, args) {
|
|
|
7675
8155
|
if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
|
|
7676
8156
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
7677
8157
|
}
|
|
7678
|
-
if (
|
|
7679
|
-
const
|
|
7680
|
-
if (
|
|
8158
|
+
if (import_node_buffer29.Buffer.isBuffer(partition)) {
|
|
8159
|
+
const text3 = partition.toString("utf8").toUpperCase();
|
|
8160
|
+
if (text3 !== "AUTO" && text3 !== "MIXED") {
|
|
7681
8161
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
7682
8162
|
}
|
|
7683
8163
|
}
|
|
@@ -7766,22 +8246,22 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
|
|
|
7766
8246
|
return { handled: false };
|
|
7767
8247
|
}
|
|
7768
8248
|
function isRoutingKey(value) {
|
|
7769
|
-
return typeof value === "string" ||
|
|
8249
|
+
return typeof value === "string" || import_node_buffer29.Buffer.isBuffer(value);
|
|
7770
8250
|
}
|
|
7771
8251
|
function flowLogicalPartitionRoutingKey(value) {
|
|
7772
|
-
if (typeof value !== "string" && !
|
|
8252
|
+
if (typeof value !== "string" && !import_node_buffer29.Buffer.isBuffer(value)) {
|
|
7773
8253
|
return void 0;
|
|
7774
8254
|
}
|
|
7775
|
-
const bytes2 =
|
|
7776
|
-
const
|
|
7777
|
-
const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(
|
|
8255
|
+
const bytes2 = import_node_buffer29.Buffer.isBuffer(value) ? value : import_node_buffer29.Buffer.from(value);
|
|
8256
|
+
const text3 = bytes2.toString("utf8");
|
|
8257
|
+
const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(text3);
|
|
7778
8258
|
if (autoMatch != null) {
|
|
7779
8259
|
const bucket = Number(autoMatch[1]);
|
|
7780
8260
|
if (bucket < 256) {
|
|
7781
|
-
return `
|
|
8261
|
+
return `{fa:${bucket}}`;
|
|
7782
8262
|
}
|
|
7783
8263
|
}
|
|
7784
|
-
const cacheKey = `${
|
|
8264
|
+
const cacheKey = `${import_node_buffer29.Buffer.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
|
|
7785
8265
|
const cached = flowPartitionRouteCache.get(cacheKey);
|
|
7786
8266
|
if (cached != null) {
|
|
7787
8267
|
flowPartitionRouteCache.delete(cacheKey);
|
|
@@ -7789,7 +8269,7 @@ function flowLogicalPartitionRoutingKey(value) {
|
|
|
7789
8269
|
return cached;
|
|
7790
8270
|
}
|
|
7791
8271
|
const digest = (0, import_node_crypto.createHash)("sha256").update(bytes2).digest("base64url");
|
|
7792
|
-
const routeKey = `
|
|
8272
|
+
const routeKey = `{f:${digest}}`;
|
|
7793
8273
|
if (flowPartitionRouteCache.size >= FLOW_PARTITION_ROUTE_CACHE_MAX) {
|
|
7794
8274
|
const oldest = flowPartitionRouteCache.keys().next().value;
|
|
7795
8275
|
if (oldest != null) flowPartitionRouteCache.delete(oldest);
|
|
@@ -7798,18 +8278,17 @@ function flowLogicalPartitionRoutingKey(value) {
|
|
|
7798
8278
|
return routeKey;
|
|
7799
8279
|
}
|
|
7800
8280
|
function flowAutoIdRoutingKey(value) {
|
|
7801
|
-
if (typeof value !== "string" && !
|
|
8281
|
+
if (typeof value !== "string" && !import_node_buffer29.Buffer.isBuffer(value)) {
|
|
7802
8282
|
return void 0;
|
|
7803
8283
|
}
|
|
7804
|
-
const
|
|
7805
|
-
|
|
7806
|
-
return `f:{fa:${bucket}}:route`;
|
|
8284
|
+
const bucket = (import_node_buffer29.Buffer.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
|
|
8285
|
+
return `{fa:${bucket}}`;
|
|
7807
8286
|
}
|
|
7808
8287
|
function flowClaimLogicalPartitionRoutingKey(value) {
|
|
7809
|
-
if (typeof value !== "string" && !
|
|
8288
|
+
if (typeof value !== "string" && !import_node_buffer29.Buffer.isBuffer(value)) return void 0;
|
|
7810
8289
|
const selector = commandPart(value);
|
|
7811
8290
|
if (selector === "AUTO" || selector === "ANY") return void 0;
|
|
7812
|
-
if (selector === "GLOBAL") return "
|
|
8291
|
+
if (selector === "GLOBAL") return "{f}";
|
|
7813
8292
|
return flowLogicalPartitionRoutingKey(value);
|
|
7814
8293
|
}
|
|
7815
8294
|
function singleShardFlowPartitionKey(values) {
|
|
@@ -7821,7 +8300,7 @@ function singleShardFlowClaimPartitionKey(values) {
|
|
|
7821
8300
|
return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
|
|
7822
8301
|
}
|
|
7823
8302
|
function singleShardKey(keys) {
|
|
7824
|
-
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !
|
|
8303
|
+
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !import_node_buffer29.Buffer.isBuffer(key))) {
|
|
7825
8304
|
return void 0;
|
|
7826
8305
|
}
|
|
7827
8306
|
const usable = keys;
|
|
@@ -7832,7 +8311,7 @@ function singleShardKey(keys) {
|
|
|
7832
8311
|
const firstSlot = routingSlotForKey(first);
|
|
7833
8312
|
return usable.every((key) => routingSlotForKey(key) === firstSlot) ? first : void 0;
|
|
7834
8313
|
}
|
|
7835
|
-
function
|
|
8314
|
+
function commandName3(args) {
|
|
7836
8315
|
return commandView(args).name;
|
|
7837
8316
|
}
|
|
7838
8317
|
var commandPart = commandToken;
|
|
@@ -7854,7 +8333,7 @@ function routedKeyGroups(keys, routeKey) {
|
|
|
7854
8333
|
const groups = /* @__PURE__ */ new Map();
|
|
7855
8334
|
for (let index = 0; index < keys.length; index += 1) {
|
|
7856
8335
|
const key = keys[index];
|
|
7857
|
-
if (typeof key !== "string" && !
|
|
8336
|
+
if (typeof key !== "string" && !import_node_buffer29.Buffer.isBuffer(key)) return void 0;
|
|
7858
8337
|
const route = routeKey(key);
|
|
7859
8338
|
const groupKey = `${route.endpointKey}\0${route.laneId}`;
|
|
7860
8339
|
const group = groups.get(groupKey);
|
|
@@ -8095,7 +8574,16 @@ function isExplicitlySafeReroute(error) {
|
|
|
8095
8574
|
if (error instanceof ConnectionClosedError) {
|
|
8096
8575
|
return error.requestDisposition === "unsent";
|
|
8097
8576
|
}
|
|
8098
|
-
return error instanceof RerouteError &&
|
|
8577
|
+
return error instanceof RerouteError && error.retryable === true && error.safeToRetry === true;
|
|
8578
|
+
}
|
|
8579
|
+
function retryAfterMs(error) {
|
|
8580
|
+
return error instanceof FerricStoreError ? error.retryAfterMs ?? 0 : 0;
|
|
8581
|
+
}
|
|
8582
|
+
async function waitForExplicitlySafeReroute(error) {
|
|
8583
|
+
if (!isExplicitlySafeReroute(error)) return false;
|
|
8584
|
+
const delayMs = retryAfterMs(error);
|
|
8585
|
+
if (delayMs > 0) await sleep(delayMs);
|
|
8586
|
+
return true;
|
|
8099
8587
|
}
|
|
8100
8588
|
|
|
8101
8589
|
// src/topology-endpoint-trust.ts
|
|
@@ -8237,7 +8725,7 @@ var TopologyPipelineExecutor = class {
|
|
|
8237
8725
|
commands.forEach((command, index) => {
|
|
8238
8726
|
const routed = this.context.routeData(command);
|
|
8239
8727
|
if (routed == null) {
|
|
8240
|
-
if (decomposableCommandNames.has(
|
|
8728
|
+
if (decomposableCommandNames.has(commandName3(command) ?? "")) standalone.push({ command, index });
|
|
8241
8729
|
else {
|
|
8242
8730
|
controlCommands.push(command);
|
|
8243
8731
|
controlIndices.push(index);
|
|
@@ -8453,7 +8941,7 @@ function topologyRouteIsCurrent(topology, route) {
|
|
|
8453
8941
|
// src/topology-route-planner.ts
|
|
8454
8942
|
function topologyRouteData(args, route) {
|
|
8455
8943
|
if (args.length === 0) return void 0;
|
|
8456
|
-
const name =
|
|
8944
|
+
const name = commandName3(args);
|
|
8457
8945
|
if (name?.startsWith("FLOW.") === true) {
|
|
8458
8946
|
const routed = flowRoutingData(name, args);
|
|
8459
8947
|
return routed == null ? void 0 : {
|
|
@@ -8482,7 +8970,7 @@ var TopologyScatterExecutor = class {
|
|
|
8482
8970
|
}
|
|
8483
8971
|
dependencies;
|
|
8484
8972
|
async execute(args) {
|
|
8485
|
-
const name =
|
|
8973
|
+
const name = commandName3(args);
|
|
8486
8974
|
if (name === "MGET") {
|
|
8487
8975
|
const value = await this.scatterArray(name, args.slice(1));
|
|
8488
8976
|
return value == null ? { handled: false } : { handled: true, value };
|
|
@@ -8564,6 +9052,18 @@ var TopologyScatterExecutor = class {
|
|
|
8564
9052
|
}
|
|
8565
9053
|
};
|
|
8566
9054
|
|
|
9055
|
+
// src/topology-reroute-retry.ts
|
|
9056
|
+
async function canRetrySafeReroute(error, attempt, retryAllowed, refresh, assertOpen) {
|
|
9057
|
+
if (attempt !== 0 || !isRetryableRouteError(error)) return false;
|
|
9058
|
+
const refreshed = await refresh().then(
|
|
9059
|
+
() => true,
|
|
9060
|
+
() => false
|
|
9061
|
+
);
|
|
9062
|
+
if (!refreshed || !retryAllowed || !await waitForExplicitlySafeReroute(error)) return false;
|
|
9063
|
+
assertOpen();
|
|
9064
|
+
return true;
|
|
9065
|
+
}
|
|
9066
|
+
|
|
8567
9067
|
// src/topology.ts
|
|
8568
9068
|
var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
8569
9069
|
adapterOptions;
|
|
@@ -8749,6 +9249,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8749
9249
|
this.assertOpen();
|
|
8750
9250
|
const snapshot = snapshotCommandArguments(args);
|
|
8751
9251
|
assertCommandHasStableConnectionState(snapshot);
|
|
9252
|
+
const casMutation = isCasMutation(snapshot);
|
|
8752
9253
|
let rerouteAttempt = 0;
|
|
8753
9254
|
for (let planningAttempt = 0; planningAttempt < MAX_TOPOLOGY_PLANNING_ATTEMPTS; planningAttempt += 1) {
|
|
8754
9255
|
const routed = this.routeData(snapshot);
|
|
@@ -8764,7 +9265,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8764
9265
|
try {
|
|
8765
9266
|
return routed.command == null ? await adapter.executeCommandOnLane(snapshot, routed.route.laneId) : await adapter.executeProtocolCommand(routed.command, routed.route.laneId);
|
|
8766
9267
|
} catch (error) {
|
|
8767
|
-
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt)) {
|
|
9268
|
+
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt, !casMutation)) {
|
|
8768
9269
|
rerouteAttempt += 1;
|
|
8769
9270
|
continue;
|
|
8770
9271
|
}
|
|
@@ -8806,6 +9307,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8806
9307
|
assertCommandHasStableConnectionState(command);
|
|
8807
9308
|
}
|
|
8808
9309
|
let rerouteAttempt = 0;
|
|
9310
|
+
const containsCasMutation = snapshot.some(isCasMutation);
|
|
8809
9311
|
for (let planningAttempt = 0; planningAttempt < MAX_TOPOLOGY_PLANNING_ATTEMPTS; planningAttempt += 1) {
|
|
8810
9312
|
const route = singleRouteForCommands(snapshot, (command) => this.routeData(command));
|
|
8811
9313
|
if (route == null) return void 0;
|
|
@@ -8814,7 +9316,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8814
9316
|
try {
|
|
8815
9317
|
return await adapter.executeFusedPipelineOnLane(snapshot, route.laneId, snapshotOptions);
|
|
8816
9318
|
} catch (error) {
|
|
8817
|
-
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt)) {
|
|
9319
|
+
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt, !containsCasMutation)) {
|
|
8818
9320
|
rerouteAttempt += 1;
|
|
8819
9321
|
continue;
|
|
8820
9322
|
}
|
|
@@ -8823,13 +9325,14 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8823
9325
|
}
|
|
8824
9326
|
throw new StaleTopologyRouteError();
|
|
8825
9327
|
}
|
|
8826
|
-
async refreshAndCanRetrySafeReroute(error, attempt) {
|
|
8827
|
-
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
9328
|
+
async refreshAndCanRetrySafeReroute(error, attempt, retryAllowed = true) {
|
|
9329
|
+
return await canRetrySafeReroute(
|
|
9330
|
+
error,
|
|
9331
|
+
attempt,
|
|
9332
|
+
retryAllowed,
|
|
9333
|
+
async () => await this.refreshTopology(),
|
|
9334
|
+
() => this.assertOpen()
|
|
8831
9335
|
);
|
|
8832
|
-
return refreshed && isExplicitlySafeReroute(error);
|
|
8833
9336
|
}
|
|
8834
9337
|
async executePipelineOnRoute(commands, route, options) {
|
|
8835
9338
|
const adapter = await this.adapterForCurrentRoute(route);
|
|
@@ -8919,7 +9422,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8919
9422
|
};
|
|
8920
9423
|
|
|
8921
9424
|
// src/response-map-preservation.ts
|
|
8922
|
-
var
|
|
9425
|
+
var import_node_buffer31 = require("buffer");
|
|
8923
9426
|
function toStringKeyMapPreservingValues(value) {
|
|
8924
9427
|
if (value == null) return void 0;
|
|
8925
9428
|
const result = {};
|
|
@@ -8929,7 +9432,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
8929
9432
|
}
|
|
8930
9433
|
return result;
|
|
8931
9434
|
}
|
|
8932
|
-
if (typeof value === "object" && !Array.isArray(value) && !
|
|
9435
|
+
if (typeof value === "object" && !Array.isArray(value) && !import_node_buffer31.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
8933
9436
|
for (const [key, item] of Object.entries(value)) {
|
|
8934
9437
|
setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
|
|
8935
9438
|
}
|
|
@@ -8938,7 +9441,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
8938
9441
|
return void 0;
|
|
8939
9442
|
}
|
|
8940
9443
|
function normalizeMapStructurePreservingBytes(value) {
|
|
8941
|
-
if (
|
|
9444
|
+
if (import_node_buffer31.Buffer.isBuffer(value) || value instanceof Uint8Array) return value;
|
|
8942
9445
|
if (value instanceof Map) {
|
|
8943
9446
|
const result = {};
|
|
8944
9447
|
for (const [key, item] of value.entries()) {
|
|
@@ -8960,7 +9463,7 @@ function normalizeMapStructurePreservingBytes(value) {
|
|
|
8960
9463
|
}
|
|
8961
9464
|
|
|
8962
9465
|
// src/native-kv-responses.ts
|
|
8963
|
-
var
|
|
9466
|
+
var import_node_buffer32 = require("buffer");
|
|
8964
9467
|
function rateLimitResultFromResp(value) {
|
|
8965
9468
|
if (!Array.isArray(value) || value.length !== 4) {
|
|
8966
9469
|
throw new TypeError("RATELIMIT.ADD returned an unexpected response");
|
|
@@ -9003,30 +9506,27 @@ function fetchOrComputeResultFromResp(value, codec) {
|
|
|
9003
9506
|
shouldCompute: false
|
|
9004
9507
|
};
|
|
9005
9508
|
}
|
|
9006
|
-
if (status !== "compute"
|
|
9509
|
+
if (status !== "compute" || value.length !== 3) {
|
|
9510
|
+
throw new TypeError("FETCH_OR_COMPUTE returned an unexpected response");
|
|
9511
|
+
}
|
|
9007
9512
|
return {
|
|
9008
9513
|
status,
|
|
9009
9514
|
computeHint: responseBytes(value[1], "FETCH_OR_COMPUTE"),
|
|
9010
|
-
|
|
9011
|
-
|
|
9012
|
-
computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE")
|
|
9013
|
-
} : {
|
|
9014
|
-
computeMode: "legacy",
|
|
9015
|
-
computeToken: null
|
|
9016
|
-
},
|
|
9515
|
+
computeMode: "fenced",
|
|
9516
|
+
computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE"),
|
|
9017
9517
|
hit: false,
|
|
9018
9518
|
shouldCompute: true
|
|
9019
9519
|
};
|
|
9020
9520
|
}
|
|
9021
9521
|
function decodePayload(codec, value) {
|
|
9022
9522
|
if (value == null) return null;
|
|
9023
|
-
if (
|
|
9024
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
9025
|
-
if (typeof value === "string") return codec.decode(
|
|
9523
|
+
if (import_node_buffer32.Buffer.isBuffer(value)) return codec.decode(value);
|
|
9524
|
+
if (value instanceof Uint8Array) return codec.decode(import_node_buffer32.Buffer.from(value));
|
|
9525
|
+
if (typeof value === "string") return codec.decode(import_node_buffer32.Buffer.from(value));
|
|
9026
9526
|
return normalizeRefMeta(value);
|
|
9027
9527
|
}
|
|
9028
9528
|
function requiredResponseString(value, context) {
|
|
9029
|
-
if (typeof value !== "string" && !
|
|
9529
|
+
if (typeof value !== "string" && !import_node_buffer32.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9030
9530
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9031
9531
|
}
|
|
9032
9532
|
const result = text(value);
|
|
@@ -9043,7 +9543,7 @@ function requiredNonNegativeInteger(value, context) {
|
|
|
9043
9543
|
return result;
|
|
9044
9544
|
}
|
|
9045
9545
|
function responseBytes(value, context) {
|
|
9046
|
-
if (typeof value !== "string" && !
|
|
9546
|
+
if (typeof value !== "string" && !import_node_buffer32.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9047
9547
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9048
9548
|
}
|
|
9049
9549
|
return bytes(value);
|
|
@@ -9128,6 +9628,9 @@ function flowRecordFromResp(value, codec) {
|
|
|
9128
9628
|
field(value, "max_active_ms"),
|
|
9129
9629
|
"FLOW record max_active_ms"
|
|
9130
9630
|
);
|
|
9631
|
+
const rawError = field(value, "error");
|
|
9632
|
+
const error = flowError(rawError, codec);
|
|
9633
|
+
const failureReason = optionalResponseString(field(rawError, "reason"), "FLOW record error reason");
|
|
9131
9634
|
return {
|
|
9132
9635
|
id: requiredTextField(value, "id", "FLOW record"),
|
|
9133
9636
|
type: requiredTextField(value, "type", "FLOW record"),
|
|
@@ -9142,6 +9645,8 @@ function flowRecordFromResp(value, codec) {
|
|
|
9142
9645
|
rootFlowId: optionalResponseString(field(value, "root_flow_id"), "FLOW record root_flow_id"),
|
|
9143
9646
|
correlationId: optionalResponseString(field(value, "correlation_id"), "FLOW record correlation_id"),
|
|
9144
9647
|
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
9648
|
+
...error == null ? {} : { error },
|
|
9649
|
+
...failureReason == null ? {} : { failureReason },
|
|
9145
9650
|
valueRefs: optionalMapField(value, "value_refs", "FLOW record"),
|
|
9146
9651
|
values,
|
|
9147
9652
|
valueSizes: optionalMapField(value, "value_sizes", "FLOW record"),
|
|
@@ -9153,6 +9658,21 @@ function flowRecordFromResp(value, codec) {
|
|
|
9153
9658
|
raw: value
|
|
9154
9659
|
};
|
|
9155
9660
|
}
|
|
9661
|
+
function flowError(value, codec) {
|
|
9662
|
+
if (value == null) return void 0;
|
|
9663
|
+
const reason = optionalResponseString(field(value, "reason"), "FLOW record error reason");
|
|
9664
|
+
if (reason === "max_active_ms") {
|
|
9665
|
+
const maxActiveMs = optionalPositiveResponseInteger(
|
|
9666
|
+
field(value, "max_active_ms"),
|
|
9667
|
+
"FLOW record error max_active_ms"
|
|
9668
|
+
);
|
|
9669
|
+
if (maxActiveMs == null) {
|
|
9670
|
+
throw new TypeError("FLOW record error max_active_ms returned an unexpected response");
|
|
9671
|
+
}
|
|
9672
|
+
return { maxActiveMs, reason };
|
|
9673
|
+
}
|
|
9674
|
+
return decodePayload2(codec, value);
|
|
9675
|
+
}
|
|
9156
9676
|
function decodePayload2(codec, value) {
|
|
9157
9677
|
if (value == null) {
|
|
9158
9678
|
return null;
|
|
@@ -9733,7 +10253,7 @@ function groupAutoPartitionItems(items) {
|
|
|
9733
10253
|
}
|
|
9734
10254
|
|
|
9735
10255
|
// src/client-values.ts
|
|
9736
|
-
var
|
|
10256
|
+
var import_node_buffer33 = require("buffer");
|
|
9737
10257
|
async function valueMGetEntries(client, refs, options = {}) {
|
|
9738
10258
|
const refCount = refs.length;
|
|
9739
10259
|
if (refCount === 0) {
|
|
@@ -9768,12 +10288,12 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9768
10288
|
const item = response[index];
|
|
9769
10289
|
if (item == null) {
|
|
9770
10290
|
entries[index] = { found: false };
|
|
9771
|
-
} else if (
|
|
10291
|
+
} else if (import_node_buffer33.Buffer.isBuffer(item)) {
|
|
9772
10292
|
entries[index] = { found: true, value: client.codec.decode(item) };
|
|
9773
10293
|
} else if (item instanceof Uint8Array) {
|
|
9774
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10294
|
+
entries[index] = { found: true, value: client.codec.decode(import_node_buffer33.Buffer.from(item)) };
|
|
9775
10295
|
} else if (typeof item === "string") {
|
|
9776
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10296
|
+
entries[index] = { found: true, value: client.codec.decode(import_node_buffer33.Buffer.from(item)) };
|
|
9777
10297
|
} else {
|
|
9778
10298
|
entries[index] = { found: true, value: item };
|
|
9779
10299
|
}
|
|
@@ -9782,10 +10302,10 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9782
10302
|
}
|
|
9783
10303
|
|
|
9784
10304
|
// src/auto-batch.ts
|
|
9785
|
-
var
|
|
10305
|
+
var import_node_buffer35 = require("buffer");
|
|
9786
10306
|
|
|
9787
10307
|
// src/auto-batch-ordering.ts
|
|
9788
|
-
var
|
|
10308
|
+
var import_node_buffer34 = require("buffer");
|
|
9789
10309
|
function autoBatchOrderingPlan(batch) {
|
|
9790
10310
|
const accesses = /* @__PURE__ */ new Map();
|
|
9791
10311
|
const fallbackDependencies = [];
|
|
@@ -9900,13 +10420,13 @@ function flowManyAutoBatchIds(command, name) {
|
|
|
9900
10420
|
return fixedFlowItemIds(
|
|
9901
10421
|
command,
|
|
9902
10422
|
mixed ? 4 : 3,
|
|
9903
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) &&
|
|
10423
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && import_node_buffer34.Buffer.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
|
|
9904
10424
|
);
|
|
9905
10425
|
}
|
|
9906
10426
|
return fixedFlowItemIds(
|
|
9907
10427
|
command,
|
|
9908
10428
|
mixed ? 4 : 3,
|
|
9909
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10429
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer34.Buffer.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
|
|
9910
10430
|
);
|
|
9911
10431
|
}
|
|
9912
10432
|
function createManyAutoBatchIds(command) {
|
|
@@ -9919,7 +10439,7 @@ function createManyAutoBatchIds(command) {
|
|
|
9919
10439
|
const ids = fixedFlowItemIds(
|
|
9920
10440
|
command,
|
|
9921
10441
|
width,
|
|
9922
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10442
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && import_node_buffer34.Buffer.isBuffer(command[itemIndex + width - 1]),
|
|
9923
10443
|
markerIndex
|
|
9924
10444
|
);
|
|
9925
10445
|
if (ids != null) return ids;
|
|
@@ -9937,7 +10457,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
|
|
|
9937
10457
|
let cursor = markerIndex + 2;
|
|
9938
10458
|
for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
|
|
9939
10459
|
const id = command[cursor];
|
|
9940
|
-
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !
|
|
10460
|
+
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !import_node_buffer34.Buffer.isBuffer(command[cursor + 2])) return void 0;
|
|
9941
10461
|
ids.push(id);
|
|
9942
10462
|
cursor += 3;
|
|
9943
10463
|
const afterValues = skipExtendedNamedItems(command, cursor, true);
|
|
@@ -9956,7 +10476,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
|
|
|
9956
10476
|
for (let index = 0; index < count; index += 1) {
|
|
9957
10477
|
const name = command[firstItem + index * 2];
|
|
9958
10478
|
const value = command[firstItem + index * 2 + 1];
|
|
9959
|
-
if (!isAutoBatchResourceValue(name) || (encodedValues ? !
|
|
10479
|
+
if (!isAutoBatchResourceValue(name) || (encodedValues ? !import_node_buffer34.Buffer.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
|
|
9960
10480
|
}
|
|
9961
10481
|
return firstItem + count * 2;
|
|
9962
10482
|
}
|
|
@@ -9971,7 +10491,7 @@ function runStepsManyAutoBatchIds(command) {
|
|
|
9971
10491
|
ids.push(item);
|
|
9972
10492
|
continue;
|
|
9973
10493
|
}
|
|
9974
|
-
if (typeof item !== "object" || item == null || Array.isArray(item) ||
|
|
10494
|
+
if (typeof item !== "object" || item == null || Array.isArray(item) || import_node_buffer34.Buffer.isBuffer(item)) return void 0;
|
|
9975
10495
|
const id = item.id;
|
|
9976
10496
|
if (!isAutoBatchResourceValue(id)) return void 0;
|
|
9977
10497
|
ids.push(id);
|
|
@@ -10012,7 +10532,7 @@ function flowValuePutOwner(command, start) {
|
|
|
10012
10532
|
}
|
|
10013
10533
|
var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
|
|
10014
10534
|
function isAutoBatchResourceValue(value) {
|
|
10015
|
-
return typeof value === "string" ||
|
|
10535
|
+
return typeof value === "string" || import_node_buffer34.Buffer.isBuffer(value);
|
|
10016
10536
|
}
|
|
10017
10537
|
function isFencingToken(value) {
|
|
10018
10538
|
return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
|
|
@@ -10021,7 +10541,7 @@ function nonNegativeItemCount(value) {
|
|
|
10021
10541
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
10022
10542
|
}
|
|
10023
10543
|
function autoBatchResourceKey(namespace, value) {
|
|
10024
|
-
return `${namespace}:${
|
|
10544
|
+
return `${namespace}:${import_node_buffer34.Buffer.from(value).toString("base64")}`;
|
|
10025
10545
|
}
|
|
10026
10546
|
function autoBatchCommandName(command) {
|
|
10027
10547
|
return commandView(command).name ?? null;
|
|
@@ -10430,15 +10950,15 @@ function claimFailure(error) {
|
|
|
10430
10950
|
}
|
|
10431
10951
|
|
|
10432
10952
|
// src/client-flow-support.ts
|
|
10433
|
-
var
|
|
10953
|
+
var import_node_buffer42 = require("buffer");
|
|
10434
10954
|
|
|
10435
10955
|
// src/client-core.ts
|
|
10436
|
-
var
|
|
10956
|
+
var import_node_buffer40 = require("buffer");
|
|
10437
10957
|
|
|
10438
10958
|
// src/client-core-helpers.ts
|
|
10439
|
-
var
|
|
10959
|
+
var import_node_buffer36 = require("buffer");
|
|
10440
10960
|
function bgsaveResponse(response) {
|
|
10441
|
-
if ((typeof response === "string" ||
|
|
10961
|
+
if ((typeof response === "string" || import_node_buffer36.Buffer.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
|
|
10442
10962
|
return true;
|
|
10443
10963
|
}
|
|
10444
10964
|
return okResponse(response);
|
|
@@ -10449,11 +10969,11 @@ function clientNameResponse(response) {
|
|
|
10449
10969
|
function fetchOrComputeCompletionToken(options) {
|
|
10450
10970
|
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
10451
10971
|
throw new TypeError(
|
|
10452
|
-
"fetch-or-compute completion requires computeToken
|
|
10972
|
+
"fetch-or-compute completion requires computeToken"
|
|
10453
10973
|
);
|
|
10454
10974
|
}
|
|
10455
|
-
if (
|
|
10456
|
-
throw new TypeError("fetch-or-compute computeToken must be a Buffer
|
|
10975
|
+
if (!import_node_buffer36.Buffer.isBuffer(options.computeToken)) {
|
|
10976
|
+
throw new TypeError("fetch-or-compute computeToken must be a Buffer");
|
|
10457
10977
|
}
|
|
10458
10978
|
return options.computeToken;
|
|
10459
10979
|
}
|
|
@@ -10475,10 +10995,10 @@ function unsupportedClientCaching() {
|
|
|
10475
10995
|
}
|
|
10476
10996
|
|
|
10477
10997
|
// src/client-base.ts
|
|
10478
|
-
var
|
|
10998
|
+
var import_node_buffer38 = require("buffer");
|
|
10479
10999
|
|
|
10480
11000
|
// src/client-executor.ts
|
|
10481
|
-
var
|
|
11001
|
+
var import_node_buffer37 = require("buffer");
|
|
10482
11002
|
var ErrorMappingExecutor = class {
|
|
10483
11003
|
constructor(executor) {
|
|
10484
11004
|
this.executor = executor;
|
|
@@ -10575,14 +11095,17 @@ var FerricStoreClientBase = class {
|
|
|
10575
11095
|
};
|
|
10576
11096
|
}
|
|
10577
11097
|
async command(...args) {
|
|
11098
|
+
assertAtomicKeyValueCommandSharesSlot(args);
|
|
10578
11099
|
return await executeCommandArgs(this.executor, args);
|
|
10579
11100
|
}
|
|
10580
11101
|
/** Execute an already-built command without a JavaScript variadic-call limit. */
|
|
10581
11102
|
async commandArgs(args) {
|
|
11103
|
+
assertAtomicKeyValueCommandSharesSlot(args);
|
|
10582
11104
|
return await executeCommandArgs(this.executor, args);
|
|
10583
11105
|
}
|
|
10584
11106
|
async pipeline(commands, options) {
|
|
10585
11107
|
const snapshot = snapshotPipelineCommands(commands);
|
|
11108
|
+
for (const command of snapshot) assertAtomicKeyValueCommandSharesSlot(command);
|
|
10586
11109
|
const snapshotOptions = snapshotPipelineOptions(options);
|
|
10587
11110
|
const results = this.executor.executePipeline != null ? await this.executor.executePipeline(snapshot, snapshotOptions) : await executeCommandArraysIndividually(
|
|
10588
11111
|
async (command) => await this.commandArgs(command),
|
|
@@ -10809,14 +11332,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
|
|
|
10809
11332
|
};
|
|
10810
11333
|
|
|
10811
11334
|
// src/store-utilities.ts
|
|
10812
|
-
var
|
|
11335
|
+
var import_node_buffer39 = require("buffer");
|
|
10813
11336
|
function encode(codec, value) {
|
|
10814
11337
|
return codec.encode(value);
|
|
10815
11338
|
}
|
|
10816
11339
|
function decode(codec, value) {
|
|
10817
11340
|
if (value == null) return null;
|
|
10818
|
-
if (
|
|
10819
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
11341
|
+
if (import_node_buffer39.Buffer.isBuffer(value)) return codec.decode(value);
|
|
11342
|
+
if (value instanceof Uint8Array) return codec.decode(import_node_buffer39.Buffer.from(value));
|
|
10820
11343
|
return value;
|
|
10821
11344
|
}
|
|
10822
11345
|
function number(value) {
|
|
@@ -10877,7 +11400,7 @@ function requireNonEmpty(values, command, noun = "argument") {
|
|
|
10877
11400
|
if (values.length === 0) throw new TypeError(`${command} requires at least one ${noun}`);
|
|
10878
11401
|
return values;
|
|
10879
11402
|
}
|
|
10880
|
-
function
|
|
11403
|
+
function commandName4(args) {
|
|
10881
11404
|
return typeof args[0] === "string" ? args[0] : "command";
|
|
10882
11405
|
}
|
|
10883
11406
|
function commandArgs(client, args) {
|
|
@@ -10892,7 +11415,7 @@ function arrayOrRest(values) {
|
|
|
10892
11415
|
function appendXReadStreams(args, streams) {
|
|
10893
11416
|
const offset = args.length;
|
|
10894
11417
|
const streamCount = streams.length;
|
|
10895
|
-
requireNonEmpty(streams,
|
|
11418
|
+
requireNonEmpty(streams, commandName4(args), "stream");
|
|
10896
11419
|
args.length = offset + 1 + streamCount * 2;
|
|
10897
11420
|
args[offset] = "STREAMS";
|
|
10898
11421
|
for (let index = 0; index < streamCount; index += 1) {
|
|
@@ -10902,7 +11425,7 @@ function appendXReadStreams(args, streams) {
|
|
|
10902
11425
|
const stream = streams[index];
|
|
10903
11426
|
if (stream == null) throw new TypeError("XREAD streams must contain only stream descriptors");
|
|
10904
11427
|
if (!Object.hasOwn(stream, "key") || !Object.hasOwn(stream, "id")) {
|
|
10905
|
-
throw new TypeError(`${
|
|
11428
|
+
throw new TypeError(`${commandName4(args)} streams require own key and id fields`);
|
|
10906
11429
|
}
|
|
10907
11430
|
args[offset + 1 + index] = stream.key;
|
|
10908
11431
|
args[offset + 1 + streamCount + index] = stream.id;
|
|
@@ -10924,7 +11447,7 @@ function concatArgs(...parts) {
|
|
|
10924
11447
|
return args;
|
|
10925
11448
|
}
|
|
10926
11449
|
function encodedArgs(prefix, codec, values, allowEmpty = false) {
|
|
10927
|
-
if (!allowEmpty) requireNonEmpty(values,
|
|
11450
|
+
if (!allowEmpty) requireNonEmpty(values, commandName4(prefix));
|
|
10928
11451
|
const args = new Array(prefix.length + values.length);
|
|
10929
11452
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
10930
11453
|
for (let index = 0; index < values.length; index += 1) {
|
|
@@ -10938,7 +11461,7 @@ function encodedArgs(prefix, codec, values, allowEmpty = false) {
|
|
|
10938
11461
|
function keyValueArgs(prefix, codec, entries) {
|
|
10939
11462
|
const validateTuples = Array.isArray(entries);
|
|
10940
11463
|
const pairs = validateTuples ? entries : Object.entries(entries);
|
|
10941
|
-
requireNonEmpty(pairs,
|
|
11464
|
+
requireNonEmpty(pairs, commandName4(prefix), "entry");
|
|
10942
11465
|
const args = new Array(prefix.length + pairs.length * 2);
|
|
10943
11466
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
10944
11467
|
for (let index = 0; index < pairs.length; index += 1) {
|
|
@@ -10952,7 +11475,7 @@ function keyValueArgs(prefix, codec, entries) {
|
|
|
10952
11475
|
return args;
|
|
10953
11476
|
}
|
|
10954
11477
|
function encodedEntryArgs(prefix, codec, entries) {
|
|
10955
|
-
requireNonEmpty(entries,
|
|
11478
|
+
requireNonEmpty(entries, commandName4(prefix), "entry");
|
|
10956
11479
|
const args = new Array(prefix.length + entries.length * 2);
|
|
10957
11480
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
10958
11481
|
for (let index = 0; index < entries.length; index += 1) {
|
|
@@ -11222,12 +11745,15 @@ var TopKStore = class {
|
|
|
11222
11745
|
const width = ownOption(options, "width");
|
|
11223
11746
|
const depth = ownOption(options, "depth");
|
|
11224
11747
|
const decay = ownOption(options, "decay");
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
|
|
11748
|
+
if (decay != null || Object.hasOwn(options, "decay")) {
|
|
11749
|
+
throw new TypeError("TOPK.RESERVE decay is not supported by FerricStore 0.8");
|
|
11750
|
+
}
|
|
11751
|
+
const tuningCount = [width, depth].filter((value) => value != null).length;
|
|
11752
|
+
if (tuningCount !== 0 && tuningCount !== 2) {
|
|
11753
|
+
throw new TypeError("TOPK.RESERVE width and depth must be provided together");
|
|
11228
11754
|
}
|
|
11229
|
-
if (tuningCount ===
|
|
11230
|
-
args.push(width, depth
|
|
11755
|
+
if (tuningCount === 2) {
|
|
11756
|
+
args.push(width, depth);
|
|
11231
11757
|
}
|
|
11232
11758
|
return okResponse(await commandArgs(this.client, args));
|
|
11233
11759
|
}
|
|
@@ -11633,10 +12159,14 @@ var KeyValueStore = class {
|
|
|
11633
12159
|
);
|
|
11634
12160
|
}
|
|
11635
12161
|
async mset(entries) {
|
|
11636
|
-
|
|
12162
|
+
const args = keyValueArgs(["MSET"], this.client.codec, entries);
|
|
12163
|
+
assertKeyValueCommandSharesSlot(args, "MSET");
|
|
12164
|
+
return okResponse(await commandArgs(this.client, args));
|
|
11637
12165
|
}
|
|
11638
12166
|
async msetnx(entries) {
|
|
11639
|
-
|
|
12167
|
+
const args = keyValueArgs(["MSETNX"], this.client.codec, entries);
|
|
12168
|
+
assertKeyValueCommandSharesSlot(args, "MSETNX");
|
|
12169
|
+
return binaryBooleanResponse(await commandArgs(this.client, args));
|
|
11640
12170
|
}
|
|
11641
12171
|
async incr(key) {
|
|
11642
12172
|
return integerReply(await this.client.command("INCR", key));
|
|
@@ -12706,7 +13236,8 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
|
|
|
12706
13236
|
return okResponse(await this.command(
|
|
12707
13237
|
"FETCH_OR_COMPUTE_RESULT",
|
|
12708
13238
|
key,
|
|
12709
|
-
|
|
13239
|
+
computeToken,
|
|
13240
|
+
encoded,
|
|
12710
13241
|
options.ttlMs
|
|
12711
13242
|
));
|
|
12712
13243
|
}
|
|
@@ -12715,7 +13246,7 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
|
|
|
12715
13246
|
return okResponse(await this.command(
|
|
12716
13247
|
"FETCH_OR_COMPUTE_ERROR",
|
|
12717
13248
|
key,
|
|
12718
|
-
|
|
13249
|
+
computeToken,
|
|
12719
13250
|
message
|
|
12720
13251
|
));
|
|
12721
13252
|
}
|
|
@@ -12841,7 +13372,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
12841
13372
|
}
|
|
12842
13373
|
async effectGet(id, effectKey, options = {}) {
|
|
12843
13374
|
const args = ["FLOW.EFFECT.GET", id, "EFFECT_KEY", effectKey];
|
|
12844
|
-
append(args, "PARTITION", options.partitionKey
|
|
13375
|
+
append(args, "PARTITION", options.partitionKey);
|
|
12845
13376
|
return optionalAdminRecord(await this.commandArgs(args), "FLOW.EFFECT.GET");
|
|
12846
13377
|
}
|
|
12847
13378
|
async effectStatus(command, id, effectKey, options) {
|
|
@@ -13013,7 +13544,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
13013
13544
|
}
|
|
13014
13545
|
async governanceLedger(id, options = {}) {
|
|
13015
13546
|
const args = ["FLOW.GOVERNANCE.LEDGER", id];
|
|
13016
|
-
append(args, "PARTITION", options.partitionKey
|
|
13547
|
+
append(args, "PARTITION", options.partitionKey);
|
|
13017
13548
|
append(args, "LIMIT", options.limit);
|
|
13018
13549
|
append(args, "FROM_MS", options.fromMs);
|
|
13019
13550
|
append(args, "TO_MS", options.toMs);
|
|
@@ -13029,7 +13560,7 @@ async function executeProducerWriteWithBackpressure(execute, policy, signal) {
|
|
|
13029
13560
|
try {
|
|
13030
13561
|
return await execute();
|
|
13031
13562
|
} catch (error) {
|
|
13032
|
-
if (!(error instanceof OverloadedError) || attempt >= policy.maxRetries) throw error;
|
|
13563
|
+
if (!(error instanceof OverloadedError) || error.retryable !== true || error.safeToRetry !== true || attempt >= policy.maxRetries) throw error;
|
|
13033
13564
|
const exponential = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** attempt);
|
|
13034
13565
|
const base = Math.min(policy.maxDelayMs, error.retryAfterMs ?? exponential);
|
|
13035
13566
|
const jitter = base * (policy.jitterPct / 100) * Math.random();
|
|
@@ -13043,6 +13574,165 @@ function throwIfClosed(signal) {
|
|
|
13043
13574
|
throw new FerricStoreError("FerricStore client is closed", { raw: signal.reason });
|
|
13044
13575
|
}
|
|
13045
13576
|
|
|
13577
|
+
// src/flow-policy.ts
|
|
13578
|
+
var import_node_buffer41 = require("buffer");
|
|
13579
|
+
var MAX_FLOW_POLICY_GENERATION = Number.MAX_SAFE_INTEGER;
|
|
13580
|
+
function assertFlowPolicyGeneration(value) {
|
|
13581
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
13582
|
+
throw new TypeError("expectedGeneration must be a nonnegative safe integer");
|
|
13583
|
+
}
|
|
13584
|
+
}
|
|
13585
|
+
function flowPolicySnapshotFromResp(value) {
|
|
13586
|
+
const policy = requiredRecord(value, "FLOW policy snapshot");
|
|
13587
|
+
const maxActiveMs = optionalPositiveInteger(field(policy, "max_active_ms"), "max_active_ms");
|
|
13588
|
+
const state = optionalText2(field(policy, "state"), "state");
|
|
13589
|
+
const mode = optionalMode(field(policy, "mode"), "mode");
|
|
13590
|
+
const version = optionalVersion(field(policy, "version"));
|
|
13591
|
+
const indexedStateMeta = optionalText2(field(policy, "indexed_state_meta"), "indexed_state_meta");
|
|
13592
|
+
const governance = optionalRecord(field(policy, "governance"), "governance");
|
|
13593
|
+
const states = optionalStates(field(policy, "states"));
|
|
13594
|
+
return {
|
|
13595
|
+
type: requiredText(field(policy, "type"), "type"),
|
|
13596
|
+
generation: nonNegativeInteger(field(policy, "generation"), "generation"),
|
|
13597
|
+
...state == null ? {} : { state },
|
|
13598
|
+
...version == null ? {} : { version },
|
|
13599
|
+
...mode == null ? {} : { mode },
|
|
13600
|
+
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
13601
|
+
retry: retrySnapshot(field(policy, "retry"), "retry"),
|
|
13602
|
+
retention: retentionSnapshot(field(policy, "retention"), "retention"),
|
|
13603
|
+
indexedAttributes: stringArray(field(policy, "indexed_attributes"), "indexed_attributes"),
|
|
13604
|
+
...indexedStateMeta == null ? {} : { indexedStateMeta },
|
|
13605
|
+
...governance == null ? {} : { governance },
|
|
13606
|
+
...states == null ? {} : { states },
|
|
13607
|
+
raw: value
|
|
13608
|
+
};
|
|
13609
|
+
}
|
|
13610
|
+
function retrySnapshot(value, context) {
|
|
13611
|
+
const retry2 = requiredRecord(value, `FLOW policy ${context}`);
|
|
13612
|
+
const backoff = requiredRecord(field(retry2, "backoff"), `FLOW policy ${context}.backoff`);
|
|
13613
|
+
return {
|
|
13614
|
+
maxRetries: nonNegativeInteger(field(retry2, "max_retries"), `${context}.max_retries`),
|
|
13615
|
+
backoff: {
|
|
13616
|
+
kind: backoffKind(field(backoff, "kind"), `${context}.backoff.kind`),
|
|
13617
|
+
baseMs: nonNegativeInteger(field(backoff, "base_ms"), `${context}.backoff.base_ms`),
|
|
13618
|
+
maxMs: nonNegativeInteger(field(backoff, "max_ms"), `${context}.backoff.max_ms`),
|
|
13619
|
+
jitterPct: nonNegativeInteger(field(backoff, "jitter_pct"), `${context}.backoff.jitter_pct`)
|
|
13620
|
+
},
|
|
13621
|
+
exhaustedTo: requiredText(field(retry2, "exhausted_to"), `${context}.exhausted_to`)
|
|
13622
|
+
};
|
|
13623
|
+
}
|
|
13624
|
+
function retentionSnapshot(value, context) {
|
|
13625
|
+
const retention = requiredRecord(value, `FLOW policy ${context}`);
|
|
13626
|
+
return {
|
|
13627
|
+
ttlMs: nonNegativeInteger(field(retention, "ttl_ms"), `${context}.ttl_ms`),
|
|
13628
|
+
historyMaxEvents: nonNegativeInteger(
|
|
13629
|
+
field(retention, "history_max_events"),
|
|
13630
|
+
`${context}.history_max_events`
|
|
13631
|
+
)
|
|
13632
|
+
};
|
|
13633
|
+
}
|
|
13634
|
+
function optionalStates(value) {
|
|
13635
|
+
if (value == null) return void 0;
|
|
13636
|
+
const source = requiredRecord(value, "FLOW policy states");
|
|
13637
|
+
const result = {};
|
|
13638
|
+
for (const [state, raw] of Object.entries(source)) {
|
|
13639
|
+
const policy = requiredRecord(raw, `FLOW policy state ${state}`);
|
|
13640
|
+
const maxActiveMs = optionalPositiveInteger(
|
|
13641
|
+
field(policy, "max_active_ms"),
|
|
13642
|
+
`states.${state}.max_active_ms`
|
|
13643
|
+
);
|
|
13644
|
+
const governance = optionalRecord(field(policy, "governance"), `states.${state}.governance`);
|
|
13645
|
+
Object.defineProperty(result, state, {
|
|
13646
|
+
configurable: true,
|
|
13647
|
+
enumerable: true,
|
|
13648
|
+
value: {
|
|
13649
|
+
mode: requiredMode(field(policy, "mode"), `states.${state}.mode`),
|
|
13650
|
+
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
13651
|
+
retry: retrySnapshot(field(policy, "retry"), `states.${state}.retry`),
|
|
13652
|
+
retention: retentionSnapshot(field(policy, "retention"), `states.${state}.retention`),
|
|
13653
|
+
...governance == null ? {} : { governance }
|
|
13654
|
+
},
|
|
13655
|
+
writable: true
|
|
13656
|
+
});
|
|
13657
|
+
}
|
|
13658
|
+
return result;
|
|
13659
|
+
}
|
|
13660
|
+
function requiredRecord(value, context) {
|
|
13661
|
+
if (value instanceof Map) {
|
|
13662
|
+
const result = {};
|
|
13663
|
+
for (const [key, item] of value.entries()) {
|
|
13664
|
+
setOwnValue(result, requiredText(key, `${context} key`), item);
|
|
13665
|
+
}
|
|
13666
|
+
return result;
|
|
13667
|
+
}
|
|
13668
|
+
if (typeof value === "object" && value != null && !Array.isArray(value) && !import_node_buffer41.Buffer.isBuffer(value) && !(value instanceof Uint8Array)) return value;
|
|
13669
|
+
throw new TypeError(`${context} returned an unexpected response`);
|
|
13670
|
+
}
|
|
13671
|
+
function optionalRecord(value, context) {
|
|
13672
|
+
return value == null ? void 0 : requiredRecord(value, `FLOW policy ${context}`);
|
|
13673
|
+
}
|
|
13674
|
+
function stringArray(value, context) {
|
|
13675
|
+
if (!Array.isArray(value)) {
|
|
13676
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13677
|
+
}
|
|
13678
|
+
const result = new Array(value.length);
|
|
13679
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
13680
|
+
if (!Object.hasOwn(value, index)) {
|
|
13681
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13682
|
+
}
|
|
13683
|
+
result[index] = requiredText(value[index], `${context}[${index}]`);
|
|
13684
|
+
}
|
|
13685
|
+
return result;
|
|
13686
|
+
}
|
|
13687
|
+
function requiredText(value, context) {
|
|
13688
|
+
if (typeof value === "string") return value;
|
|
13689
|
+
if (import_node_buffer41.Buffer.isBuffer(value) || value instanceof Uint8Array) {
|
|
13690
|
+
return import_node_buffer41.Buffer.from(value).toString("utf8");
|
|
13691
|
+
}
|
|
13692
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13693
|
+
}
|
|
13694
|
+
function optionalText2(value, context) {
|
|
13695
|
+
return value == null ? void 0 : requiredText(value, context);
|
|
13696
|
+
}
|
|
13697
|
+
function nonNegativeInteger(value, context) {
|
|
13698
|
+
let parsed;
|
|
13699
|
+
try {
|
|
13700
|
+
parsed = integer(value);
|
|
13701
|
+
} catch {
|
|
13702
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13703
|
+
}
|
|
13704
|
+
if (parsed < 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13705
|
+
return parsed;
|
|
13706
|
+
}
|
|
13707
|
+
function optionalPositiveInteger(value, context) {
|
|
13708
|
+
if (value == null) return void 0;
|
|
13709
|
+
const parsed = nonNegativeInteger(value, context);
|
|
13710
|
+
if (parsed === 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13711
|
+
return parsed;
|
|
13712
|
+
}
|
|
13713
|
+
function optionalVersion(value) {
|
|
13714
|
+
if (value == null) return void 0;
|
|
13715
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
13716
|
+
return nonNegativeInteger(value, "version");
|
|
13717
|
+
}
|
|
13718
|
+
return requiredText(value, "version");
|
|
13719
|
+
}
|
|
13720
|
+
function backoffKind(value, context) {
|
|
13721
|
+
const kind = requiredText(value, context).toLowerCase();
|
|
13722
|
+
if (kind === "none" || kind === "fixed" || kind === "linear" || kind === "exponential") {
|
|
13723
|
+
return kind;
|
|
13724
|
+
}
|
|
13725
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13726
|
+
}
|
|
13727
|
+
function requiredMode(value, context) {
|
|
13728
|
+
const mode = requiredText(value, context).toLowerCase();
|
|
13729
|
+
if (mode === "fifo" || mode === "parallel") return mode;
|
|
13730
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
13731
|
+
}
|
|
13732
|
+
function optionalMode(value, context) {
|
|
13733
|
+
return value == null ? void 0 : requiredMode(value, context);
|
|
13734
|
+
}
|
|
13735
|
+
|
|
13046
13736
|
// src/client-flow-support.ts
|
|
13047
13737
|
var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
13048
13738
|
async rewind(id, options = {}) {
|
|
@@ -13185,27 +13875,36 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13185
13875
|
}
|
|
13186
13876
|
async installPolicy(type, options = {}) {
|
|
13187
13877
|
const args = ["FLOW.POLICY.SET", type];
|
|
13878
|
+
const expectedGeneration = Object.hasOwn(options, "expectedGeneration") ? options.expectedGeneration : void 0;
|
|
13879
|
+
const replace = Object.hasOwn(options, "replace") ? options.replace : void 0;
|
|
13880
|
+
if (expectedGeneration != null) assertFlowPolicyGeneration(expectedGeneration);
|
|
13881
|
+
if (replace != null && typeof replace !== "boolean") {
|
|
13882
|
+
throw new TypeError("replace must be a boolean");
|
|
13883
|
+
}
|
|
13884
|
+
append(args, "EXPECTED_GENERATION", expectedGeneration);
|
|
13885
|
+
appendBool(args, "REPLACE", replace);
|
|
13188
13886
|
if (options.indexedAttributes != null) {
|
|
13189
13887
|
args.push("INDEXED_ATTRIBUTES", JSON.stringify(options.indexedAttributes));
|
|
13190
13888
|
}
|
|
13191
13889
|
append(args, "INDEXED_STATE_META", options.indexedStateMeta);
|
|
13192
13890
|
append(args, "MAX_ACTIVE_MS", options.maxActiveMs);
|
|
13891
|
+
if (options.state == null) append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
13193
13892
|
append(args, "STATE", options.state);
|
|
13194
13893
|
appendPolicyMode(args, options.state, options.mode);
|
|
13195
13894
|
if (options.retry != null) {
|
|
13196
13895
|
appendRetryPolicy(args, options.retry);
|
|
13197
13896
|
}
|
|
13897
|
+
if (options.state != null) append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
13198
13898
|
for (const [state, policy] of Object.entries(options.states ?? {})) {
|
|
13199
13899
|
args.push("STATE", state);
|
|
13200
13900
|
appendFlowStatePolicy(args, policy);
|
|
13201
13901
|
}
|
|
13202
|
-
|
|
13203
|
-
return await this.commandArgs(args);
|
|
13902
|
+
return flowPolicySnapshotFromResp(await this.commandArgs(args));
|
|
13204
13903
|
}
|
|
13205
13904
|
async policyGet(type, options = {}) {
|
|
13206
13905
|
const args = ["FLOW.POLICY.GET", type];
|
|
13207
13906
|
append(args, "STATE", options.state);
|
|
13208
|
-
return
|
|
13907
|
+
return flowPolicySnapshotFromResp(await this.commandArgs(args));
|
|
13209
13908
|
}
|
|
13210
13909
|
async retentionCleanup() {
|
|
13211
13910
|
return parseKvResponse(await this.command("FLOW.RETENTION_CLEANUP"));
|
|
@@ -13294,7 +13993,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13294
13993
|
};
|
|
13295
13994
|
|
|
13296
13995
|
// src/flow-many-snapshot.ts
|
|
13297
|
-
var
|
|
13996
|
+
var import_node_buffer43 = require("buffer");
|
|
13298
13997
|
var encodedOptionFields = ["error", "payload", "reason", "result"];
|
|
13299
13998
|
function snapshotCreateItem(item, codec) {
|
|
13300
13999
|
const snapshot = {
|
|
@@ -13334,7 +14033,7 @@ function snapshotFlowManyOptions(options, codec) {
|
|
|
13334
14033
|
}
|
|
13335
14034
|
function snapshotClaimedItem(item) {
|
|
13336
14035
|
const wire = item[CLAIMED_ITEM_WIRE];
|
|
13337
|
-
const leaseToken =
|
|
14036
|
+
const leaseToken = import_node_buffer43.Buffer.from(wire?.leaseToken ?? item.leaseToken);
|
|
13338
14037
|
const snapshot = {
|
|
13339
14038
|
...item,
|
|
13340
14039
|
fencingToken: wire?.fencingToken ?? item.fencingToken,
|
|
@@ -13351,15 +14050,15 @@ function snapshotClaimedItem(item) {
|
|
|
13351
14050
|
function snapshotFencedItem(item) {
|
|
13352
14051
|
return Object.freeze({
|
|
13353
14052
|
...item,
|
|
13354
|
-
...item.leaseToken == null ? {} : { leaseToken:
|
|
14053
|
+
...item.leaseToken == null ? {} : { leaseToken: import_node_buffer43.Buffer.from(item.leaseToken) }
|
|
13355
14054
|
});
|
|
13356
14055
|
}
|
|
13357
14056
|
function snapshotClaimedItemWire(wire, leaseToken) {
|
|
13358
14057
|
return Object.freeze({
|
|
13359
14058
|
fencingToken: wire.fencingToken,
|
|
13360
|
-
id:
|
|
14059
|
+
id: import_node_buffer43.Buffer.from(wire.id),
|
|
13361
14060
|
leaseToken,
|
|
13362
|
-
partitionKey: wire.partitionKey == null ? wire.partitionKey :
|
|
14061
|
+
partitionKey: wire.partitionKey == null ? wire.partitionKey : import_node_buffer43.Buffer.from(wire.partitionKey)
|
|
13363
14062
|
});
|
|
13364
14063
|
}
|
|
13365
14064
|
function snapshotArray(values) {
|
|
@@ -13370,7 +14069,7 @@ function snapshotArray(values) {
|
|
|
13370
14069
|
return Object.freeze(snapshot);
|
|
13371
14070
|
}
|
|
13372
14071
|
function snapshotStateMeta(stateMeta) {
|
|
13373
|
-
return snapshotRecord(stateMeta, (value) =>
|
|
14072
|
+
return snapshotRecord(stateMeta, (value) => import_node_buffer43.Buffer.isBuffer(value) ? import_node_buffer43.Buffer.from(value) : value);
|
|
13374
14073
|
}
|
|
13375
14074
|
function snapshotCommandRecord(values) {
|
|
13376
14075
|
const seen = /* @__PURE__ */ new WeakMap();
|
|
@@ -13388,7 +14087,7 @@ function snapshotRecord(values, capture) {
|
|
|
13388
14087
|
}
|
|
13389
14088
|
function snapshotCommandArgument(value, seen) {
|
|
13390
14089
|
if (typeof value !== "object" || value == null) return value;
|
|
13391
|
-
if (
|
|
14090
|
+
if (import_node_buffer43.Buffer.isBuffer(value) || value instanceof Uint8Array) return import_node_buffer43.Buffer.from(value);
|
|
13392
14091
|
const objectValue = value;
|
|
13393
14092
|
const existing = seen.get(objectValue);
|
|
13394
14093
|
if (existing != null) return existing;
|
|
@@ -14186,6 +14885,9 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14186
14885
|
return new _FerricStoreClient(executor, clientOptions);
|
|
14187
14886
|
}
|
|
14188
14887
|
async valuePut(value, options = {}) {
|
|
14888
|
+
if (options.ownerFlowId != null && options.name != null && options.ttlMs != null) {
|
|
14889
|
+
throw new TypeError("named Flow values cannot have a TTL");
|
|
14890
|
+
}
|
|
14189
14891
|
const args = ["FLOW.VALUE.PUT", this.codec.encode(value), "NOW", options.nowMs ?? nowMs()];
|
|
14190
14892
|
append(args, "PARTITION", options.partitionKey);
|
|
14191
14893
|
append(args, "OWNER_FLOW_ID", options.ownerFlowId);
|
|
@@ -14217,7 +14919,6 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14217
14919
|
append(args, "TRANSITION_TO", options.transitionTo);
|
|
14218
14920
|
append(args, "RUN_AT", options.runAtMs);
|
|
14219
14921
|
append(args, "NOW", options.nowMs ?? nowMs());
|
|
14220
|
-
append(args, "PRIORITY", options.priority);
|
|
14221
14922
|
appendNamedValues(args, this.codec, options);
|
|
14222
14923
|
return await this.commandArgs(args);
|
|
14223
14924
|
}
|
|
@@ -14247,6 +14948,7 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14247
14948
|
append(args, "CORRELATION_ID", options.correlationId);
|
|
14248
14949
|
append(args, "PRIORITY", options.priority);
|
|
14249
14950
|
append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
14951
|
+
append(args, "MAX_ACTIVE_MS", options.maxActiveMs);
|
|
14250
14952
|
appendAttributes(args, options.attributes);
|
|
14251
14953
|
appendStateMeta(args, options.stateMeta);
|
|
14252
14954
|
appendNamedValues(args, this.codec, options);
|
|
@@ -14607,7 +15309,7 @@ async function runContinuousWorkerPool(options) {
|
|
|
14607
15309
|
initialIdleSleepMs,
|
|
14608
15310
|
nonNegativeDuration(options.maxIdleSleepMs, 5e3)
|
|
14609
15311
|
);
|
|
14610
|
-
const refillDelayMs =
|
|
15312
|
+
const refillDelayMs = nonNegativeInteger2(options.refillDelayMs, 0);
|
|
14611
15313
|
const active = /* @__PURE__ */ new Set();
|
|
14612
15314
|
const pending = [];
|
|
14613
15315
|
let pendingIndex = 0;
|
|
@@ -14726,7 +15428,7 @@ function normalizeWorkflowWorkerConfig(options) {
|
|
|
14726
15428
|
function positiveInteger(value, fallback) {
|
|
14727
15429
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
|
|
14728
15430
|
}
|
|
14729
|
-
function
|
|
15431
|
+
function nonNegativeInteger2(value, fallback) {
|
|
14730
15432
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(0, Math.trunc(value));
|
|
14731
15433
|
}
|
|
14732
15434
|
function nonNegativeDuration(value, fallback) {
|
|
@@ -16142,6 +16844,7 @@ var Workflow = class {
|
|
|
16142
16844
|
}
|
|
16143
16845
|
return await this.client.installPolicy(this.type, {
|
|
16144
16846
|
...options,
|
|
16847
|
+
replace: Object.hasOwn(options, "replace") ? options.replace ?? true : true,
|
|
16145
16848
|
states
|
|
16146
16849
|
});
|
|
16147
16850
|
}
|
|
@@ -16352,16 +17055,23 @@ var WorkflowWorker = class {
|
|
|
16352
17055
|
);
|
|
16353
17056
|
}
|
|
16354
17057
|
};
|
|
17058
|
+
|
|
17059
|
+
// src/version.ts
|
|
17060
|
+
var FERRICSTORE_SDK_VERSION = "0.3.0";
|
|
17061
|
+
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.9.1";
|
|
17062
|
+
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
16355
17063
|
// Annotate the CommonJS export names for ESM import in node:
|
|
16356
17064
|
0 && (module.exports = {
|
|
16357
17065
|
BitmapStore,
|
|
16358
17066
|
BloomFilterStore,
|
|
16359
17067
|
COMMAND_OPCODES,
|
|
16360
|
-
COMPACT_RESPONSE_OPCODES,
|
|
16361
17068
|
ClaimHydrationError,
|
|
16362
17069
|
ConnectionClosedError,
|
|
16363
17070
|
CountMinSketchStore,
|
|
16364
17071
|
CuckooFilterStore,
|
|
17072
|
+
FERRICSTORE_MINIMUM_SERVER_VERSION,
|
|
17073
|
+
FERRICSTORE_NATIVE_PROTOCOL_VERSION,
|
|
17074
|
+
FERRICSTORE_SDK_VERSION,
|
|
16365
17075
|
FerricStoreClient,
|
|
16366
17076
|
FerricStoreError,
|
|
16367
17077
|
FlowAlreadyExistsError,
|
|
@@ -16378,6 +17088,7 @@ var WorkflowWorker = class {
|
|
|
16378
17088
|
ListStore,
|
|
16379
17089
|
LockHeldError,
|
|
16380
17090
|
LockNotOwnedError,
|
|
17091
|
+
MAX_FLOW_POLICY_GENERATION,
|
|
16381
17092
|
NativeAdapter,
|
|
16382
17093
|
OverloadedError,
|
|
16383
17094
|
Queue,
|
|
@@ -16392,6 +17103,7 @@ var WorkflowWorker = class {
|
|
|
16392
17103
|
SetStore,
|
|
16393
17104
|
SortedSetStore,
|
|
16394
17105
|
StaleLeaseError,
|
|
17106
|
+
StalePolicyGenerationError,
|
|
16395
17107
|
StreamStore,
|
|
16396
17108
|
TDigestStore,
|
|
16397
17109
|
TopKStore,
|