@ferricstore/ferricstore 0.1.7 → 0.2.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 +17 -5
- package/dist/index.cjs +869 -548
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -30
- package/dist/index.d.ts +29 -30
- package/dist/index.js +856 -537
- 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 +5 -2
- 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/RequestTimeoutError.html +6 -3
- package/docs/api/classes/RerouteError.html +6 -3
- package/docs/api/classes/StaleLeaseError.html +6 -3
- package/docs/api/classes/TDigestStore.html +2 -2
- package/docs/api/classes/TopKStore.html +1 -1
- package/docs/api/classes/TopologyNativeAdapterPool.html +1 -1
- package/docs/api/classes/Workflow.html +1 -1
- package/docs/api/functions/classifyServerError.html +1 -1
- package/docs/api/functions/mapException.html +1 -1
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +16 -6
- 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/FlowPolicyOptions.html +3 -3
- 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/FetchOrComputeFencedResult.html +1 -0
- package/docs/api/types/FetchOrComputeResult.html +1 -1
- 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/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.js
CHANGED
|
@@ -16,10 +16,16 @@ import "buffer";
|
|
|
16
16
|
var FerricStoreError = class extends Error {
|
|
17
17
|
code = "ferricstore_error";
|
|
18
18
|
raw;
|
|
19
|
+
retryable;
|
|
20
|
+
safeToRetry;
|
|
21
|
+
retryAfterMs;
|
|
19
22
|
constructor(message, options = {}) {
|
|
20
23
|
super(message, { cause: options.cause });
|
|
21
24
|
this.name = new.target.name;
|
|
22
25
|
this.raw = options.raw;
|
|
26
|
+
this.retryable = options.retryable ?? structuredBooleanField(options.raw, "retryable");
|
|
27
|
+
this.safeToRetry = options.safeToRetry ?? structuredBooleanField(options.raw, "safe_to_retry");
|
|
28
|
+
this.retryAfterMs = options.retryAfterMs ?? structuredIntegerField(options.raw, "retry_after_ms");
|
|
23
29
|
}
|
|
24
30
|
};
|
|
25
31
|
var ConnectionClosedError = class extends FerricStoreError {
|
|
@@ -66,11 +72,14 @@ var InvalidCommandError = class extends FerricStoreError {
|
|
|
66
72
|
};
|
|
67
73
|
var OverloadedError = class extends FerricStoreError {
|
|
68
74
|
code = "overloaded";
|
|
69
|
-
retryAfterMs;
|
|
70
75
|
reason;
|
|
71
76
|
constructor(message, options = {}) {
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
const local = options.raw == null;
|
|
78
|
+
super(message, {
|
|
79
|
+
...options,
|
|
80
|
+
retryable: options.retryable ?? (local ? true : void 0),
|
|
81
|
+
safeToRetry: options.safeToRetry ?? (local ? true : void 0)
|
|
82
|
+
});
|
|
74
83
|
this.reason = options.reason;
|
|
75
84
|
}
|
|
76
85
|
};
|
|
@@ -88,15 +97,21 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
88
97
|
const lower = message.toLowerCase();
|
|
89
98
|
const structuredCode = structuredStringField(raw, "code");
|
|
90
99
|
const code = structuredCode?.toLowerCase();
|
|
100
|
+
const retry2 = {
|
|
101
|
+
retryable: structuredBooleanField(raw, "retryable"),
|
|
102
|
+
safeToRetry: structuredBooleanField(raw, "safe_to_retry"),
|
|
103
|
+
retryAfterMs: structuredIntegerField(raw, "retry_after_ms") ?? intField(lower, "retry_after_ms")
|
|
104
|
+
};
|
|
91
105
|
if (isRerouteStatus(status) || code === "reroute") {
|
|
92
|
-
return new RerouteError(message, { cause, raw });
|
|
106
|
+
return new RerouteError(message, { cause, raw, ...definedRetryMetadata(retry2) });
|
|
93
107
|
}
|
|
94
108
|
if (isBusyStatus(status) || isOverloadCode(structuredCode) || overloadMessage(lower)) {
|
|
95
109
|
return new OverloadedError(message, {
|
|
96
110
|
cause,
|
|
97
111
|
raw,
|
|
112
|
+
...definedRetryMetadata(retry2),
|
|
98
113
|
reason: structuredStringField(raw, "reason") ?? structuredCode ?? stringField(lower, "reason"),
|
|
99
|
-
retryAfterMs:
|
|
114
|
+
retryAfterMs: retry2.retryAfterMs
|
|
100
115
|
});
|
|
101
116
|
}
|
|
102
117
|
if (code === "flow_already_exists" || lower.includes("flow") && lower.includes("already exists")) {
|
|
@@ -120,7 +135,7 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
120
135
|
if (code === "invalid_command" || lower.includes("wrong number of arguments") || lower.includes("syntax error")) {
|
|
121
136
|
return new InvalidCommandError(message, { cause, raw });
|
|
122
137
|
}
|
|
123
|
-
return new FerricStoreError(message, { cause, raw });
|
|
138
|
+
return new FerricStoreError(message, { cause, raw, ...definedRetryMetadata(retry2) });
|
|
124
139
|
}
|
|
125
140
|
function mapException(error) {
|
|
126
141
|
if (error instanceof FerricStoreError) {
|
|
@@ -160,8 +175,23 @@ function structuredIntegerField(raw, name) {
|
|
|
160
175
|
if (typeof value === "bigint") {
|
|
161
176
|
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
162
177
|
}
|
|
163
|
-
const
|
|
164
|
-
return
|
|
178
|
+
const text3 = binaryText(value);
|
|
179
|
+
return text3 == null ? void 0 : nonNegativeSafeIntegerText(text3);
|
|
180
|
+
}
|
|
181
|
+
function structuredBooleanField(raw, name) {
|
|
182
|
+
const value = structuredField(raw, name);
|
|
183
|
+
if (typeof value === "boolean") return value;
|
|
184
|
+
const text3 = binaryText(value)?.toLowerCase();
|
|
185
|
+
if (text3 === "true" || text3 === "1") return true;
|
|
186
|
+
if (text3 === "false" || text3 === "0") return false;
|
|
187
|
+
return void 0;
|
|
188
|
+
}
|
|
189
|
+
function definedRetryMetadata(metadata) {
|
|
190
|
+
return {
|
|
191
|
+
...metadata.retryable == null ? {} : { retryable: metadata.retryable },
|
|
192
|
+
...metadata.safeToRetry == null ? {} : { safeToRetry: metadata.safeToRetry },
|
|
193
|
+
...metadata.retryAfterMs == null ? {} : { retryAfterMs: metadata.retryAfterMs }
|
|
194
|
+
};
|
|
165
195
|
}
|
|
166
196
|
function nonNegativeSafeIntegerText(value) {
|
|
167
197
|
if (!/^[0-9]+$/u.test(value)) return void 0;
|
|
@@ -334,9 +364,6 @@ function mapDenseResponseArray(value, transform) {
|
|
|
334
364
|
return result;
|
|
335
365
|
}
|
|
336
366
|
|
|
337
|
-
// src/auto-partition.ts
|
|
338
|
-
import { Buffer as Buffer3 } from "buffer";
|
|
339
|
-
|
|
340
367
|
// src/crc32.ts
|
|
341
368
|
import "buffer";
|
|
342
369
|
var table = new Uint32Array(256);
|
|
@@ -354,12 +381,49 @@ function crc32(buffer) {
|
|
|
354
381
|
}
|
|
355
382
|
return (value ^ 4294967295) >>> 0;
|
|
356
383
|
}
|
|
384
|
+
function crc32Utf8(text3, start = 0, end = text3.length) {
|
|
385
|
+
let value = 4294967295;
|
|
386
|
+
for (let index = start; index < end; index += 1) {
|
|
387
|
+
const first = text3.charCodeAt(index);
|
|
388
|
+
let point = first;
|
|
389
|
+
if (first >= 55296 && first <= 56319) {
|
|
390
|
+
const second = index + 1 < end ? text3.charCodeAt(index + 1) : 0;
|
|
391
|
+
if (second >= 56320 && second <= 57343) {
|
|
392
|
+
point = 65536 + (first - 55296 << 10) + second - 56320;
|
|
393
|
+
index += 1;
|
|
394
|
+
} else {
|
|
395
|
+
point = 65533;
|
|
396
|
+
}
|
|
397
|
+
} else if (first >= 56320 && first <= 57343) {
|
|
398
|
+
point = 65533;
|
|
399
|
+
}
|
|
400
|
+
if (point < 128) {
|
|
401
|
+
value = updateCrc32(value, point);
|
|
402
|
+
} else if (point < 2048) {
|
|
403
|
+
value = updateCrc32(value, 192 | point >>> 6);
|
|
404
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
405
|
+
} else if (point < 65536) {
|
|
406
|
+
value = updateCrc32(value, 224 | point >>> 12);
|
|
407
|
+
value = updateCrc32(value, 128 | point >>> 6 & 63);
|
|
408
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
409
|
+
} else {
|
|
410
|
+
value = updateCrc32(value, 240 | point >>> 18);
|
|
411
|
+
value = updateCrc32(value, 128 | point >>> 12 & 63);
|
|
412
|
+
value = updateCrc32(value, 128 | point >>> 6 & 63);
|
|
413
|
+
value = updateCrc32(value, 128 | point & 63);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
return (value ^ 4294967295) >>> 0;
|
|
417
|
+
}
|
|
418
|
+
function updateCrc32(value, byte) {
|
|
419
|
+
return value >>> 8 ^ (table[(value ^ byte) & 255] ?? 0);
|
|
420
|
+
}
|
|
357
421
|
|
|
358
422
|
// src/auto-partition.ts
|
|
359
423
|
var AUTO_PARTITION_PREFIX = "__flow_auto__:";
|
|
360
424
|
var AUTO_PARTITION_BUCKETS = 256;
|
|
361
425
|
function autoPartitionKeyForId(id) {
|
|
362
|
-
return `${AUTO_PARTITION_PREFIX}${
|
|
426
|
+
return `${AUTO_PARTITION_PREFIX}${crc32Utf8(id) % AUTO_PARTITION_BUCKETS}`;
|
|
363
427
|
}
|
|
364
428
|
|
|
365
429
|
// src/flow-argument-helpers.ts
|
|
@@ -752,7 +816,7 @@ function coerceDiagnosticValue(value) {
|
|
|
752
816
|
// src/native-connection.ts
|
|
753
817
|
import net from "net";
|
|
754
818
|
import tls from "tls";
|
|
755
|
-
import { Buffer as
|
|
819
|
+
import { Buffer as Buffer3 } from "buffer";
|
|
756
820
|
function parseFerricUrl(value) {
|
|
757
821
|
const url = new URL(value);
|
|
758
822
|
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
@@ -878,7 +942,7 @@ function nonNegativeSafeInteger(value) {
|
|
|
878
942
|
if (typeof value === "bigint") {
|
|
879
943
|
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
880
944
|
}
|
|
881
|
-
const source =
|
|
945
|
+
const source = Buffer3.isBuffer(value) || value instanceof Uint8Array ? Buffer3.from(value).toString("utf8") : value;
|
|
882
946
|
if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
|
|
883
947
|
return void 0;
|
|
884
948
|
}
|
|
@@ -1112,10 +1176,10 @@ var NativeHeartbeat = class {
|
|
|
1112
1176
|
};
|
|
1113
1177
|
|
|
1114
1178
|
// src/protocol.ts
|
|
1115
|
-
import { Buffer as
|
|
1179
|
+
import { Buffer as Buffer22 } from "buffer";
|
|
1116
1180
|
|
|
1117
1181
|
// src/command-grammar.ts
|
|
1118
|
-
import { Buffer as
|
|
1182
|
+
import { Buffer as Buffer4 } from "buffer";
|
|
1119
1183
|
|
|
1120
1184
|
// src/command-metadata-flow.ts
|
|
1121
1185
|
var flowStateIdCommands = /* @__PURE__ */ new Set([
|
|
@@ -1562,8 +1626,8 @@ var secondKeySubcommands = /* @__PURE__ */ new Map([
|
|
|
1562
1626
|
]);
|
|
1563
1627
|
function commandToken(value) {
|
|
1564
1628
|
if (typeof value === "string") return value.toUpperCase();
|
|
1565
|
-
if (
|
|
1566
|
-
return
|
|
1629
|
+
if (Buffer4.isBuffer(value) || value instanceof Uint8Array) {
|
|
1630
|
+
return Buffer4.from(value).toString("utf8").toUpperCase();
|
|
1567
1631
|
}
|
|
1568
1632
|
return void 0;
|
|
1569
1633
|
}
|
|
@@ -1666,7 +1730,7 @@ function safeIntegerArgument(value) {
|
|
|
1666
1730
|
if (typeof value === "bigint") {
|
|
1667
1731
|
return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
1668
1732
|
}
|
|
1669
|
-
const source = typeof value === "string" ? value :
|
|
1733
|
+
const source = typeof value === "string" ? value : Buffer4.isBuffer(value) || value instanceof Uint8Array ? Buffer4.from(value).toString("utf8") : void 0;
|
|
1670
1734
|
if (source == null || !/^[+-]?\d+$/u.test(source)) return void 0;
|
|
1671
1735
|
const parsed = BigInt(source);
|
|
1672
1736
|
return parsed >= BigInt(Number.MIN_SAFE_INTEGER) && parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : void 0;
|
|
@@ -1719,7 +1783,7 @@ function hasOwnCommandArgument(args, index, end, section) {
|
|
|
1719
1783
|
}
|
|
1720
1784
|
|
|
1721
1785
|
// src/protocol-core.ts
|
|
1722
|
-
import { Buffer as
|
|
1786
|
+
import { Buffer as Buffer8 } from "buffer";
|
|
1723
1787
|
|
|
1724
1788
|
// src/protocol-constants.ts
|
|
1725
1789
|
import "buffer";
|
|
@@ -1927,6 +1991,7 @@ var OPCODES = {
|
|
|
1927
1991
|
flowFail: COMMAND_OPCODES["FLOW.FAIL"],
|
|
1928
1992
|
flowValuePut: COMMAND_OPCODES["FLOW.VALUE.PUT"],
|
|
1929
1993
|
flowValueMGet: COMMAND_OPCODES["FLOW.VALUE.MGET"],
|
|
1994
|
+
flowSignal: COMMAND_OPCODES["FLOW.SIGNAL"],
|
|
1930
1995
|
flowCreateMany: COMMAND_OPCODES["FLOW.CREATE_MANY"],
|
|
1931
1996
|
flowCompleteMany: COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
|
|
1932
1997
|
flowTransitionMany: COMMAND_OPCODES["FLOW.TRANSITION_MANY"],
|
|
@@ -1939,68 +2004,15 @@ var OPCODES = {
|
|
|
1939
2004
|
flowRunStepsMany: COMMAND_OPCODES["FLOW.RUN_STEPS_MANY"],
|
|
1940
2005
|
flowSearch: COMMAND_OPCODES["FLOW.SEARCH"]
|
|
1941
2006
|
};
|
|
1942
|
-
var COMPACT_RESPONSE_OPCODES = {
|
|
1943
|
-
flow_claim_jobs_v1: [COMMAND_OPCODES["FLOW.CLAIM_DUE"]],
|
|
1944
|
-
flow_record_list_v1: [
|
|
1945
|
-
COMMAND_OPCODES["FLOW.LIST"],
|
|
1946
|
-
COMMAND_OPCODES["FLOW.TERMINALS"],
|
|
1947
|
-
COMMAND_OPCODES["FLOW.FAILURES"],
|
|
1948
|
-
COMMAND_OPCODES["FLOW.BY_PARENT"],
|
|
1949
|
-
COMMAND_OPCODES["FLOW.BY_ROOT"],
|
|
1950
|
-
COMMAND_OPCODES["FLOW.BY_CORRELATION"],
|
|
1951
|
-
COMMAND_OPCODES["FLOW.STUCK"]
|
|
1952
|
-
],
|
|
1953
|
-
flow_record_v1: [COMMAND_OPCODES["FLOW.GET"]],
|
|
1954
|
-
kv_get_v1: [COMMAND_OPCODES.GET],
|
|
1955
|
-
kv_mget_v1: [COMMAND_OPCODES.MGET, COMMAND_OPCODES["FLOW.VALUE.MGET"]],
|
|
1956
|
-
ok_list_v1: [
|
|
1957
|
-
COMMAND_OPCODES.SET,
|
|
1958
|
-
COMMAND_OPCODES.MSET,
|
|
1959
|
-
COMMAND_OPCODES["FLOW.CREATE_MANY"],
|
|
1960
|
-
COMMAND_OPCODES["FLOW.COMPLETE_MANY"],
|
|
1961
|
-
COMMAND_OPCODES["FLOW.RETRY_MANY"],
|
|
1962
|
-
COMMAND_OPCODES["FLOW.FAIL_MANY"],
|
|
1963
|
-
COMMAND_OPCODES["FLOW.CANCEL_MANY"]
|
|
1964
|
-
],
|
|
1965
|
-
pipeline_v1: [COMMAND_OPCODES.PIPELINE]
|
|
1966
|
-
};
|
|
1967
|
-
var COMPACT_KIND_FLOW_CLAIM_JOBS = 1 << 0;
|
|
1968
|
-
var COMPACT_KIND_FLOW_RECORD = 1 << 1;
|
|
1969
|
-
var COMPACT_KIND_FLOW_RECORD_LIST = 1 << 2;
|
|
1970
|
-
var COMPACT_KIND_KV_GET = 1 << 3;
|
|
1971
|
-
var COMPACT_KIND_KV_MGET = 1 << 4;
|
|
1972
|
-
var COMPACT_KIND_OK_LIST = 1 << 5;
|
|
1973
|
-
var COMPACT_KIND_PIPELINE = 1 << 6;
|
|
1974
|
-
var compactResponseOpcodeKinds = new Uint8Array(
|
|
1975
|
-
Math.max(...Object.values(COMPACT_RESPONSE_OPCODES).flat()) + 1
|
|
1976
|
-
);
|
|
1977
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_CLAIM_JOBS, COMPACT_RESPONSE_OPCODES.flow_claim_jobs_v1);
|
|
1978
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD, COMPACT_RESPONSE_OPCODES.flow_record_v1);
|
|
1979
|
-
registerCompactResponseOpcodes(COMPACT_KIND_FLOW_RECORD_LIST, COMPACT_RESPONSE_OPCODES.flow_record_list_v1);
|
|
1980
|
-
registerCompactResponseOpcodes(COMPACT_KIND_KV_GET, COMPACT_RESPONSE_OPCODES.kv_get_v1);
|
|
1981
|
-
registerCompactResponseOpcodes(COMPACT_KIND_KV_MGET, [
|
|
1982
|
-
...COMPACT_RESPONSE_OPCODES.kv_mget_v1,
|
|
1983
|
-
COMMAND_OPCODES.PIPELINE
|
|
1984
|
-
]);
|
|
1985
|
-
registerCompactResponseOpcodes(COMPACT_KIND_OK_LIST, [
|
|
1986
|
-
...COMPACT_RESPONSE_OPCODES.ok_list_v1,
|
|
1987
|
-
COMMAND_OPCODES.PIPELINE
|
|
1988
|
-
]);
|
|
1989
|
-
registerCompactResponseOpcodes(COMPACT_KIND_PIPELINE, COMPACT_RESPONSE_OPCODES.pipeline_v1);
|
|
1990
|
-
function registerCompactResponseOpcodes(kind, opcodes) {
|
|
1991
|
-
for (const opcode of opcodes) {
|
|
1992
|
-
compactResponseOpcodeKinds[opcode] = (compactResponseOpcodeKinds[opcode] ?? 0) | kind;
|
|
1993
|
-
}
|
|
1994
|
-
}
|
|
1995
|
-
function compactResponseOpcodeSupports(opcode, kind) {
|
|
1996
|
-
return ((compactResponseOpcodeKinds[opcode] ?? 0) & kind) !== 0;
|
|
1997
|
-
}
|
|
1998
2007
|
var COMPACT_FLOW_CLAIM_JOBS = 128;
|
|
1999
2008
|
var COMPACT_OK_LIST = 129;
|
|
2000
2009
|
var COMPACT_KV_GET = 130;
|
|
2001
2010
|
var COMPACT_KV_MGET = 131;
|
|
2002
2011
|
var COMPACT_FLOW_RECORD = 132;
|
|
2003
2012
|
var COMPACT_FLOW_RECORD_LIST = 133;
|
|
2013
|
+
var COMPACT_BINARY_LIST_LIST = 134;
|
|
2014
|
+
var COMPACT_BINARY_MAP_LIST = 135;
|
|
2015
|
+
var COMPACT_INTEGER_LIST = 136;
|
|
2004
2016
|
var COMPACT_KV_MGET_FIXED = 137;
|
|
2005
2017
|
var COMPACT_FLOW_CREATE_MANY_REQUEST = 144;
|
|
2006
2018
|
var COMPACT_FLOW_CLAIM_DUE_REQUEST = 145;
|
|
@@ -2070,16 +2082,16 @@ var FLOW_RECORD_FIELD_KEYS = [
|
|
|
2070
2082
|
];
|
|
2071
2083
|
|
|
2072
2084
|
// src/protocol-text.ts
|
|
2073
|
-
import { Buffer as
|
|
2085
|
+
import { Buffer as Buffer6 } from "buffer";
|
|
2074
2086
|
function toBuffer(value) {
|
|
2075
|
-
if (
|
|
2076
|
-
if (value instanceof Uint8Array) return
|
|
2077
|
-
if (typeof value === "string") return
|
|
2087
|
+
if (Buffer6.isBuffer(value)) return value;
|
|
2088
|
+
if (value instanceof Uint8Array) return Buffer6.from(value);
|
|
2089
|
+
if (typeof value === "string") return Buffer6.from(value);
|
|
2078
2090
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2079
|
-
return
|
|
2091
|
+
return Buffer6.from(String(value));
|
|
2080
2092
|
}
|
|
2081
|
-
if (typeof value === "symbol") return
|
|
2082
|
-
if (value == null) return
|
|
2093
|
+
if (typeof value === "symbol") return Buffer6.from(value.description ?? value.toString());
|
|
2094
|
+
if (value == null) return Buffer6.alloc(0);
|
|
2083
2095
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2084
2096
|
}
|
|
2085
2097
|
function asText(value) {
|
|
@@ -2087,14 +2099,14 @@ function asText(value) {
|
|
|
2087
2099
|
}
|
|
2088
2100
|
function optionalText(value) {
|
|
2089
2101
|
if (value == null || value === "") return void 0;
|
|
2090
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ||
|
|
2102
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || Buffer6.isBuffer(value) || value instanceof Uint8Array) {
|
|
2091
2103
|
return asText(value);
|
|
2092
2104
|
}
|
|
2093
2105
|
return void 0;
|
|
2094
2106
|
}
|
|
2095
2107
|
function commandTokenIs(value, expected) {
|
|
2096
2108
|
if (typeof value === "string") return value.toUpperCase() === expected;
|
|
2097
|
-
if (
|
|
2109
|
+
if (Buffer6.isBuffer(value) || value instanceof Uint8Array) {
|
|
2098
2110
|
return asText(value).toUpperCase() === expected;
|
|
2099
2111
|
}
|
|
2100
2112
|
return false;
|
|
@@ -2108,7 +2120,7 @@ function commandNameIs(value, expected) {
|
|
|
2108
2120
|
}
|
|
2109
2121
|
|
|
2110
2122
|
// src/request-context.ts
|
|
2111
|
-
import { Buffer as
|
|
2123
|
+
import { Buffer as Buffer7 } from "buffer";
|
|
2112
2124
|
var requestContextCommands = /* @__PURE__ */ new Set([
|
|
2113
2125
|
"INVOCATION.CREATE",
|
|
2114
2126
|
"INVOCATION.DEFINITION.GET",
|
|
@@ -2163,9 +2175,9 @@ function requestContextCommandToken(value) {
|
|
|
2163
2175
|
const upper = value.toUpperCase();
|
|
2164
2176
|
return isRequestContextCommand(upper) ? upper : void 0;
|
|
2165
2177
|
}
|
|
2166
|
-
if (
|
|
2178
|
+
if (Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2167
2179
|
if (value[0] !== 73 && value[0] !== 105) return void 0;
|
|
2168
|
-
const command =
|
|
2180
|
+
const command = Buffer7.from(value).toString("utf8").toUpperCase();
|
|
2169
2181
|
return isRequestContextCommand(command) ? command : void 0;
|
|
2170
2182
|
}
|
|
2171
2183
|
return void 0;
|
|
@@ -2196,12 +2208,12 @@ function requestContextText(context, fieldName) {
|
|
|
2196
2208
|
return value;
|
|
2197
2209
|
}
|
|
2198
2210
|
function isPlainObject(value) {
|
|
2199
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2211
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer7.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2200
2212
|
}
|
|
2201
2213
|
function commandToken2(value) {
|
|
2202
2214
|
if (typeof value === "string") return value.toUpperCase();
|
|
2203
|
-
if (
|
|
2204
|
-
return
|
|
2215
|
+
if (Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2216
|
+
return Buffer7.from(value).toString("utf8").toUpperCase();
|
|
2205
2217
|
}
|
|
2206
2218
|
return "";
|
|
2207
2219
|
}
|
|
@@ -2291,17 +2303,17 @@ function requestFrameTooLarge(maxBytes) {
|
|
|
2291
2303
|
);
|
|
2292
2304
|
}
|
|
2293
2305
|
function binaryValueByteLength(value) {
|
|
2294
|
-
if (
|
|
2295
|
-
if (typeof value === "string") return
|
|
2306
|
+
if (Buffer8.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
|
|
2307
|
+
if (typeof value === "string") return Buffer8.byteLength(value);
|
|
2296
2308
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2297
|
-
return
|
|
2309
|
+
return Buffer8.byteLength(String(value));
|
|
2298
2310
|
}
|
|
2299
|
-
if (typeof value === "symbol") return
|
|
2311
|
+
if (typeof value === "symbol") return Buffer8.byteLength(value.description ?? value.toString());
|
|
2300
2312
|
if (value == null) return 0;
|
|
2301
2313
|
return toBuffer(value).byteLength;
|
|
2302
2314
|
}
|
|
2303
2315
|
function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
2304
|
-
if (
|
|
2316
|
+
if (Buffer8.isBuffer(value)) {
|
|
2305
2317
|
value.copy(output, offset);
|
|
2306
2318
|
return;
|
|
2307
2319
|
}
|
|
@@ -2310,17 +2322,17 @@ function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
|
2310
2322
|
return;
|
|
2311
2323
|
}
|
|
2312
2324
|
if (value == null) return;
|
|
2313
|
-
let
|
|
2325
|
+
let text3;
|
|
2314
2326
|
if (typeof value === "string") {
|
|
2315
|
-
|
|
2327
|
+
text3 = value;
|
|
2316
2328
|
} else if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2317
|
-
|
|
2329
|
+
text3 = String(value);
|
|
2318
2330
|
} else if (typeof value === "symbol") {
|
|
2319
|
-
|
|
2331
|
+
text3 = value.description ?? value.toString();
|
|
2320
2332
|
} else {
|
|
2321
2333
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2322
2334
|
}
|
|
2323
|
-
output.write(
|
|
2335
|
+
output.write(text3, offset, knownByteLength ?? Buffer8.byteLength(text3), "utf8");
|
|
2324
2336
|
}
|
|
2325
2337
|
function compactBinaryEncodedLength(value) {
|
|
2326
2338
|
return 4 + compactBinaryByteLength(value);
|
|
@@ -2333,10 +2345,10 @@ function compactBinaryByteLength(value) {
|
|
|
2333
2345
|
return byteLength;
|
|
2334
2346
|
}
|
|
2335
2347
|
function isCompactBinaryArgument(value) {
|
|
2336
|
-
return typeof value === "string" ||
|
|
2348
|
+
return typeof value === "string" || Buffer8.isBuffer(value) || value instanceof Uint8Array;
|
|
2337
2349
|
}
|
|
2338
2350
|
function isCompactBinaryScalar(value) {
|
|
2339
|
-
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" ||
|
|
2351
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || Buffer8.isBuffer(value) || value instanceof Uint8Array;
|
|
2340
2352
|
}
|
|
2341
2353
|
function compactOptionalBinaryEncodedLength(value) {
|
|
2342
2354
|
return value == null ? 4 : compactBinaryEncodedLength(value);
|
|
@@ -2419,13 +2431,13 @@ function i64Arg(value) {
|
|
|
2419
2431
|
}
|
|
2420
2432
|
function boolArg(value) {
|
|
2421
2433
|
if (typeof value === "boolean") return value;
|
|
2422
|
-
const
|
|
2423
|
-
return
|
|
2434
|
+
const text3 = asText(value).toUpperCase();
|
|
2435
|
+
return text3 === "1" || text3 === "TRUE" || text3 === "YES" || text3 === "ON";
|
|
2424
2436
|
}
|
|
2425
2437
|
function isBoolToken(value) {
|
|
2426
2438
|
if (typeof value === "boolean") return true;
|
|
2427
|
-
const
|
|
2428
|
-
return
|
|
2439
|
+
const text3 = asText(value).toUpperCase();
|
|
2440
|
+
return text3 === "1" || text3 === "0" || text3 === "TRUE" || text3 === "FALSE" || text3 === "YES" || text3 === "NO" || text3 === "ON" || text3 === "OFF";
|
|
2429
2441
|
}
|
|
2430
2442
|
function independentMode(value) {
|
|
2431
2443
|
if (value === true) return 2;
|
|
@@ -2467,7 +2479,23 @@ function setOwnValue2(target, key, value) {
|
|
|
2467
2479
|
}
|
|
2468
2480
|
|
|
2469
2481
|
// src/protocol-flow-options.ts
|
|
2470
|
-
import { Buffer as
|
|
2482
|
+
import { Buffer as Buffer9 } from "buffer";
|
|
2483
|
+
|
|
2484
|
+
// src/protocol-flow-option-value.ts
|
|
2485
|
+
function setFlowOptionValue(payload, field2, value, repeat) {
|
|
2486
|
+
if (!repeat || !Object.hasOwn(payload, field2)) {
|
|
2487
|
+
setOwnValue2(payload, field2, value);
|
|
2488
|
+
return;
|
|
2489
|
+
}
|
|
2490
|
+
const previous = payload[field2];
|
|
2491
|
+
setOwnValue2(
|
|
2492
|
+
payload,
|
|
2493
|
+
field2,
|
|
2494
|
+
Array.isArray(previous) ? [...previous, value] : [previous, value]
|
|
2495
|
+
);
|
|
2496
|
+
}
|
|
2497
|
+
|
|
2498
|
+
// src/protocol-flow-options.ts
|
|
2471
2499
|
var OPTION_FIELDS = {
|
|
2472
2500
|
CONSISTENT_PROJECTION: "consistent_projection",
|
|
2473
2501
|
COUNT: "count",
|
|
@@ -2542,7 +2570,7 @@ function normalizeFlowSearchStateMeta(payload) {
|
|
|
2542
2570
|
payload.state_meta = { [asText(state)]: stateMeta };
|
|
2543
2571
|
}
|
|
2544
2572
|
function isPlainObject2(value) {
|
|
2545
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2573
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer9.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2546
2574
|
}
|
|
2547
2575
|
function parseFlowOptions(args, start, end, config) {
|
|
2548
2576
|
const payload = {};
|
|
@@ -2636,8 +2664,9 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2636
2664
|
case "TRANSITION_TO":
|
|
2637
2665
|
case "TO_EVENT":
|
|
2638
2666
|
case "EXPECT_STATE": {
|
|
2639
|
-
const field2 = token.toLowerCase();
|
|
2640
|
-
if (!
|
|
2667
|
+
const field2 = token === "IDEMPOTENCY" ? "idempotency_key" : token.toLowerCase();
|
|
2668
|
+
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2669
|
+
setFlowOptionValue(payload, field2, args[index + 1], token === "IF_STATE");
|
|
2641
2670
|
index += 2;
|
|
2642
2671
|
break;
|
|
2643
2672
|
}
|
|
@@ -2927,6 +2956,7 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
2927
2956
|
LEASE_MS: "lease_ms",
|
|
2928
2957
|
LEASE_TOKEN: "lease_token",
|
|
2929
2958
|
LIMIT: "limit",
|
|
2959
|
+
MAX_ACTIVE_MS: "max_active_ms",
|
|
2930
2960
|
MAX_FIRES: "max_fires",
|
|
2931
2961
|
MAXBYTES: "payload_max_bytes",
|
|
2932
2962
|
NOW: "now_ms",
|
|
@@ -2936,7 +2966,6 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
2936
2966
|
OVERLAP_RETRY_MS: "overlap_retry_ms",
|
|
2937
2967
|
OVERWRITE: "overwrite",
|
|
2938
2968
|
PARENT_FLOW_ID: "parent_flow_id",
|
|
2939
|
-
PARENT_ID: "parent_id",
|
|
2940
2969
|
PARTITION: "partition_key",
|
|
2941
2970
|
PAYLOAD: "payload",
|
|
2942
2971
|
PAYLOAD_MAX_BYTES: "payload_max_bytes",
|
|
@@ -2951,7 +2980,6 @@ var FLOW_ADMIN_FIELDS = {
|
|
|
2951
2980
|
REV: "rev",
|
|
2952
2981
|
RETURN: "return",
|
|
2953
2982
|
ROOT_FLOW_ID: "root_flow_id",
|
|
2954
|
-
ROOT_ID: "root_id",
|
|
2955
2983
|
SCOPE: "scope",
|
|
2956
2984
|
SHARD_ID: "shard_id",
|
|
2957
2985
|
START_AT_MS: "start_at_ms",
|
|
@@ -3088,7 +3116,7 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3088
3116
|
}
|
|
3089
3117
|
|
|
3090
3118
|
// src/protocol-flow-compact.ts
|
|
3091
|
-
import { Buffer as
|
|
3119
|
+
import { Buffer as Buffer11 } from "buffer";
|
|
3092
3120
|
|
|
3093
3121
|
// src/protocol-flow-compact-common.ts
|
|
3094
3122
|
function compactManyRequestTag(value, regularTag, okOnSuccessTag) {
|
|
@@ -3197,7 +3225,7 @@ function parseNamedCountMap(values, start) {
|
|
|
3197
3225
|
}
|
|
3198
3226
|
|
|
3199
3227
|
// src/protocol-flow-compact-transition.ts
|
|
3200
|
-
import { Buffer as
|
|
3228
|
+
import { Buffer as Buffer10 } from "buffer";
|
|
3201
3229
|
function compactFlowTransitionManyPayload(partition, fromState, toState, rawItems, mixed, options, maxBodyBytes) {
|
|
3202
3230
|
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) {
|
|
3203
3231
|
return void 0;
|
|
@@ -3249,7 +3277,7 @@ function compactFlowTransitionManyPayload(partition, fromState, toState, rawItem
|
|
|
3249
3277
|
total += 4 + idLength + 4 + itemPartitionLength + 8 + 4 + leaseLength;
|
|
3250
3278
|
}
|
|
3251
3279
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3252
|
-
const out =
|
|
3280
|
+
const out = Buffer10.allocUnsafe(total);
|
|
3253
3281
|
let offset = 0;
|
|
3254
3282
|
out.writeUInt8(tag, offset);
|
|
3255
3283
|
offset += 1;
|
|
@@ -3307,7 +3335,7 @@ function compactFlowCreateManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3307
3335
|
}
|
|
3308
3336
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3309
3337
|
const tag = mixed ? COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST : auto ? COMPACT_FLOW_CREATE_MANY_REQUEST : COMPACT_FLOW_CREATE_MANY_PARTITION_REQUEST;
|
|
3310
|
-
const out =
|
|
3338
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3311
3339
|
let offset = 0;
|
|
3312
3340
|
out.writeUInt8(tag, offset++);
|
|
3313
3341
|
offset = writeBinary(out, offset, toBuffer(options.type));
|
|
@@ -3352,7 +3380,7 @@ function compactFlowClaimDuePayload(type, options, maxBodyBytes) {
|
|
|
3352
3380
|
total += 1;
|
|
3353
3381
|
}
|
|
3354
3382
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3355
|
-
const out =
|
|
3383
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3356
3384
|
let offset = 0;
|
|
3357
3385
|
out.writeUInt8(COMPACT_FLOW_CLAIM_DUE_REQUEST, offset++);
|
|
3358
3386
|
offset = writeBinary(out, offset, toBuffer(type));
|
|
@@ -3406,7 +3434,7 @@ function compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto
|
|
|
3406
3434
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3407
3435
|
}
|
|
3408
3436
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3409
|
-
const out =
|
|
3437
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3410
3438
|
let offset = 0;
|
|
3411
3439
|
out.writeUInt8(
|
|
3412
3440
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_COMPLETE_MANY_OK_REQUEST : COMPACT_FLOW_COMPLETE_MANY_REQUEST,
|
|
@@ -3453,7 +3481,7 @@ function compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3453
3481
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3454
3482
|
}
|
|
3455
3483
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3456
|
-
const out =
|
|
3484
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3457
3485
|
let offset = 0;
|
|
3458
3486
|
out.writeUInt8(
|
|
3459
3487
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_RETRY_MANY_OK_REQUEST : COMPACT_FLOW_RETRY_MANY_REQUEST,
|
|
@@ -3541,7 +3569,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3541
3569
|
total += 4 + idLength + 4 + itemPartitionLength + 8;
|
|
3542
3570
|
}
|
|
3543
3571
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3544
|
-
const out =
|
|
3572
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3545
3573
|
let offset = 0;
|
|
3546
3574
|
out.writeUInt8(tag, offset);
|
|
3547
3575
|
offset += 1;
|
|
@@ -3577,7 +3605,7 @@ function isOptionalSafeIntegerNumber(value) {
|
|
|
3577
3605
|
}
|
|
3578
3606
|
|
|
3579
3607
|
// src/protocol-flow-compact-single.ts
|
|
3580
|
-
import { Buffer as
|
|
3608
|
+
import { Buffer as Buffer12 } from "buffer";
|
|
3581
3609
|
function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
3582
3610
|
if (refs.length > 4294967295 || maxBytes != null && (typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 0)) return void 0;
|
|
3583
3611
|
const minimum = 13 + refs.length * 4;
|
|
@@ -3594,7 +3622,7 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3594
3622
|
total += 4 + byteLength;
|
|
3595
3623
|
}
|
|
3596
3624
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3597
|
-
const out =
|
|
3625
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3598
3626
|
let offset = 0;
|
|
3599
3627
|
out.writeUInt8(COMPACT_FLOW_VALUE_MGET_REQUEST, offset);
|
|
3600
3628
|
offset += 1;
|
|
@@ -3637,7 +3665,7 @@ function compactFlowListPayload(args, maxBodyBytes) {
|
|
|
3637
3665
|
const stateLength = state == null ? 0 : compactBinaryByteLength(state);
|
|
3638
3666
|
const total = 1 + 4 + typeLength + 4 + stateLength + 8 + 1;
|
|
3639
3667
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3640
|
-
const out =
|
|
3668
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3641
3669
|
let offset = 0;
|
|
3642
3670
|
out.writeUInt8(COMPACT_FLOW_LIST_REQUEST, offset);
|
|
3643
3671
|
offset += 1;
|
|
@@ -4080,6 +4108,7 @@ function flowSpawnChildrenPayload(args) {
|
|
|
4080
4108
|
"FROM_STATE",
|
|
4081
4109
|
"ON_CHILD_FAILED",
|
|
4082
4110
|
"ON_PARENT_CLOSED",
|
|
4111
|
+
"MAX_ACTIVE_MS",
|
|
4083
4112
|
"VALUE",
|
|
4084
4113
|
"VALUE_REF"
|
|
4085
4114
|
])
|
|
@@ -4110,6 +4139,29 @@ function flowSearchPayload(args) {
|
|
|
4110
4139
|
return { opcode: OPCODES.flowSearch, payload: { type: args[0], ...payload } };
|
|
4111
4140
|
}
|
|
4112
4141
|
|
|
4142
|
+
// src/protocol-flow-signal.ts
|
|
4143
|
+
function flowSignalPayload(args) {
|
|
4144
|
+
if (args.length < 3) return void 0;
|
|
4145
|
+
const options = parseFlowOptions(args, 1, args.length, {
|
|
4146
|
+
allowed: /* @__PURE__ */ new Set([
|
|
4147
|
+
"SIGNAL",
|
|
4148
|
+
"PARTITION",
|
|
4149
|
+
"IDEMPOTENCY",
|
|
4150
|
+
"IF_STATE",
|
|
4151
|
+
"TRANSITION_TO",
|
|
4152
|
+
"RUN_AT",
|
|
4153
|
+
"NOW",
|
|
4154
|
+
"VALUE",
|
|
4155
|
+
"VALUE_REF",
|
|
4156
|
+
"DROP_VALUE",
|
|
4157
|
+
"OVERRIDE_VALUE"
|
|
4158
|
+
]),
|
|
4159
|
+
required: /* @__PURE__ */ new Set(["SIGNAL"])
|
|
4160
|
+
});
|
|
4161
|
+
if (options == null) return void 0;
|
|
4162
|
+
return { opcode: OPCODES.flowSignal, payload: { id: args[0], ...options } };
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4113
4165
|
// src/protocol-connection-policy.ts
|
|
4114
4166
|
function assertCommandDoesNotRequirePinnedConnection(args) {
|
|
4115
4167
|
const outer = commandName(args[0]);
|
|
@@ -4157,7 +4209,7 @@ function commandRequiresOrderedPipelineExecution(args) {
|
|
|
4157
4209
|
}
|
|
4158
4210
|
|
|
4159
4211
|
// src/protocol-compact-request.ts
|
|
4160
|
-
import { Buffer as
|
|
4212
|
+
import { Buffer as Buffer13 } from "buffer";
|
|
4161
4213
|
function compactMsetPayload(args, maxBodyBytes) {
|
|
4162
4214
|
if (args.length % 2 !== 0) throw new FerricStoreError("MSET requires key/value pairs");
|
|
4163
4215
|
const minimum = 6 + args.length * 4;
|
|
@@ -4176,7 +4228,7 @@ function compactMsetPayload(args, maxBodyBytes) {
|
|
|
4176
4228
|
total += 4 + byteLength;
|
|
4177
4229
|
}
|
|
4178
4230
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4179
|
-
const out =
|
|
4231
|
+
const out = Buffer13.allocUnsafe(total);
|
|
4180
4232
|
let offset = writeCompactPipelineHeader(out, 1, args.length / 2);
|
|
4181
4233
|
for (let index = 0; index < args.length; index += 1) {
|
|
4182
4234
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4200,7 +4252,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4200
4252
|
total += 4 + byteLength;
|
|
4201
4253
|
}
|
|
4202
4254
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4203
|
-
const out =
|
|
4255
|
+
const out = Buffer13.allocUnsafe(total);
|
|
4204
4256
|
let offset = writeCompactPipelineHeader(out, mode, args.length);
|
|
4205
4257
|
for (let index = 0; index < args.length; index += 1) {
|
|
4206
4258
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4210,7 +4262,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4210
4262
|
function compactPipelinePayload(commands, maxBodyBytes) {
|
|
4211
4263
|
if (commands.length === 0) {
|
|
4212
4264
|
assertCompactPayloadFits(6, maxBodyBytes);
|
|
4213
|
-
const out =
|
|
4265
|
+
const out = Buffer13.allocUnsafe(6);
|
|
4214
4266
|
writeCompactPipelineHeader(out, 128 | 2, 0);
|
|
4215
4267
|
return out;
|
|
4216
4268
|
}
|
|
@@ -4252,7 +4304,7 @@ function compactSetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4252
4304
|
total += 8 + keyByteLength + valueByteLength;
|
|
4253
4305
|
}
|
|
4254
4306
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4255
|
-
const out =
|
|
4307
|
+
const out = Buffer13.allocUnsafe(total);
|
|
4256
4308
|
let offset = writeCompactPipelineHeader(out, 128 | 1, commands.length);
|
|
4257
4309
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4258
4310
|
offset = writeBinaryValue(out, offset, argumentValues[index * 2], argumentByteLengths[index * 2] ?? 0);
|
|
@@ -4287,7 +4339,7 @@ function compactGetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4287
4339
|
total += 4 + keyByteLength;
|
|
4288
4340
|
}
|
|
4289
4341
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4290
|
-
const out =
|
|
4342
|
+
const out = Buffer13.allocUnsafe(total);
|
|
4291
4343
|
let offset = writeCompactPipelineHeader(out, 128 | 2, commands.length);
|
|
4292
4344
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4293
4345
|
offset = writeBinaryValue(out, offset, keys[index], keyByteLengths[index] ?? 0);
|
|
@@ -4328,7 +4380,7 @@ function writeCompactPipelineHeader(out, mode, count) {
|
|
|
4328
4380
|
}
|
|
4329
4381
|
|
|
4330
4382
|
// src/protocol-kv.ts
|
|
4331
|
-
import { Buffer as
|
|
4383
|
+
import { Buffer as Buffer14 } from "buffer";
|
|
4332
4384
|
function collectionProtocolCommand(command, args) {
|
|
4333
4385
|
switch (command) {
|
|
4334
4386
|
case "CAS":
|
|
@@ -4476,15 +4528,20 @@ function fetchOrComputeCommand(args) {
|
|
|
4476
4528
|
};
|
|
4477
4529
|
}
|
|
4478
4530
|
function fetchOrComputeResultCommand(args) {
|
|
4479
|
-
if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]))
|
|
4531
|
+
if (args.length !== 4 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) {
|
|
4532
|
+
throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT requires key, ownership token, value, and ttl_ms");
|
|
4533
|
+
}
|
|
4480
4534
|
const ttlMs = positiveSafeInteger2(args[3]);
|
|
4481
|
-
|
|
4535
|
+
if (ttlMs == null) throw new FerricStoreError("FETCH_OR_COMPUTE_RESULT ttl_ms must be positive");
|
|
4536
|
+
return {
|
|
4482
4537
|
opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_RESULT,
|
|
4483
4538
|
payload: { key: args[0], token: args[1], ttl_ms: ttlMs, value: args[2] }
|
|
4484
4539
|
};
|
|
4485
4540
|
}
|
|
4486
4541
|
function fetchOrComputeErrorCommand(args) {
|
|
4487
|
-
if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2]))
|
|
4542
|
+
if (args.length !== 3 || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1]) || !isBinaryCommandArgument(args[2])) {
|
|
4543
|
+
throw new FerricStoreError("FETCH_OR_COMPUTE_ERROR requires key, ownership token, and message");
|
|
4544
|
+
}
|
|
4488
4545
|
return {
|
|
4489
4546
|
opcode: COMMAND_OPCODES.FETCH_OR_COMPUTE_ERROR,
|
|
4490
4547
|
payload: { key: args[0], message: args[2], token: args[1] }
|
|
@@ -4570,17 +4627,17 @@ function parsedNumber(value) {
|
|
|
4570
4627
|
}
|
|
4571
4628
|
}
|
|
4572
4629
|
function isBinaryCommandArgument(value) {
|
|
4573
|
-
return typeof value === "string" ||
|
|
4630
|
+
return typeof value === "string" || Buffer14.isBuffer(value);
|
|
4574
4631
|
}
|
|
4575
4632
|
function isDirectKvValueArgument(value) {
|
|
4576
4633
|
return isBinaryCommandArgument(value) || typeof value === "object" && value != null;
|
|
4577
4634
|
}
|
|
4578
4635
|
function binaryToken(value) {
|
|
4579
|
-
return typeof value === "string" ? value.toUpperCase() :
|
|
4636
|
+
return typeof value === "string" ? value.toUpperCase() : Buffer14.isBuffer(value) ? value.toString("utf8").toUpperCase() : void 0;
|
|
4580
4637
|
}
|
|
4581
4638
|
|
|
4582
4639
|
// src/protocol-value.ts
|
|
4583
|
-
import { Buffer as
|
|
4640
|
+
import { Buffer as Buffer15 } from "buffer";
|
|
4584
4641
|
function planValueWithLimit(value, maxBytes) {
|
|
4585
4642
|
const budget = {
|
|
4586
4643
|
maxBytes,
|
|
@@ -4635,7 +4692,7 @@ function planContainerValue(value, budget, ancestors, depth) {
|
|
|
4635
4692
|
let byteLength = 5;
|
|
4636
4693
|
let index = 0;
|
|
4637
4694
|
for (const [key, item] of entries) {
|
|
4638
|
-
const keyByteLength =
|
|
4695
|
+
const keyByteLength = Buffer15.byteLength(key);
|
|
4639
4696
|
consumeEncodeBytes(budget, 4 + keyByteLength);
|
|
4640
4697
|
const valuePlan = planValueAt(item, budget, ancestors, depth + 1);
|
|
4641
4698
|
entryPlans[index] = { key, keyByteLength, value: valuePlan };
|
|
@@ -4684,7 +4741,7 @@ function planScalarValue(value, budget) {
|
|
|
4684
4741
|
consumeEncodeBytes(budget, 9);
|
|
4685
4742
|
return { byteLength: 9, tag: 7, value };
|
|
4686
4743
|
}
|
|
4687
|
-
if (typeof value === "string" ||
|
|
4744
|
+
if (typeof value === "string" || Buffer15.isBuffer(value) || value instanceof Uint8Array) {
|
|
4688
4745
|
const valueByteLength = binaryValueByteLength(value);
|
|
4689
4746
|
const byteLength = 5 + valueByteLength;
|
|
4690
4747
|
consumeEncodeBytes(budget, byteLength);
|
|
@@ -4708,7 +4765,7 @@ function writeValuePlan(output, start, plan) {
|
|
|
4708
4765
|
offset += 4;
|
|
4709
4766
|
if (typeof plan.value === "string") {
|
|
4710
4767
|
output.write(plan.value, offset, plan.valueByteLength, "utf8");
|
|
4711
|
-
} else if (
|
|
4768
|
+
} else if (Buffer15.isBuffer(plan.value)) {
|
|
4712
4769
|
plan.value.copy(output, offset);
|
|
4713
4770
|
} else {
|
|
4714
4771
|
output.set(plan.value, offset);
|
|
@@ -4841,58 +4898,458 @@ function requireAvailable(data, offset, size) {
|
|
|
4841
4898
|
}
|
|
4842
4899
|
}
|
|
4843
4900
|
|
|
4901
|
+
// src/key-slot-validation.ts
|
|
4902
|
+
import { Buffer as Buffer17 } from "buffer";
|
|
4903
|
+
|
|
4904
|
+
// src/topology-utilities.ts
|
|
4905
|
+
import { Buffer as Buffer16 } from "buffer";
|
|
4906
|
+
function isPlainObject3(value) {
|
|
4907
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer16.isBuffer(value);
|
|
4908
|
+
}
|
|
4909
|
+
function getField(source, ...keys) {
|
|
4910
|
+
if (source instanceof Map) {
|
|
4911
|
+
for (const key of keys) {
|
|
4912
|
+
if (source.has(key)) return source.get(key);
|
|
4913
|
+
const bufferKey = Buffer16.from(key);
|
|
4914
|
+
for (const [itemKey, value] of source.entries()) {
|
|
4915
|
+
if (Buffer16.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
4916
|
+
}
|
|
4917
|
+
}
|
|
4918
|
+
return void 0;
|
|
4919
|
+
}
|
|
4920
|
+
if (isPlainObject3(source)) {
|
|
4921
|
+
for (const key of keys) {
|
|
4922
|
+
if (Object.hasOwn(source, key)) return source[key];
|
|
4923
|
+
}
|
|
4924
|
+
}
|
|
4925
|
+
return void 0;
|
|
4926
|
+
}
|
|
4927
|
+
function textOrUndefined(value) {
|
|
4928
|
+
if (typeof value === "string") return value;
|
|
4929
|
+
if (Buffer16.isBuffer(value)) return value.toString("utf8");
|
|
4930
|
+
return void 0;
|
|
4931
|
+
}
|
|
4932
|
+
function numberOrUndefined(value) {
|
|
4933
|
+
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
4934
|
+
}
|
|
4935
|
+
function nativeEventName(event) {
|
|
4936
|
+
return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
|
|
4937
|
+
}
|
|
4938
|
+
function endpointFromRange(item) {
|
|
4939
|
+
const endpointValue = getField(item, "endpoint");
|
|
4940
|
+
if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
|
|
4941
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4942
|
+
}
|
|
4943
|
+
const raw = endpointValue ?? item;
|
|
4944
|
+
const host = textOrUndefined(getField(raw, "host", "native_host"));
|
|
4945
|
+
const nativePort = numberOrUndefined(getField(raw, "native_port"));
|
|
4946
|
+
if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
|
|
4947
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4948
|
+
}
|
|
4949
|
+
const nativeTlsPortValue = getField(raw, "native_tls_port");
|
|
4950
|
+
const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
|
|
4951
|
+
if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
|
|
4952
|
+
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
4953
|
+
}
|
|
4954
|
+
return {
|
|
4955
|
+
host,
|
|
4956
|
+
nativePort,
|
|
4957
|
+
node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
|
|
4958
|
+
...nativeTlsPort == null ? {} : { nativeTlsPort }
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
4961
|
+
function validEndpointHost(host) {
|
|
4962
|
+
if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
|
|
4963
|
+
const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
4964
|
+
try {
|
|
4965
|
+
const url = new URL(`ferric://${authorityHost}:6388`);
|
|
4966
|
+
return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
|
|
4967
|
+
} catch {
|
|
4968
|
+
return false;
|
|
4969
|
+
}
|
|
4970
|
+
}
|
|
4971
|
+
function sameEndpoint(left, right) {
|
|
4972
|
+
return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
|
|
4973
|
+
}
|
|
4974
|
+
function parseFerricUrl2(value) {
|
|
4975
|
+
const url = new URL(value);
|
|
4976
|
+
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
4977
|
+
throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
|
|
4978
|
+
}
|
|
4979
|
+
return {
|
|
4980
|
+
host: normalizeFerricUrlHost(url.hostname),
|
|
4981
|
+
...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
|
|
4982
|
+
port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
|
|
4983
|
+
tls: url.protocol === "ferrics:",
|
|
4984
|
+
...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
|
|
4985
|
+
};
|
|
4986
|
+
}
|
|
4987
|
+
function endpointKeyFor(endpoint) {
|
|
4988
|
+
return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
|
|
4989
|
+
}
|
|
4990
|
+
function connectionKeyForEndpoint(endpoint, useTls) {
|
|
4991
|
+
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
4992
|
+
return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
|
|
4993
|
+
}
|
|
4994
|
+
function connectionKeyFromUrl(url) {
|
|
4995
|
+
const parsed = parseFerricUrl2(url);
|
|
4996
|
+
return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
|
|
4997
|
+
}
|
|
4998
|
+
function normalizedEndpointHost(host) {
|
|
4999
|
+
const lower = host.toLowerCase();
|
|
5000
|
+
return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
|
|
5001
|
+
}
|
|
5002
|
+
function urlFromEndpoint(endpoint, useTls) {
|
|
5003
|
+
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
5004
|
+
const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
|
|
5005
|
+
return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
|
|
5006
|
+
}
|
|
5007
|
+
async function mapSettledWithConcurrency(items, concurrency, operation) {
|
|
5008
|
+
const results = new Array(items.length);
|
|
5009
|
+
let nextIndex = 0;
|
|
5010
|
+
const worker = async () => {
|
|
5011
|
+
while (nextIndex < items.length) {
|
|
5012
|
+
const index = nextIndex++;
|
|
5013
|
+
const item = items[index];
|
|
5014
|
+
try {
|
|
5015
|
+
results[index] = { status: "fulfilled", value: await operation(item, index) };
|
|
5016
|
+
} catch (reason) {
|
|
5017
|
+
results[index] = { status: "rejected", reason };
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
};
|
|
5021
|
+
await Promise.all(Array.from(
|
|
5022
|
+
{ length: Math.min(concurrency, items.length) },
|
|
5023
|
+
async () => await worker()
|
|
5024
|
+
));
|
|
5025
|
+
return results;
|
|
5026
|
+
}
|
|
5027
|
+
function throwFirstRejected(results) {
|
|
5028
|
+
for (const result of results) {
|
|
5029
|
+
if (result.status === "rejected") throw result.reason;
|
|
5030
|
+
}
|
|
5031
|
+
}
|
|
5032
|
+
var TaskConcurrencyLimiter = class {
|
|
5033
|
+
constructor(concurrency) {
|
|
5034
|
+
this.concurrency = concurrency;
|
|
5035
|
+
}
|
|
5036
|
+
concurrency;
|
|
5037
|
+
active = 0;
|
|
5038
|
+
head = 0;
|
|
5039
|
+
pending = [];
|
|
5040
|
+
async run(operation) {
|
|
5041
|
+
await this.acquire();
|
|
5042
|
+
try {
|
|
5043
|
+
return await operation();
|
|
5044
|
+
} finally {
|
|
5045
|
+
this.release();
|
|
5046
|
+
}
|
|
5047
|
+
}
|
|
5048
|
+
acquire() {
|
|
5049
|
+
if (this.active < this.concurrency) {
|
|
5050
|
+
this.active += 1;
|
|
5051
|
+
return Promise.resolve();
|
|
5052
|
+
}
|
|
5053
|
+
return new Promise((resolve) => this.pending.push(resolve));
|
|
5054
|
+
}
|
|
5055
|
+
release() {
|
|
5056
|
+
const next = this.pending[this.head];
|
|
5057
|
+
if (next == null) {
|
|
5058
|
+
this.active -= 1;
|
|
5059
|
+
return;
|
|
5060
|
+
}
|
|
5061
|
+
this.head += 1;
|
|
5062
|
+
next();
|
|
5063
|
+
if (this.head === this.pending.length) {
|
|
5064
|
+
this.pending.length = 0;
|
|
5065
|
+
this.head = 0;
|
|
5066
|
+
} else if (this.head >= 1024 && this.head * 2 >= this.pending.length) {
|
|
5067
|
+
this.pending.splice(0, this.head);
|
|
5068
|
+
this.head = 0;
|
|
5069
|
+
}
|
|
5070
|
+
}
|
|
5071
|
+
};
|
|
5072
|
+
function normalizedHostSet(hosts) {
|
|
5073
|
+
return new Set(
|
|
5074
|
+
hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
|
|
5075
|
+
);
|
|
5076
|
+
}
|
|
5077
|
+
var OPEN_BRACE = "{".charCodeAt(0);
|
|
5078
|
+
var CLOSE_BRACE = "}".charCodeAt(0);
|
|
5079
|
+
function hashTagOrKey(key) {
|
|
5080
|
+
const start = key.indexOf(OPEN_BRACE);
|
|
5081
|
+
if (start < 0) return key;
|
|
5082
|
+
const end = key.indexOf(CLOSE_BRACE, start + 1);
|
|
5083
|
+
return end > start + 1 ? key.subarray(start + 1, end) : key;
|
|
5084
|
+
}
|
|
5085
|
+
var ROUTE_SLOT_MASK = 1023;
|
|
5086
|
+
function routingSlotForKey(key) {
|
|
5087
|
+
if (typeof key === "string") {
|
|
5088
|
+
const [start, end] = stringHashRange(key);
|
|
5089
|
+
return crc32Utf8(key, start, end) & ROUTE_SLOT_MASK;
|
|
5090
|
+
}
|
|
5091
|
+
const keyBytes = key;
|
|
5092
|
+
return crc32(hashTagOrKey(keyBytes)) & ROUTE_SLOT_MASK;
|
|
5093
|
+
}
|
|
5094
|
+
function stringHashRange(key) {
|
|
5095
|
+
const startBrace = key.indexOf("{");
|
|
5096
|
+
const endBrace = startBrace < 0 ? -1 : key.indexOf("}", startBrace + 1);
|
|
5097
|
+
return endBrace > startBrace + 1 ? [startBrace + 1, endBrace] : [0, key.length];
|
|
5098
|
+
}
|
|
5099
|
+
|
|
5100
|
+
// src/key-slot-validation.ts
|
|
5101
|
+
var validatedCommands = /* @__PURE__ */ new WeakSet();
|
|
5102
|
+
function assertAtomicKeyValueCommandSharesSlot(args) {
|
|
5103
|
+
const value = args[0];
|
|
5104
|
+
const command = (typeof value === "string" ? value : Buffer17.isBuffer(value) ? value.toString("utf8") : "").toUpperCase();
|
|
5105
|
+
if (command === "MSET" || command === "MSETNX") {
|
|
5106
|
+
assertKeyValueCommandSharesSlot(args, command);
|
|
5107
|
+
}
|
|
5108
|
+
}
|
|
5109
|
+
function assertKeyValueCommandSharesSlot(args, command) {
|
|
5110
|
+
if (validatedCommands.has(args) || args.length < 3 || args.length % 2 === 0) return;
|
|
5111
|
+
let expectedSlot;
|
|
5112
|
+
for (let index = 1; index < args.length; index += 2) {
|
|
5113
|
+
const key = args[index];
|
|
5114
|
+
if (typeof key !== "string" && !Buffer17.isBuffer(key)) return;
|
|
5115
|
+
const slot = routingSlotForKey(key);
|
|
5116
|
+
expectedSlot ??= slot;
|
|
5117
|
+
if (slot !== expectedSlot) {
|
|
5118
|
+
throw new TypeError(`${command} keys must share a slot`);
|
|
5119
|
+
}
|
|
5120
|
+
}
|
|
5121
|
+
validatedCommands.add(args);
|
|
5122
|
+
}
|
|
5123
|
+
|
|
4844
5124
|
// src/protocol-response.ts
|
|
5125
|
+
import { Buffer as Buffer21 } from "buffer";
|
|
5126
|
+
|
|
5127
|
+
// src/protocol-compact-response.ts
|
|
5128
|
+
import { Buffer as Buffer20 } from "buffer";
|
|
5129
|
+
|
|
5130
|
+
// src/native-negotiation.ts
|
|
4845
5131
|
import { Buffer as Buffer18 } from "buffer";
|
|
5132
|
+
var EMPTY_COMPACT_RESPONSE_OPCODES = /* @__PURE__ */ new Map();
|
|
5133
|
+
function nativeNegotiation(value) {
|
|
5134
|
+
const capabilities = field(value, "capabilities") ?? value;
|
|
5135
|
+
const limits = field(capabilities, "limits");
|
|
5136
|
+
const responseCodecs = field(capabilities, "response_codecs");
|
|
5137
|
+
const maxResponseBytes = positiveSafeInteger3(field(limits, "max_response_bytes"));
|
|
5138
|
+
return {
|
|
5139
|
+
compactResponseOpcodes: parseCompactResponseOpcodes(
|
|
5140
|
+
field(responseCodecs, "compact_response_opcodes")
|
|
5141
|
+
),
|
|
5142
|
+
...maxResponseBytes == null ? {} : { maxResponseBytes }
|
|
5143
|
+
};
|
|
5144
|
+
}
|
|
5145
|
+
function compactResponseOpcodeSupports(capabilities, codec, opcode) {
|
|
5146
|
+
return capabilities?.get(codec)?.has(opcode) === true;
|
|
5147
|
+
}
|
|
5148
|
+
function parseCompactResponseOpcodes(value) {
|
|
5149
|
+
const entries = mapEntries(value);
|
|
5150
|
+
if (entries == null) return EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
5151
|
+
const result = /* @__PURE__ */ new Map();
|
|
5152
|
+
for (const [rawName, rawOpcodes] of entries) {
|
|
5153
|
+
const name = text2(rawName);
|
|
5154
|
+
if (name == null || name.length === 0 || !Array.isArray(rawOpcodes)) continue;
|
|
5155
|
+
const opcodes = /* @__PURE__ */ new Set();
|
|
5156
|
+
let valid = true;
|
|
5157
|
+
for (let index = 0; index < rawOpcodes.length; index += 1) {
|
|
5158
|
+
if (!Object.hasOwn(rawOpcodes, index)) {
|
|
5159
|
+
valid = false;
|
|
5160
|
+
break;
|
|
5161
|
+
}
|
|
5162
|
+
const opcode = unsigned16(rawOpcodes[index]);
|
|
5163
|
+
if (opcode == null) {
|
|
5164
|
+
valid = false;
|
|
5165
|
+
break;
|
|
5166
|
+
}
|
|
5167
|
+
opcodes.add(opcode);
|
|
5168
|
+
}
|
|
5169
|
+
if (valid) result.set(name, opcodes);
|
|
5170
|
+
}
|
|
5171
|
+
return result;
|
|
5172
|
+
}
|
|
5173
|
+
function mapEntries(value) {
|
|
5174
|
+
if (value instanceof Map) return [...value.entries()];
|
|
5175
|
+
if (typeof value !== "object" || value == null || Array.isArray(value)) return void 0;
|
|
5176
|
+
return Object.entries(value);
|
|
5177
|
+
}
|
|
5178
|
+
function unsigned16(value) {
|
|
5179
|
+
const parsed = nonNegativeSafeInteger2(value);
|
|
5180
|
+
return parsed != null && parsed <= 65535 ? parsed : void 0;
|
|
5181
|
+
}
|
|
5182
|
+
function positiveSafeInteger3(value) {
|
|
5183
|
+
const parsed = nonNegativeSafeInteger2(value);
|
|
5184
|
+
return parsed != null && parsed > 0 ? parsed : void 0;
|
|
5185
|
+
}
|
|
5186
|
+
function nonNegativeSafeInteger2(value) {
|
|
5187
|
+
if (typeof value === "bigint") {
|
|
5188
|
+
return value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
5189
|
+
}
|
|
5190
|
+
const source = text2(value) ?? value;
|
|
5191
|
+
if (typeof source !== "number" && (typeof source !== "string" || !/^\d+$/u.test(source))) {
|
|
5192
|
+
return void 0;
|
|
5193
|
+
}
|
|
5194
|
+
const parsed = Number(source);
|
|
5195
|
+
return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : void 0;
|
|
5196
|
+
}
|
|
5197
|
+
function text2(value) {
|
|
5198
|
+
if (typeof value === "string") return value;
|
|
5199
|
+
if (Buffer18.isBuffer(value) || value instanceof Uint8Array) {
|
|
5200
|
+
return Buffer18.from(value).toString("utf8");
|
|
5201
|
+
}
|
|
5202
|
+
return void 0;
|
|
5203
|
+
}
|
|
5204
|
+
|
|
5205
|
+
// src/protocol-compact-collections.ts
|
|
5206
|
+
import "buffer";
|
|
5207
|
+
function decodeCompactIntegerList(data, budget) {
|
|
5208
|
+
requireAvailable(data, 0, 5);
|
|
5209
|
+
const count = data.readUInt32BE(1);
|
|
5210
|
+
requireCompactContainer(count, budget);
|
|
5211
|
+
if (data.byteLength !== 5 + count * 8) {
|
|
5212
|
+
throw new FerricStoreError("invalid compact integer list response");
|
|
5213
|
+
}
|
|
5214
|
+
const values = new Array(count);
|
|
5215
|
+
for (let index = 0, offset = 5; index < count; index += 1, offset += 8) {
|
|
5216
|
+
const value = data.readBigInt64BE(offset);
|
|
5217
|
+
values[index] = value <= MAX_SAFE_INTEGER_BIGINT && value >= MIN_SAFE_INTEGER_BIGINT ? Number(value) : value;
|
|
5218
|
+
}
|
|
5219
|
+
return values;
|
|
5220
|
+
}
|
|
5221
|
+
function decodeCompactBinaryListList(data, budget) {
|
|
5222
|
+
requireAvailable(data, 0, 5);
|
|
5223
|
+
const count = data.readUInt32BE(1);
|
|
5224
|
+
requireCompactContainer(count, budget);
|
|
5225
|
+
let offset = 5;
|
|
5226
|
+
const values = new Array(count);
|
|
5227
|
+
for (let index = 0; index < count; index += 1) {
|
|
5228
|
+
const read = readCompactBinaryList(data, offset, budget);
|
|
5229
|
+
values[index] = read.value;
|
|
5230
|
+
offset = read.offset;
|
|
5231
|
+
}
|
|
5232
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary list-list bytes");
|
|
5233
|
+
return values;
|
|
5234
|
+
}
|
|
5235
|
+
function decodeCompactBinaryMapList(data, budget) {
|
|
5236
|
+
requireAvailable(data, 0, 5);
|
|
5237
|
+
const count = data.readUInt32BE(1);
|
|
5238
|
+
requireCompactContainer(count, budget);
|
|
5239
|
+
let offset = 5;
|
|
5240
|
+
const values = new Array(count);
|
|
5241
|
+
for (let index = 0; index < count; index += 1) {
|
|
5242
|
+
const read = readCompactBinaryMap(data, offset, budget);
|
|
5243
|
+
values[index] = read.value;
|
|
5244
|
+
offset = read.offset;
|
|
5245
|
+
}
|
|
5246
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact binary map-list bytes");
|
|
5247
|
+
return values;
|
|
5248
|
+
}
|
|
5249
|
+
function readCompactBinaryList(data, offset, budget) {
|
|
5250
|
+
requireAvailable(data, offset, 4);
|
|
5251
|
+
const count = data.readUInt32BE(offset);
|
|
5252
|
+
requireCompactContainer(count, budget);
|
|
5253
|
+
offset += 4;
|
|
5254
|
+
const values = new Array(count);
|
|
5255
|
+
for (let index = 0; index < count; index += 1) {
|
|
5256
|
+
const read = readBinary(data, offset);
|
|
5257
|
+
values[index] = read.value;
|
|
5258
|
+
offset = read.offset;
|
|
5259
|
+
}
|
|
5260
|
+
return { value: values, offset };
|
|
5261
|
+
}
|
|
5262
|
+
function readCompactBinaryMap(data, offset, budget) {
|
|
5263
|
+
requireAvailable(data, offset, 4);
|
|
5264
|
+
const count = data.readUInt32BE(offset);
|
|
5265
|
+
requireCompactContainer(count, budget);
|
|
5266
|
+
offset += 4;
|
|
5267
|
+
const values = {};
|
|
5268
|
+
for (let index = 0; index < count; index += 1) {
|
|
5269
|
+
const key = readBinary(data, offset);
|
|
5270
|
+
const value = readBinary(data, key.offset);
|
|
5271
|
+
setOwnValue2(values, key.value.toString("utf8"), value.value);
|
|
5272
|
+
offset = value.offset;
|
|
5273
|
+
}
|
|
5274
|
+
return { value: values, offset };
|
|
5275
|
+
}
|
|
5276
|
+
function markCompactPipelineDecoded(values) {
|
|
5277
|
+
Object.defineProperty(values, COMPACT_PIPELINE_DECODED, { value: true });
|
|
5278
|
+
return values;
|
|
5279
|
+
}
|
|
5280
|
+
function requireCompactContainer(count, budget) {
|
|
5281
|
+
if (count > DEFAULT_MAX_VALUE_ITEMS) {
|
|
5282
|
+
throw new FerricStoreError("native compact response container exceeds max items");
|
|
5283
|
+
}
|
|
5284
|
+
consumeDecodeItems(count, budget);
|
|
5285
|
+
}
|
|
4846
5286
|
|
|
4847
5287
|
// src/protocol-compact-response.ts
|
|
4848
|
-
import { Buffer as Buffer17 } from "buffer";
|
|
4849
5288
|
function tryDecodeCompactResponse(opcode, body, hints) {
|
|
4850
5289
|
if (body.byteLength === 0) return { found: false, value: void 0 };
|
|
4851
5290
|
const budget = { remainingItems: DEFAULT_MAX_VALUE_ITEMS };
|
|
4852
5291
|
const tag = body.readUInt8(0);
|
|
4853
|
-
|
|
5292
|
+
const pipelineValues = opcode === OPCODES.pipeline && supports(hints, "pipeline_v1", opcode);
|
|
5293
|
+
if (tag === COMPACT_OK_LIST && (supports(hints, "ok_list_v1", opcode) || pipelineValues)) {
|
|
4854
5294
|
const values = decodeCompactOkList(body, budget);
|
|
4855
|
-
return {
|
|
5295
|
+
return {
|
|
5296
|
+
found: true,
|
|
5297
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values.length === 1 ? "OK" : values
|
|
5298
|
+
};
|
|
4856
5299
|
}
|
|
4857
|
-
if (tag === COMPACT_KV_GET &&
|
|
5300
|
+
if (tag === COMPACT_KV_GET && supports(hints, "kv_get_v1", opcode)) {
|
|
4858
5301
|
return { found: true, value: decodeCompactKvGet(body) };
|
|
4859
5302
|
}
|
|
4860
|
-
if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) &&
|
|
5303
|
+
if ((tag === COMPACT_KV_MGET || tag === COMPACT_KV_MGET_FIXED) && (supports(hints, "kv_mget_v1", opcode) || pipelineValues)) {
|
|
5304
|
+
const values = tag === COMPACT_KV_MGET ? decodeCompactMget(body, budget) : decodeCompactMgetFixed(body, budget);
|
|
4861
5305
|
return {
|
|
4862
5306
|
found: true,
|
|
4863
|
-
value:
|
|
5307
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
4864
5308
|
};
|
|
4865
5309
|
}
|
|
4866
|
-
if (tag ===
|
|
5310
|
+
if (tag === COMPACT_INTEGER_LIST && pipelineValues) {
|
|
5311
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactIntegerList(body, budget)) };
|
|
5312
|
+
}
|
|
5313
|
+
if (tag === COMPACT_BINARY_LIST_LIST && pipelineValues) {
|
|
5314
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryListList(body, budget)) };
|
|
5315
|
+
}
|
|
5316
|
+
if (tag === COMPACT_BINARY_MAP_LIST && pipelineValues) {
|
|
5317
|
+
return { found: true, value: markCompactPipelineDecoded(decodeCompactBinaryMapList(body, budget)) };
|
|
5318
|
+
}
|
|
5319
|
+
if (tag === COMPACT_PIPELINE_RESPONSE && pipelineValues) {
|
|
4867
5320
|
return { found: true, value: decodeCompactPipeline(body, budget, hints.pipelineClaimModes) };
|
|
4868
5321
|
}
|
|
4869
|
-
if (tag === COMPACT_FLOW_CLAIM_JOBS &&
|
|
4870
|
-
|
|
5322
|
+
if (tag === COMPACT_FLOW_CLAIM_JOBS && (supports(hints, "flow_claim_jobs_v1", opcode) || pipelineValues)) {
|
|
5323
|
+
const values = decodeCompactClaimJobs(body, budget, hints.compactClaimMode);
|
|
5324
|
+
return {
|
|
5325
|
+
found: true,
|
|
5326
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(values) : values
|
|
5327
|
+
};
|
|
4871
5328
|
}
|
|
4872
|
-
if (tag === COMPACT_FLOW_RECORD &&
|
|
5329
|
+
if (tag === COMPACT_FLOW_RECORD && supports(hints, "flow_record_v1", opcode)) {
|
|
4873
5330
|
const read = readCompactFlowRecord(body, 0, budget);
|
|
4874
5331
|
if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record bytes");
|
|
4875
5332
|
return { found: true, value: read.value };
|
|
4876
5333
|
}
|
|
4877
|
-
if (tag === COMPACT_FLOW_RECORD_LIST &&
|
|
5334
|
+
if (tag === COMPACT_FLOW_RECORD_LIST && (supports(hints, "flow_record_list_v1", opcode) || pipelineValues)) {
|
|
4878
5335
|
const read = readCompactFlowRecordList(body, 0, budget);
|
|
4879
5336
|
if (read.offset !== body.byteLength) throw new FerricStoreError("trailing compact Flow record list bytes");
|
|
4880
|
-
return {
|
|
5337
|
+
return {
|
|
5338
|
+
found: true,
|
|
5339
|
+
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(read.value) : read.value
|
|
5340
|
+
};
|
|
4881
5341
|
}
|
|
4882
5342
|
return { found: false, value: void 0 };
|
|
4883
5343
|
}
|
|
4884
|
-
function
|
|
4885
|
-
return compactResponseOpcodeSupports(
|
|
4886
|
-
}
|
|
4887
|
-
function isFlowRecordListOpcode(opcode) {
|
|
4888
|
-
return compactResponseOpcodeSupports(opcode, COMPACT_KIND_FLOW_RECORD_LIST);
|
|
5344
|
+
function supports(hints, codec, opcode) {
|
|
5345
|
+
return compactResponseOpcodeSupports(hints.compactResponseOpcodes, codec, opcode);
|
|
4889
5346
|
}
|
|
4890
5347
|
function decodeCompactOkList(data, budget) {
|
|
4891
5348
|
requireAvailable(data, 0, 5);
|
|
4892
5349
|
const count = data.readUInt32BE(1);
|
|
4893
|
-
|
|
5350
|
+
requireCompactContainer2(count, budget);
|
|
4894
5351
|
if (data.byteLength !== 5) throw new FerricStoreError("invalid compact OK list response");
|
|
4895
|
-
return Array.from({ length: count }, () =>
|
|
5352
|
+
return Array.from({ length: count }, () => Buffer20.from("OK"));
|
|
4896
5353
|
}
|
|
4897
5354
|
function decodeCompactKvGet(data) {
|
|
4898
5355
|
requireAvailable(data, 0, 2);
|
|
@@ -4909,7 +5366,7 @@ function decodeCompactKvGet(data) {
|
|
|
4909
5366
|
function decodeCompactMget(data, budget) {
|
|
4910
5367
|
requireAvailable(data, 0, 5);
|
|
4911
5368
|
const count = data.readUInt32BE(1);
|
|
4912
|
-
|
|
5369
|
+
requireCompactContainer2(count, budget);
|
|
4913
5370
|
let offset = 5;
|
|
4914
5371
|
const values = [];
|
|
4915
5372
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -4933,12 +5390,12 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
4933
5390
|
requireAvailable(data, 0, 9);
|
|
4934
5391
|
const count = data.readUInt32BE(1);
|
|
4935
5392
|
const size = data.readUInt32BE(5);
|
|
4936
|
-
|
|
5393
|
+
requireCompactContainer2(count, budget);
|
|
4937
5394
|
const expected = 9 + count * size;
|
|
4938
5395
|
if (size === NULL_U32 || data.byteLength !== expected) {
|
|
4939
5396
|
throw new FerricStoreError("invalid compact fixed MGET response");
|
|
4940
5397
|
}
|
|
4941
|
-
if (size === 0) return new Array(count).fill(
|
|
5398
|
+
if (size === 0) return new Array(count).fill(Buffer20.alloc(0));
|
|
4942
5399
|
const values = new Array(count);
|
|
4943
5400
|
for (let index = 0, offset = 9; index < count; index += 1, offset += size) {
|
|
4944
5401
|
values[index] = data.subarray(offset, offset + size);
|
|
@@ -4948,7 +5405,7 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
4948
5405
|
function decodeCompactPipeline(data, budget, claimModes) {
|
|
4949
5406
|
requireAvailable(data, 0, 5);
|
|
4950
5407
|
const count = data.readUInt32BE(1);
|
|
4951
|
-
|
|
5408
|
+
requireCompactContainer2(count, budget);
|
|
4952
5409
|
if (count > Math.floor((data.byteLength - 5) / 2)) {
|
|
4953
5410
|
throw new FerricStoreError("compact pipeline item count exceeds response bytes");
|
|
4954
5411
|
}
|
|
@@ -5010,13 +5467,12 @@ function decodeCompactPipeline(data, budget, claimModes) {
|
|
|
5010
5467
|
}
|
|
5011
5468
|
}
|
|
5012
5469
|
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact pipeline bytes");
|
|
5013
|
-
|
|
5014
|
-
return values;
|
|
5470
|
+
return markCompactPipelineDecoded(values);
|
|
5015
5471
|
}
|
|
5016
5472
|
function decodeCompactClaimJobs(data, budget, mode) {
|
|
5017
5473
|
requireAvailable(data, 0, 5);
|
|
5018
5474
|
const count = data.readUInt32BE(1);
|
|
5019
|
-
|
|
5475
|
+
requireCompactContainer2(count, budget);
|
|
5020
5476
|
if (mode != null) {
|
|
5021
5477
|
const values = [];
|
|
5022
5478
|
let offset = 5;
|
|
@@ -5100,7 +5556,7 @@ function readCompactFlowRecord(data, offset, budget = { remainingItems: DEFAULT_
|
|
|
5100
5556
|
if (data.readUInt8(offset) !== COMPACT_FLOW_RECORD) throw new FerricStoreError("expected compact Flow record");
|
|
5101
5557
|
offset += 1;
|
|
5102
5558
|
const count = data.readUInt32BE(offset);
|
|
5103
|
-
|
|
5559
|
+
requireCompactContainer2(count, budget);
|
|
5104
5560
|
offset += 4;
|
|
5105
5561
|
const record = {};
|
|
5106
5562
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -5128,7 +5584,7 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
|
|
|
5128
5584
|
}
|
|
5129
5585
|
offset += 1;
|
|
5130
5586
|
const count = data.readUInt32BE(offset);
|
|
5131
|
-
|
|
5587
|
+
requireCompactContainer2(count, budget);
|
|
5132
5588
|
offset += 4;
|
|
5133
5589
|
const records = [];
|
|
5134
5590
|
for (let index = 0; index < count; index += 1) {
|
|
@@ -5136,34 +5592,7 @@ function readCompactFlowRecordList(data, offset, budget = { remainingItems: DEFA
|
|
|
5136
5592
|
records.push(read.value);
|
|
5137
5593
|
offset = read.offset;
|
|
5138
5594
|
}
|
|
5139
|
-
return { value: records, offset };
|
|
5140
|
-
}
|
|
5141
|
-
function readCompactBinaryList(data, offset, budget) {
|
|
5142
|
-
requireAvailable(data, offset, 4);
|
|
5143
|
-
const count = data.readUInt32BE(offset);
|
|
5144
|
-
requireCompactContainer(count, budget);
|
|
5145
|
-
offset += 4;
|
|
5146
|
-
const values = [];
|
|
5147
|
-
for (let index = 0; index < count; index += 1) {
|
|
5148
|
-
const read = readBinary(data, offset);
|
|
5149
|
-
values.push(read.value);
|
|
5150
|
-
offset = read.offset;
|
|
5151
|
-
}
|
|
5152
|
-
return { value: values, offset };
|
|
5153
|
-
}
|
|
5154
|
-
function readCompactBinaryMap(data, offset, budget) {
|
|
5155
|
-
requireAvailable(data, offset, 4);
|
|
5156
|
-
const count = data.readUInt32BE(offset);
|
|
5157
|
-
requireCompactContainer(count, budget);
|
|
5158
|
-
offset += 4;
|
|
5159
|
-
const values = {};
|
|
5160
|
-
for (let index = 0; index < count; index += 1) {
|
|
5161
|
-
const key = readBinary(data, offset);
|
|
5162
|
-
const value = readBinary(data, key.offset);
|
|
5163
|
-
setOwnValue2(values, key.value.toString("utf8"), value.value);
|
|
5164
|
-
offset = value.offset;
|
|
5165
|
-
}
|
|
5166
|
-
return { value: values, offset };
|
|
5595
|
+
return { value: records, offset };
|
|
5167
5596
|
}
|
|
5168
5597
|
function readOptionalBinary(data, offset) {
|
|
5169
5598
|
requireAvailable(data, offset, 4);
|
|
@@ -5173,7 +5602,7 @@ function readOptionalBinary(data, offset) {
|
|
|
5173
5602
|
requireAvailable(data, offset, size);
|
|
5174
5603
|
return { value: data.subarray(offset, offset + size), offset: offset + size };
|
|
5175
5604
|
}
|
|
5176
|
-
function
|
|
5605
|
+
function requireCompactContainer2(count, budget) {
|
|
5177
5606
|
if (count > DEFAULT_MAX_VALUE_ITEMS) {
|
|
5178
5607
|
throw new FerricStoreError("native compact response container exceeds max items");
|
|
5179
5608
|
}
|
|
@@ -5181,7 +5610,7 @@ function requireCompactContainer(count, budget) {
|
|
|
5181
5610
|
}
|
|
5182
5611
|
function errorMessage(status, value) {
|
|
5183
5612
|
if (typeof value === "string") return value;
|
|
5184
|
-
if (
|
|
5613
|
+
if (Buffer20.isBuffer(value)) return value.toString("utf8");
|
|
5185
5614
|
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5186
5615
|
const message = value.message;
|
|
5187
5616
|
return typeof message === "string" ? message : String(message);
|
|
@@ -5261,7 +5690,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5261
5690
|
return out;
|
|
5262
5691
|
}
|
|
5263
5692
|
function pipelineStatus(value) {
|
|
5264
|
-
if (typeof value !== "string" && !
|
|
5693
|
+
if (typeof value !== "string" && !Buffer21.isBuffer(value) && !(value instanceof Uint8Array)) return null;
|
|
5265
5694
|
const status = asText(value).toLowerCase();
|
|
5266
5695
|
return status === "ok" || status === "busy" || status === "error" ? status : null;
|
|
5267
5696
|
}
|
|
@@ -5276,7 +5705,7 @@ function decodeResponseValue(opcode, body, hints) {
|
|
|
5276
5705
|
}
|
|
5277
5706
|
function errorMessage2(status, value) {
|
|
5278
5707
|
if (typeof value === "string") return value;
|
|
5279
|
-
if (
|
|
5708
|
+
if (Buffer21.isBuffer(value)) return value.toString("utf8");
|
|
5280
5709
|
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5281
5710
|
const message = value.message;
|
|
5282
5711
|
return typeof message === "string" ? message : String(message);
|
|
@@ -5292,7 +5721,7 @@ function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGE
|
|
|
5292
5721
|
const bodyLength = customPayload ? binaryValueByteLength(command.payload) : plan?.byteLength ?? 0;
|
|
5293
5722
|
if (bodyLength > bodyLimit) throw requestFrameTooLarge(bodyLimit);
|
|
5294
5723
|
const flags = command.flags ?? 0;
|
|
5295
|
-
const frame =
|
|
5724
|
+
const frame = Buffer22.allocUnsafe(HEADER_SIZE + bodyLength);
|
|
5296
5725
|
frame.write(MAGIC, 0, "ascii");
|
|
5297
5726
|
frame.writeUInt8(REQUEST_VERSION, 4);
|
|
5298
5727
|
frame.writeUInt8(flags, 5);
|
|
@@ -5343,6 +5772,9 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5343
5772
|
}
|
|
5344
5773
|
const command = asText(args[0]).toUpperCase();
|
|
5345
5774
|
assertNormalizedCommandDoesNotRequirePinnedConnection(args, command);
|
|
5775
|
+
if (command === "MSET" || command === "MSETNX") {
|
|
5776
|
+
assertKeyValueCommandSharesSlot(args, command);
|
|
5777
|
+
}
|
|
5346
5778
|
const commandArgs2 = args.slice(1);
|
|
5347
5779
|
if (command === "COMMAND_EXEC" && commandArgs2.length >= 1) {
|
|
5348
5780
|
return commandExec(commandArgs2);
|
|
@@ -5480,20 +5912,7 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5480
5912
|
])) ?? commandExec(args);
|
|
5481
5913
|
}
|
|
5482
5914
|
if (command === "FLOW.SIGNAL") {
|
|
5483
|
-
return
|
|
5484
|
-
"SIGNAL",
|
|
5485
|
-
"PARTITION",
|
|
5486
|
-
"IDEMPOTENCY",
|
|
5487
|
-
"IF_STATE",
|
|
5488
|
-
"TRANSITION_TO",
|
|
5489
|
-
"RUN_AT",
|
|
5490
|
-
"NOW",
|
|
5491
|
-
"PRIORITY",
|
|
5492
|
-
"VALUE",
|
|
5493
|
-
"VALUE_REF",
|
|
5494
|
-
"DROP_VALUE",
|
|
5495
|
-
"OVERRIDE_VALUE"
|
|
5496
|
-
]));
|
|
5915
|
+
return flowSignalPayload(commandArgs2) ?? commandExec(args);
|
|
5497
5916
|
}
|
|
5498
5917
|
if (command === "FLOW.CANCEL") {
|
|
5499
5918
|
return flowCommandExecWithRouting(command, commandArgs2, 1, /* @__PURE__ */ new Set([
|
|
@@ -5662,6 +6081,7 @@ var DEFAULT_MAX_PENDING_CONTROL_REQUESTS = 4096;
|
|
|
5662
6081
|
var DEFAULT_MAX_RESPONSE_BYTES = 64 * 1024 * 1024;
|
|
5663
6082
|
var DEFAULT_MAX_QUEUED_REQUESTS = 65536;
|
|
5664
6083
|
var DEFAULT_MAX_QUEUED_WRITE_BYTES = 64 * 1024 * 1024;
|
|
6084
|
+
var UNAUTHENTICATED_MAX_FRAME_BYTES = 64 * 1024;
|
|
5665
6085
|
function assertNativeAdapterOptions(options) {
|
|
5666
6086
|
const supplied = options;
|
|
5667
6087
|
for (const name of ["autoReconnect", "haRouting", "seeds"]) {
|
|
@@ -5681,7 +6101,7 @@ import "net";
|
|
|
5681
6101
|
import "tls";
|
|
5682
6102
|
|
|
5683
6103
|
// src/client-native-options.ts
|
|
5684
|
-
import { Buffer as
|
|
6104
|
+
import { Buffer as Buffer23 } from "buffer";
|
|
5685
6105
|
|
|
5686
6106
|
// src/string-array-snapshot.ts
|
|
5687
6107
|
function snapshotOwnStringArray(values, name) {
|
|
@@ -5764,7 +6184,7 @@ function snapshotTlsOptions(options) {
|
|
|
5764
6184
|
return Object.freeze(snapshot);
|
|
5765
6185
|
}
|
|
5766
6186
|
function snapshotTlsValue(value, name) {
|
|
5767
|
-
if (
|
|
6187
|
+
if (Buffer23.isBuffer(value)) return Buffer23.from(value);
|
|
5768
6188
|
if (value instanceof Uint8Array) return value.slice();
|
|
5769
6189
|
if (Array.isArray(value)) {
|
|
5770
6190
|
const snapshot = new Array(value.length);
|
|
@@ -6234,6 +6654,9 @@ var NativeChunkAssembler = class {
|
|
|
6234
6654
|
framesByKey = /* @__PURE__ */ new Map();
|
|
6235
6655
|
totalBytes = 0;
|
|
6236
6656
|
totalFrames = 0;
|
|
6657
|
+
updateMaxResponseBytes(limit) {
|
|
6658
|
+
this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
|
|
6659
|
+
}
|
|
6237
6660
|
assemble(frame) {
|
|
6238
6661
|
const key = `${frame.requestId}:${frame.opcode}:${frame.laneId}`;
|
|
6239
6662
|
const previous = this.chunks.get(key);
|
|
@@ -6478,12 +6901,18 @@ var NativeReceiveBuffer = class {
|
|
|
6478
6901
|
var NativeResponseHandler = class {
|
|
6479
6902
|
constructor(options) {
|
|
6480
6903
|
this.options = options;
|
|
6904
|
+
this.maxResponseBytes = options.maxResponseBytes;
|
|
6481
6905
|
}
|
|
6482
6906
|
options;
|
|
6483
6907
|
receiveBuffer = new NativeReceiveBuffer();
|
|
6484
6908
|
drainScheduled = false;
|
|
6485
6909
|
paused = false;
|
|
6486
6910
|
stopped = false;
|
|
6911
|
+
maxResponseBytes;
|
|
6912
|
+
updateMaxResponseBytes(limit) {
|
|
6913
|
+
this.maxResponseBytes = Math.min(this.maxResponseBytes, limit);
|
|
6914
|
+
this.options.chunkAssembler.updateMaxResponseBytes(this.maxResponseBytes);
|
|
6915
|
+
}
|
|
6487
6916
|
onData(chunk) {
|
|
6488
6917
|
if (this.stopped) return;
|
|
6489
6918
|
try {
|
|
@@ -6565,15 +6994,18 @@ var NativeResponseHandler = class {
|
|
|
6565
6994
|
}
|
|
6566
6995
|
const completeFrame = this.options.chunkAssembler.assemble(frame);
|
|
6567
6996
|
if (completeFrame == null) return;
|
|
6568
|
-
if (completeFrame.body.byteLength > this.
|
|
6997
|
+
if (completeFrame.body.byteLength > this.maxResponseBytes) {
|
|
6569
6998
|
throw new FerricStoreError(
|
|
6570
|
-
`native protocol response exceeded ${this.
|
|
6999
|
+
`native protocol response exceeded ${this.maxResponseBytes} bytes`
|
|
6571
7000
|
);
|
|
6572
7001
|
}
|
|
6573
7002
|
let value;
|
|
6574
7003
|
let responseError;
|
|
6575
7004
|
try {
|
|
6576
|
-
value = decodeResponse(completeFrame, pending.opcode,
|
|
7005
|
+
value = decodeResponse(completeFrame, pending.opcode, {
|
|
7006
|
+
...pending,
|
|
7007
|
+
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7008
|
+
});
|
|
6577
7009
|
if (pending.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
6578
7010
|
} catch (error) {
|
|
6579
7011
|
responseError = error;
|
|
@@ -6589,7 +7021,7 @@ var NativeResponseHandler = class {
|
|
|
6589
7021
|
pending.discardedResponseBytes = discardedResponseBytes;
|
|
6590
7022
|
pending.discardedResponseFrames = discardedResponseFrames;
|
|
6591
7023
|
const chunked = discardedResponseFrames > 1 || (frame.flags & FLAG_MORE_CHUNKS) !== 0;
|
|
6592
|
-
if (discardedResponseBytes > this.
|
|
7024
|
+
if (discardedResponseBytes > this.maxResponseBytes || chunked && discardedResponseBytes > this.options.maxChunkBytes) {
|
|
6593
7025
|
throw new FerricStoreError("native protocol discarded response exceeded configured byte limits");
|
|
6594
7026
|
}
|
|
6595
7027
|
if (discardedResponseFrames > this.options.maxChunkFrames) {
|
|
@@ -6598,12 +7030,14 @@ var NativeResponseHandler = class {
|
|
|
6598
7030
|
if ((frame.flags & FLAG_MORE_CHUNKS) === 0) this.options.takePending(frame.requestId);
|
|
6599
7031
|
}
|
|
6600
7032
|
handleManagementFrame(frame) {
|
|
6601
|
-
if (frame.body.byteLength > this.
|
|
7033
|
+
if (frame.body.byteLength > this.maxResponseBytes) {
|
|
6602
7034
|
throw new FerricStoreError(
|
|
6603
|
-
`native protocol response exceeded ${this.
|
|
7035
|
+
`native protocol response exceeded ${this.maxResponseBytes} bytes`
|
|
6604
7036
|
);
|
|
6605
7037
|
}
|
|
6606
|
-
const value = decodeResponse(frame, frame.opcode
|
|
7038
|
+
const value = decodeResponse(frame, frame.opcode, {
|
|
7039
|
+
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7040
|
+
});
|
|
6607
7041
|
if (frame.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
6608
7042
|
const event = {
|
|
6609
7043
|
flags: frame.flags,
|
|
@@ -6768,6 +7202,40 @@ var NativeWriteQueue = class {
|
|
|
6768
7202
|
}
|
|
6769
7203
|
};
|
|
6770
7204
|
|
|
7205
|
+
// src/native-connection-capabilities.ts
|
|
7206
|
+
var NativeConnectionCapabilities = class {
|
|
7207
|
+
constructor(configuredRequestFrameBytes) {
|
|
7208
|
+
this.configuredRequestFrameBytes = configuredRequestFrameBytes;
|
|
7209
|
+
this.negotiatedRequestFrameBytes = configuredRequestFrameBytes;
|
|
7210
|
+
this.requestFrameBytes = Math.min(configuredRequestFrameBytes, UNAUTHENTICATED_MAX_FRAME_BYTES);
|
|
7211
|
+
}
|
|
7212
|
+
configuredRequestFrameBytes;
|
|
7213
|
+
compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
7214
|
+
requestFrameBytes;
|
|
7215
|
+
negotiatedRequestFrameBytes;
|
|
7216
|
+
apply(value) {
|
|
7217
|
+
const limits = startupLimits(value);
|
|
7218
|
+
const negotiation = nativeNegotiation(value);
|
|
7219
|
+
this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
|
|
7220
|
+
if (limits.frameBytes != null) {
|
|
7221
|
+
this.negotiatedRequestFrameBytes = Math.min(
|
|
7222
|
+
this.configuredRequestFrameBytes,
|
|
7223
|
+
limits.frameBytes
|
|
7224
|
+
);
|
|
7225
|
+
this.requestFrameBytes = Math.min(this.requestFrameBytes, this.negotiatedRequestFrameBytes);
|
|
7226
|
+
}
|
|
7227
|
+
return {
|
|
7228
|
+
...limits.laneQueue == null ? {} : { laneQueue: limits.laneQueue },
|
|
7229
|
+
...limits.lanes == null ? {} : { lanes: limits.lanes },
|
|
7230
|
+
...negotiation.maxResponseBytes == null ? {} : { maxResponseBytes: negotiation.maxResponseBytes },
|
|
7231
|
+
...limits.pipelineCommands == null ? {} : { pipelineCommands: limits.pipelineCommands }
|
|
7232
|
+
};
|
|
7233
|
+
}
|
|
7234
|
+
activateAuthenticated() {
|
|
7235
|
+
this.requestFrameBytes = this.negotiatedRequestFrameBytes;
|
|
7236
|
+
}
|
|
7237
|
+
};
|
|
7238
|
+
|
|
6771
7239
|
// src/native-adapter.ts
|
|
6772
7240
|
var NativeAdapter = class _NativeAdapter {
|
|
6773
7241
|
socket;
|
|
@@ -6776,9 +7244,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6776
7244
|
closedWaiters = /* @__PURE__ */ new Set();
|
|
6777
7245
|
chunkAssembler;
|
|
6778
7246
|
closed = false;
|
|
7247
|
+
capabilities;
|
|
6779
7248
|
protocolLanes;
|
|
6780
7249
|
maxPipelineCommands = Number.MAX_SAFE_INTEGER;
|
|
6781
|
-
maxRequestFrameBytes;
|
|
6782
7250
|
pendingControlRequests = 0;
|
|
6783
7251
|
maxPendingControlRequests;
|
|
6784
7252
|
heartbeat;
|
|
@@ -6793,7 +7261,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6793
7261
|
const normalizedMaxChunkBytes = normalizePositiveLimit(maxChunkBytes, DEFAULT_MAX_CHUNK_BYTES);
|
|
6794
7262
|
const normalizedMaxChunkFrames = normalizePositiveLimit(maxChunkFrames, DEFAULT_MAX_CHUNK_FRAMES);
|
|
6795
7263
|
const normalizedMaxFrameBytes = normalizePositiveLimit(maxFrameBytes, DEFAULT_MAX_FRAME_BYTES);
|
|
6796
|
-
this.
|
|
7264
|
+
this.capabilities = new NativeConnectionCapabilities(normalizedMaxFrameBytes);
|
|
6797
7265
|
const normalizedMaxResponseBytes = normalizePositiveLimit(maxResponseBytes, DEFAULT_MAX_RESPONSE_BYTES);
|
|
6798
7266
|
this.chunkAssembler = new NativeChunkAssembler(
|
|
6799
7267
|
normalizedMaxChunkBytes,
|
|
@@ -6820,7 +7288,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6820
7288
|
this.heartbeat = new NativeHeartbeat(
|
|
6821
7289
|
this.heartbeatIntervalMs,
|
|
6822
7290
|
async () => {
|
|
6823
|
-
await this.request(buildProtocolCommand(["PING"], this.
|
|
7291
|
+
await this.request(buildProtocolCommand(["PING"], this.capabilities.requestFrameBytes), true);
|
|
6824
7292
|
},
|
|
6825
7293
|
(error) => {
|
|
6826
7294
|
this.failAll(new FerricStoreError("FerricStore protocol heartbeat failed", { cause: error }), true);
|
|
@@ -6831,6 +7299,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6831
7299
|
applyFlowControlLimits: (value) => this.applyFlowControlLimits(value),
|
|
6832
7300
|
beginDraining: () => this.beginDraining(),
|
|
6833
7301
|
chunkAssembler: this.chunkAssembler,
|
|
7302
|
+
compactResponseOpcodes: () => this.capabilities.compactResponseOpcodes,
|
|
6834
7303
|
destroy: (error) => this.socket.destroy(error),
|
|
6835
7304
|
failAll: (reason, connectionClosed, message) => this.failAll(reason, connectionClosed, message),
|
|
6836
7305
|
heartbeat: this.heartbeat,
|
|
@@ -6856,6 +7325,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6856
7325
|
adapter,
|
|
6857
7326
|
auth: async (username, password) => {
|
|
6858
7327
|
await adapter.request({ laneId: 0, opcode: OPCODES.auth, payload: { password, username } });
|
|
7328
|
+
adapter.capabilities.activateAuthenticated();
|
|
6859
7329
|
},
|
|
6860
7330
|
close: async () => {
|
|
6861
7331
|
await adapter.close();
|
|
@@ -6873,13 +7343,13 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6873
7343
|
return await this.executeCommandArgs(args);
|
|
6874
7344
|
}
|
|
6875
7345
|
async executeCommandArgs(args) {
|
|
6876
|
-
const command = buildProtocolCommand(args, this.
|
|
7346
|
+
const command = buildProtocolCommand(args, this.capabilities.requestFrameBytes);
|
|
6877
7347
|
return await this.request(command);
|
|
6878
7348
|
}
|
|
6879
7349
|
/** @internal Execute raw command arguments on a topology-selected lane. */
|
|
6880
7350
|
async executeCommandOnLane(args, laneId) {
|
|
6881
7351
|
return await this.executeProtocolCommand(
|
|
6882
|
-
buildProtocolCommand(args, this.
|
|
7352
|
+
buildProtocolCommand(args, this.capabilities.requestFrameBytes),
|
|
6883
7353
|
laneId
|
|
6884
7354
|
);
|
|
6885
7355
|
}
|
|
@@ -6901,7 +7371,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6901
7371
|
laneId,
|
|
6902
7372
|
options,
|
|
6903
7373
|
this.maxPipelineCommands,
|
|
6904
|
-
this.
|
|
7374
|
+
this.capabilities.requestFrameBytes
|
|
6905
7375
|
);
|
|
6906
7376
|
}
|
|
6907
7377
|
/** @internal Execute an ordered pipeline on a topology-selected lane. */
|
|
@@ -6912,13 +7382,11 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6912
7382
|
laneId,
|
|
6913
7383
|
options,
|
|
6914
7384
|
this.maxPipelineCommands,
|
|
6915
|
-
this.
|
|
7385
|
+
this.capabilities.requestFrameBytes
|
|
6916
7386
|
);
|
|
6917
7387
|
}
|
|
6918
7388
|
async close() {
|
|
6919
|
-
if (this.closed)
|
|
6920
|
-
return;
|
|
6921
|
-
}
|
|
7389
|
+
if (this.closed) return;
|
|
6922
7390
|
this.failAll(new FerricStoreError("FerricStore connection closed"), true);
|
|
6923
7391
|
this.socket.destroy();
|
|
6924
7392
|
}
|
|
@@ -6936,7 +7404,9 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6936
7404
|
});
|
|
6937
7405
|
this.applyStartupLimits(response);
|
|
6938
7406
|
const authRequired = field(response, "auth_required");
|
|
6939
|
-
|
|
7407
|
+
const required = authRequired == null ? false : booleanResponse(authRequired);
|
|
7408
|
+
if (authRequired != null && !required) this.capabilities.activateAuthenticated();
|
|
7409
|
+
return required;
|
|
6940
7410
|
}
|
|
6941
7411
|
request(command, allowWhileDraining = false) {
|
|
6942
7412
|
if (this.closed || this.draining && !allowWhileDraining) {
|
|
@@ -6977,7 +7447,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
6977
7447
|
let frame;
|
|
6978
7448
|
try {
|
|
6979
7449
|
requestId = this.requestScheduler.nextRequestId();
|
|
6980
|
-
frame = encodeRequest(command, requestId, this.
|
|
7450
|
+
frame = encodeRequest(command, requestId, this.capabilities.requestFrameBytes);
|
|
6981
7451
|
} catch (error) {
|
|
6982
7452
|
if (hasFlowControlCredit) this.flowControl.release(laneId);
|
|
6983
7453
|
return Promise.reject(error instanceof Error ? error : new FerricStoreError(String(error), { raw: error }));
|
|
@@ -7031,9 +7501,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7031
7501
|
this.resolveClosedWaiters();
|
|
7032
7502
|
}
|
|
7033
7503
|
failAll(reason, connectionClosed = false, dispatchedMessage) {
|
|
7034
|
-
if (this.closed)
|
|
7035
|
-
return;
|
|
7036
|
-
}
|
|
7504
|
+
if (this.closed) return;
|
|
7037
7505
|
this.closed = true;
|
|
7038
7506
|
this.responseHandler.stop();
|
|
7039
7507
|
this.resolveClosedWaiters();
|
|
@@ -7099,18 +7567,18 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7099
7567
|
}
|
|
7100
7568
|
applyStartupLimits(value) {
|
|
7101
7569
|
this.applyFlowControlLimits(value);
|
|
7102
|
-
const
|
|
7103
|
-
if (
|
|
7104
|
-
this.
|
|
7570
|
+
const capabilities = this.capabilities.apply(value);
|
|
7571
|
+
if (capabilities.maxResponseBytes != null) {
|
|
7572
|
+
this.responseHandler.updateMaxResponseBytes(capabilities.maxResponseBytes);
|
|
7105
7573
|
}
|
|
7106
|
-
if (
|
|
7107
|
-
this.
|
|
7574
|
+
if (capabilities.laneQueue != null) {
|
|
7575
|
+
this.flowControl.updateLaneQueueLimit(capabilities.laneQueue);
|
|
7108
7576
|
}
|
|
7109
|
-
if (
|
|
7110
|
-
this.
|
|
7577
|
+
if (capabilities.lanes != null) {
|
|
7578
|
+
this.protocolLanes = Math.min(this.protocolLanes, capabilities.lanes);
|
|
7111
7579
|
}
|
|
7112
|
-
if (
|
|
7113
|
-
this.
|
|
7580
|
+
if (capabilities.pipelineCommands != null) {
|
|
7581
|
+
this.maxPipelineCommands = capabilities.pipelineCommands;
|
|
7114
7582
|
}
|
|
7115
7583
|
}
|
|
7116
7584
|
};
|
|
@@ -7321,214 +7789,8 @@ function normalizeNonNegativeInteger2(value, fallback) {
|
|
|
7321
7789
|
import "buffer";
|
|
7322
7790
|
|
|
7323
7791
|
// src/topology-routing.ts
|
|
7324
|
-
import { Buffer as
|
|
7792
|
+
import { Buffer as Buffer28 } from "buffer";
|
|
7325
7793
|
import { createHash } from "crypto";
|
|
7326
|
-
|
|
7327
|
-
// src/topology-utilities.ts
|
|
7328
|
-
import { Buffer as Buffer25 } from "buffer";
|
|
7329
|
-
function isPlainObject3(value) {
|
|
7330
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer25.isBuffer(value);
|
|
7331
|
-
}
|
|
7332
|
-
function getField(source, ...keys) {
|
|
7333
|
-
if (source instanceof Map) {
|
|
7334
|
-
for (const key of keys) {
|
|
7335
|
-
if (source.has(key)) return source.get(key);
|
|
7336
|
-
const bufferKey = Buffer25.from(key);
|
|
7337
|
-
for (const [itemKey, value] of source.entries()) {
|
|
7338
|
-
if (Buffer25.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
7339
|
-
}
|
|
7340
|
-
}
|
|
7341
|
-
return void 0;
|
|
7342
|
-
}
|
|
7343
|
-
if (isPlainObject3(source)) {
|
|
7344
|
-
for (const key of keys) {
|
|
7345
|
-
if (Object.hasOwn(source, key)) return source[key];
|
|
7346
|
-
}
|
|
7347
|
-
}
|
|
7348
|
-
return void 0;
|
|
7349
|
-
}
|
|
7350
|
-
function textOrUndefined(value) {
|
|
7351
|
-
if (typeof value === "string") return value;
|
|
7352
|
-
if (Buffer25.isBuffer(value)) return value.toString("utf8");
|
|
7353
|
-
return void 0;
|
|
7354
|
-
}
|
|
7355
|
-
function numberOrUndefined(value) {
|
|
7356
|
-
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
7357
|
-
}
|
|
7358
|
-
function nativeEventName(event) {
|
|
7359
|
-
return textOrUndefined(getField(event.value, "event"))?.toUpperCase();
|
|
7360
|
-
}
|
|
7361
|
-
function endpointFromRange(item) {
|
|
7362
|
-
const endpointValue = getField(item, "endpoint");
|
|
7363
|
-
if (endpointValue != null && !isPlainObject3(endpointValue) && !(endpointValue instanceof Map)) {
|
|
7364
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7365
|
-
}
|
|
7366
|
-
const raw = endpointValue ?? item;
|
|
7367
|
-
const host = textOrUndefined(getField(raw, "host", "native_host"));
|
|
7368
|
-
const nativePort = numberOrUndefined(getField(raw, "native_port"));
|
|
7369
|
-
if (host == null || !validEndpointHost(host) || nativePort == null || nativePort <= 0 || nativePort > 65535) {
|
|
7370
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7371
|
-
}
|
|
7372
|
-
const nativeTlsPortValue = getField(raw, "native_tls_port");
|
|
7373
|
-
const nativeTlsPort = numberOrUndefined(nativeTlsPortValue);
|
|
7374
|
-
if (nativeTlsPortValue != null && (nativeTlsPort == null || nativeTlsPort <= 0 || nativeTlsPort > 65535)) {
|
|
7375
|
-
throw new FerricStoreError("invalid SHARDS endpoint", { raw: item });
|
|
7376
|
-
}
|
|
7377
|
-
return {
|
|
7378
|
-
host,
|
|
7379
|
-
nativePort,
|
|
7380
|
-
node: textOrUndefined(getField(raw, "node", "leader_node", "owner_node")) ?? host,
|
|
7381
|
-
...nativeTlsPort == null ? {} : { nativeTlsPort }
|
|
7382
|
-
};
|
|
7383
|
-
}
|
|
7384
|
-
function validEndpointHost(host) {
|
|
7385
|
-
if (host.length === 0 || host.trim() !== host || /[\s\\/?#@]/u.test(host)) return false;
|
|
7386
|
-
const authorityHost = host.includes(":") && !host.startsWith("[") ? `[${host}]` : host;
|
|
7387
|
-
try {
|
|
7388
|
-
const url = new URL(`ferric://${authorityHost}:6388`);
|
|
7389
|
-
return url.hostname !== "" && url.port === "6388" && url.username === "" && url.password === "";
|
|
7390
|
-
} catch {
|
|
7391
|
-
return false;
|
|
7392
|
-
}
|
|
7393
|
-
}
|
|
7394
|
-
function sameEndpoint(left, right) {
|
|
7395
|
-
return normalizedEndpointHost(left.host) === normalizedEndpointHost(right.host) && left.nativePort === right.nativePort && left.nativeTlsPort === right.nativeTlsPort && left.node === right.node;
|
|
7396
|
-
}
|
|
7397
|
-
function parseFerricUrl2(value) {
|
|
7398
|
-
const url = new URL(value);
|
|
7399
|
-
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
7400
|
-
throw new FerricStoreError(`unsupported FerricStore URL scheme: ${url.protocol}`);
|
|
7401
|
-
}
|
|
7402
|
-
return {
|
|
7403
|
-
host: normalizeFerricUrlHost(url.hostname),
|
|
7404
|
-
...url.password === "" ? {} : { password: decodeURIComponent(url.password) },
|
|
7405
|
-
port: Number(url.port || (url.protocol === "ferrics:" ? 6389 : 6388)),
|
|
7406
|
-
tls: url.protocol === "ferrics:",
|
|
7407
|
-
...url.username === "" ? {} : { username: decodeURIComponent(url.username) }
|
|
7408
|
-
};
|
|
7409
|
-
}
|
|
7410
|
-
function endpointKeyFor(endpoint) {
|
|
7411
|
-
return `${normalizedEndpointHost(endpoint.host)}:${endpoint.nativePort}`;
|
|
7412
|
-
}
|
|
7413
|
-
function connectionKeyForEndpoint(endpoint, useTls) {
|
|
7414
|
-
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
7415
|
-
return `${useTls ? "ferrics" : "ferric"}://${normalizedEndpointHost(endpoint.host)}:${port}`;
|
|
7416
|
-
}
|
|
7417
|
-
function connectionKeyFromUrl(url) {
|
|
7418
|
-
const parsed = parseFerricUrl2(url);
|
|
7419
|
-
return `${parsed.tls ? "ferrics" : "ferric"}://${normalizedEndpointHost(parsed.host)}:${parsed.port}`;
|
|
7420
|
-
}
|
|
7421
|
-
function normalizedEndpointHost(host) {
|
|
7422
|
-
const lower = host.toLowerCase();
|
|
7423
|
-
return lower.startsWith("[") && lower.endsWith("]") ? lower.slice(1, -1) : lower;
|
|
7424
|
-
}
|
|
7425
|
-
function urlFromEndpoint(endpoint, useTls) {
|
|
7426
|
-
const port = useTls && endpoint.nativeTlsPort != null ? endpoint.nativeTlsPort : endpoint.nativePort;
|
|
7427
|
-
const host = endpoint.host.includes(":") && !endpoint.host.startsWith("[") ? `[${endpoint.host}]` : endpoint.host;
|
|
7428
|
-
return `${useTls ? "ferrics" : "ferric"}://${host}:${port}`;
|
|
7429
|
-
}
|
|
7430
|
-
async function mapSettledWithConcurrency(items, concurrency, operation) {
|
|
7431
|
-
const results = new Array(items.length);
|
|
7432
|
-
let nextIndex = 0;
|
|
7433
|
-
const worker = async () => {
|
|
7434
|
-
while (nextIndex < items.length) {
|
|
7435
|
-
const index = nextIndex++;
|
|
7436
|
-
const item = items[index];
|
|
7437
|
-
try {
|
|
7438
|
-
results[index] = { status: "fulfilled", value: await operation(item, index) };
|
|
7439
|
-
} catch (reason) {
|
|
7440
|
-
results[index] = { status: "rejected", reason };
|
|
7441
|
-
}
|
|
7442
|
-
}
|
|
7443
|
-
};
|
|
7444
|
-
await Promise.all(Array.from(
|
|
7445
|
-
{ length: Math.min(concurrency, items.length) },
|
|
7446
|
-
async () => await worker()
|
|
7447
|
-
));
|
|
7448
|
-
return results;
|
|
7449
|
-
}
|
|
7450
|
-
function throwFirstRejected(results) {
|
|
7451
|
-
for (const result of results) {
|
|
7452
|
-
if (result.status === "rejected") throw result.reason;
|
|
7453
|
-
}
|
|
7454
|
-
}
|
|
7455
|
-
var TaskConcurrencyLimiter = class {
|
|
7456
|
-
constructor(concurrency) {
|
|
7457
|
-
this.concurrency = concurrency;
|
|
7458
|
-
}
|
|
7459
|
-
concurrency;
|
|
7460
|
-
active = 0;
|
|
7461
|
-
head = 0;
|
|
7462
|
-
pending = [];
|
|
7463
|
-
async run(operation) {
|
|
7464
|
-
await this.acquire();
|
|
7465
|
-
try {
|
|
7466
|
-
return await operation();
|
|
7467
|
-
} finally {
|
|
7468
|
-
this.release();
|
|
7469
|
-
}
|
|
7470
|
-
}
|
|
7471
|
-
acquire() {
|
|
7472
|
-
if (this.active < this.concurrency) {
|
|
7473
|
-
this.active += 1;
|
|
7474
|
-
return Promise.resolve();
|
|
7475
|
-
}
|
|
7476
|
-
return new Promise((resolve) => this.pending.push(resolve));
|
|
7477
|
-
}
|
|
7478
|
-
release() {
|
|
7479
|
-
const next = this.pending[this.head];
|
|
7480
|
-
if (next == null) {
|
|
7481
|
-
this.active -= 1;
|
|
7482
|
-
return;
|
|
7483
|
-
}
|
|
7484
|
-
this.head += 1;
|
|
7485
|
-
next();
|
|
7486
|
-
if (this.head === this.pending.length) {
|
|
7487
|
-
this.pending.length = 0;
|
|
7488
|
-
this.head = 0;
|
|
7489
|
-
} else if (this.head >= 1024 && this.head * 2 >= this.pending.length) {
|
|
7490
|
-
this.pending.splice(0, this.head);
|
|
7491
|
-
this.head = 0;
|
|
7492
|
-
}
|
|
7493
|
-
}
|
|
7494
|
-
};
|
|
7495
|
-
function normalizedHostSet(hosts) {
|
|
7496
|
-
return new Set(
|
|
7497
|
-
hosts.filter((host) => host != null && host !== "").map((host) => normalizedEndpointHost(host))
|
|
7498
|
-
);
|
|
7499
|
-
}
|
|
7500
|
-
function bufferStartsWith(value, prefix) {
|
|
7501
|
-
return value.byteLength >= prefix.byteLength && value.subarray(0, prefix.byteLength).equals(prefix);
|
|
7502
|
-
}
|
|
7503
|
-
var OPEN_BRACE = "{".charCodeAt(0);
|
|
7504
|
-
var CLOSE_BRACE = "}".charCodeAt(0);
|
|
7505
|
-
function hashTagOrKey(key) {
|
|
7506
|
-
const start = key.indexOf(OPEN_BRACE);
|
|
7507
|
-
if (start < 0) return key;
|
|
7508
|
-
const end = key.indexOf(CLOSE_BRACE, start + 1);
|
|
7509
|
-
return end > start + 1 ? key.subarray(start + 1, end) : key;
|
|
7510
|
-
}
|
|
7511
|
-
function flowHashTag(rest, fallbackKey) {
|
|
7512
|
-
const end = rest.indexOf(CLOSE_BRACE);
|
|
7513
|
-
return end > 0 ? rest.subarray(0, end) : hashTagOrKey(fallbackKey);
|
|
7514
|
-
}
|
|
7515
|
-
var ROUTE_SLOT_MASK = 1023;
|
|
7516
|
-
var FLOW_KEY_PREFIX = Buffer25.from("f:{");
|
|
7517
|
-
var VALUE_REF_FLOW_KEY_PREFIX = Buffer25.from("X:f:{");
|
|
7518
|
-
function routingSlotForKey(key) {
|
|
7519
|
-
const keyBytes = Buffer25.isBuffer(key) ? key : Buffer25.from(key);
|
|
7520
|
-
let hashInput;
|
|
7521
|
-
if (bufferStartsWith(keyBytes, FLOW_KEY_PREFIX)) {
|
|
7522
|
-
hashInput = flowHashTag(keyBytes.subarray(FLOW_KEY_PREFIX.byteLength), keyBytes);
|
|
7523
|
-
} else if (bufferStartsWith(keyBytes, VALUE_REF_FLOW_KEY_PREFIX)) {
|
|
7524
|
-
hashInput = flowHashTag(keyBytes.subarray(VALUE_REF_FLOW_KEY_PREFIX.byteLength), keyBytes);
|
|
7525
|
-
} else {
|
|
7526
|
-
hashInput = hashTagOrKey(keyBytes);
|
|
7527
|
-
}
|
|
7528
|
-
return crc32(hashInput) & ROUTE_SLOT_MASK;
|
|
7529
|
-
}
|
|
7530
|
-
|
|
7531
|
-
// src/topology-routing.ts
|
|
7532
7794
|
var FLOW_PARTITION_ROUTE_CACHE_MAX = 1024;
|
|
7533
7795
|
var flowPartitionRouteCache = /* @__PURE__ */ new Map();
|
|
7534
7796
|
function routingKeyFromProtocolPayload(name, command) {
|
|
@@ -7536,9 +7798,18 @@ function routingKeyFromProtocolPayload(name, command) {
|
|
|
7536
7798
|
return void 0;
|
|
7537
7799
|
}
|
|
7538
7800
|
if (isPlainObject3(command.payload)) {
|
|
7539
|
-
for (const field2 of [
|
|
7801
|
+
for (const field2 of [
|
|
7802
|
+
"key",
|
|
7803
|
+
"partition_key",
|
|
7804
|
+
"id",
|
|
7805
|
+
"owner_flow_id",
|
|
7806
|
+
"parent_flow_id",
|
|
7807
|
+
"root_flow_id",
|
|
7808
|
+
"correlation_id",
|
|
7809
|
+
"scope"
|
|
7810
|
+
]) {
|
|
7540
7811
|
const value = getField(command.payload, field2);
|
|
7541
|
-
if (typeof value === "string" ||
|
|
7812
|
+
if (typeof value === "string" || Buffer28.isBuffer(value)) {
|
|
7542
7813
|
return value;
|
|
7543
7814
|
}
|
|
7544
7815
|
}
|
|
@@ -7585,9 +7856,9 @@ function flowRoutingData(name, args) {
|
|
|
7585
7856
|
if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
|
|
7586
7857
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
7587
7858
|
}
|
|
7588
|
-
if (
|
|
7589
|
-
const
|
|
7590
|
-
if (
|
|
7859
|
+
if (Buffer28.isBuffer(partition)) {
|
|
7860
|
+
const text3 = partition.toString("utf8").toUpperCase();
|
|
7861
|
+
if (text3 !== "AUTO" && text3 !== "MIXED") {
|
|
7591
7862
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
7592
7863
|
}
|
|
7593
7864
|
}
|
|
@@ -7676,22 +7947,22 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
|
|
|
7676
7947
|
return { handled: false };
|
|
7677
7948
|
}
|
|
7678
7949
|
function isRoutingKey(value) {
|
|
7679
|
-
return typeof value === "string" ||
|
|
7950
|
+
return typeof value === "string" || Buffer28.isBuffer(value);
|
|
7680
7951
|
}
|
|
7681
7952
|
function flowLogicalPartitionRoutingKey(value) {
|
|
7682
|
-
if (typeof value !== "string" && !
|
|
7953
|
+
if (typeof value !== "string" && !Buffer28.isBuffer(value)) {
|
|
7683
7954
|
return void 0;
|
|
7684
7955
|
}
|
|
7685
|
-
const bytes2 =
|
|
7686
|
-
const
|
|
7687
|
-
const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(
|
|
7956
|
+
const bytes2 = Buffer28.isBuffer(value) ? value : Buffer28.from(value);
|
|
7957
|
+
const text3 = bytes2.toString("utf8");
|
|
7958
|
+
const autoMatch = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(text3);
|
|
7688
7959
|
if (autoMatch != null) {
|
|
7689
7960
|
const bucket = Number(autoMatch[1]);
|
|
7690
7961
|
if (bucket < 256) {
|
|
7691
|
-
return `
|
|
7962
|
+
return `{fa:${bucket}}`;
|
|
7692
7963
|
}
|
|
7693
7964
|
}
|
|
7694
|
-
const cacheKey = `${
|
|
7965
|
+
const cacheKey = `${Buffer28.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
|
|
7695
7966
|
const cached = flowPartitionRouteCache.get(cacheKey);
|
|
7696
7967
|
if (cached != null) {
|
|
7697
7968
|
flowPartitionRouteCache.delete(cacheKey);
|
|
@@ -7699,7 +7970,7 @@ function flowLogicalPartitionRoutingKey(value) {
|
|
|
7699
7970
|
return cached;
|
|
7700
7971
|
}
|
|
7701
7972
|
const digest = createHash("sha256").update(bytes2).digest("base64url");
|
|
7702
|
-
const routeKey = `
|
|
7973
|
+
const routeKey = `{f:${digest}}`;
|
|
7703
7974
|
if (flowPartitionRouteCache.size >= FLOW_PARTITION_ROUTE_CACHE_MAX) {
|
|
7704
7975
|
const oldest = flowPartitionRouteCache.keys().next().value;
|
|
7705
7976
|
if (oldest != null) flowPartitionRouteCache.delete(oldest);
|
|
@@ -7708,18 +7979,17 @@ function flowLogicalPartitionRoutingKey(value) {
|
|
|
7708
7979
|
return routeKey;
|
|
7709
7980
|
}
|
|
7710
7981
|
function flowAutoIdRoutingKey(value) {
|
|
7711
|
-
if (typeof value !== "string" && !
|
|
7982
|
+
if (typeof value !== "string" && !Buffer28.isBuffer(value)) {
|
|
7712
7983
|
return void 0;
|
|
7713
7984
|
}
|
|
7714
|
-
const
|
|
7715
|
-
|
|
7716
|
-
return `f:{fa:${bucket}}:route`;
|
|
7985
|
+
const bucket = (Buffer28.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
|
|
7986
|
+
return `{fa:${bucket}}`;
|
|
7717
7987
|
}
|
|
7718
7988
|
function flowClaimLogicalPartitionRoutingKey(value) {
|
|
7719
|
-
if (typeof value !== "string" && !
|
|
7989
|
+
if (typeof value !== "string" && !Buffer28.isBuffer(value)) return void 0;
|
|
7720
7990
|
const selector = commandPart(value);
|
|
7721
7991
|
if (selector === "AUTO" || selector === "ANY") return void 0;
|
|
7722
|
-
if (selector === "GLOBAL") return "
|
|
7992
|
+
if (selector === "GLOBAL") return "{f}";
|
|
7723
7993
|
return flowLogicalPartitionRoutingKey(value);
|
|
7724
7994
|
}
|
|
7725
7995
|
function singleShardFlowPartitionKey(values) {
|
|
@@ -7731,7 +8001,7 @@ function singleShardFlowClaimPartitionKey(values) {
|
|
|
7731
8001
|
return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
|
|
7732
8002
|
}
|
|
7733
8003
|
function singleShardKey(keys) {
|
|
7734
|
-
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !
|
|
8004
|
+
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !Buffer28.isBuffer(key))) {
|
|
7735
8005
|
return void 0;
|
|
7736
8006
|
}
|
|
7737
8007
|
const usable = keys;
|
|
@@ -7764,7 +8034,7 @@ function routedKeyGroups(keys, routeKey) {
|
|
|
7764
8034
|
const groups = /* @__PURE__ */ new Map();
|
|
7765
8035
|
for (let index = 0; index < keys.length; index += 1) {
|
|
7766
8036
|
const key = keys[index];
|
|
7767
|
-
if (typeof key !== "string" && !
|
|
8037
|
+
if (typeof key !== "string" && !Buffer28.isBuffer(key)) return void 0;
|
|
7768
8038
|
const route = routeKey(key);
|
|
7769
8039
|
const groupKey = `${route.endpointKey}\0${route.laneId}`;
|
|
7770
8040
|
const group = groups.get(groupKey);
|
|
@@ -8005,7 +8275,16 @@ function isExplicitlySafeReroute(error) {
|
|
|
8005
8275
|
if (error instanceof ConnectionClosedError) {
|
|
8006
8276
|
return error.requestDisposition === "unsent";
|
|
8007
8277
|
}
|
|
8008
|
-
return error instanceof RerouteError &&
|
|
8278
|
+
return error instanceof RerouteError && error.retryable === true && error.safeToRetry === true;
|
|
8279
|
+
}
|
|
8280
|
+
function retryAfterMs(error) {
|
|
8281
|
+
return error instanceof FerricStoreError ? error.retryAfterMs ?? 0 : 0;
|
|
8282
|
+
}
|
|
8283
|
+
async function waitForExplicitlySafeReroute(error) {
|
|
8284
|
+
if (!isExplicitlySafeReroute(error)) return false;
|
|
8285
|
+
const delayMs = retryAfterMs(error);
|
|
8286
|
+
if (delayMs > 0) await sleep(delayMs);
|
|
8287
|
+
return true;
|
|
8009
8288
|
}
|
|
8010
8289
|
|
|
8011
8290
|
// src/topology-endpoint-trust.ts
|
|
@@ -8739,7 +9018,9 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8739
9018
|
() => true,
|
|
8740
9019
|
() => false
|
|
8741
9020
|
);
|
|
8742
|
-
|
|
9021
|
+
if (!refreshed || !await waitForExplicitlySafeReroute(error)) return false;
|
|
9022
|
+
this.assertOpen();
|
|
9023
|
+
return true;
|
|
8743
9024
|
}
|
|
8744
9025
|
async executePipelineOnRoute(commands, route, options) {
|
|
8745
9026
|
const adapter = await this.adapterForCurrentRoute(route);
|
|
@@ -8829,7 +9110,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8829
9110
|
};
|
|
8830
9111
|
|
|
8831
9112
|
// src/response-map-preservation.ts
|
|
8832
|
-
import { Buffer as
|
|
9113
|
+
import { Buffer as Buffer30 } from "buffer";
|
|
8833
9114
|
function toStringKeyMapPreservingValues(value) {
|
|
8834
9115
|
if (value == null) return void 0;
|
|
8835
9116
|
const result = {};
|
|
@@ -8839,7 +9120,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
8839
9120
|
}
|
|
8840
9121
|
return result;
|
|
8841
9122
|
}
|
|
8842
|
-
if (typeof value === "object" && !Array.isArray(value) && !
|
|
9123
|
+
if (typeof value === "object" && !Array.isArray(value) && !Buffer30.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
8843
9124
|
for (const [key, item] of Object.entries(value)) {
|
|
8844
9125
|
setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
|
|
8845
9126
|
}
|
|
@@ -8848,7 +9129,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
8848
9129
|
return void 0;
|
|
8849
9130
|
}
|
|
8850
9131
|
function normalizeMapStructurePreservingBytes(value) {
|
|
8851
|
-
if (
|
|
9132
|
+
if (Buffer30.isBuffer(value) || value instanceof Uint8Array) return value;
|
|
8852
9133
|
if (value instanceof Map) {
|
|
8853
9134
|
const result = {};
|
|
8854
9135
|
for (const [key, item] of value.entries()) {
|
|
@@ -8870,7 +9151,7 @@ function normalizeMapStructurePreservingBytes(value) {
|
|
|
8870
9151
|
}
|
|
8871
9152
|
|
|
8872
9153
|
// src/native-kv-responses.ts
|
|
8873
|
-
import { Buffer as
|
|
9154
|
+
import { Buffer as Buffer31 } from "buffer";
|
|
8874
9155
|
function rateLimitResultFromResp(value) {
|
|
8875
9156
|
if (!Array.isArray(value) || value.length !== 4) {
|
|
8876
9157
|
throw new TypeError("RATELIMIT.ADD returned an unexpected response");
|
|
@@ -8913,30 +9194,27 @@ function fetchOrComputeResultFromResp(value, codec) {
|
|
|
8913
9194
|
shouldCompute: false
|
|
8914
9195
|
};
|
|
8915
9196
|
}
|
|
8916
|
-
if (status !== "compute"
|
|
9197
|
+
if (status !== "compute" || value.length !== 3) {
|
|
9198
|
+
throw new TypeError("FETCH_OR_COMPUTE returned an unexpected response");
|
|
9199
|
+
}
|
|
8917
9200
|
return {
|
|
8918
9201
|
status,
|
|
8919
9202
|
computeHint: responseBytes(value[1], "FETCH_OR_COMPUTE"),
|
|
8920
|
-
|
|
8921
|
-
|
|
8922
|
-
computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE")
|
|
8923
|
-
} : {
|
|
8924
|
-
computeMode: "legacy",
|
|
8925
|
-
computeToken: null
|
|
8926
|
-
},
|
|
9203
|
+
computeMode: "fenced",
|
|
9204
|
+
computeToken: responseBytes(value[2], "FETCH_OR_COMPUTE"),
|
|
8927
9205
|
hit: false,
|
|
8928
9206
|
shouldCompute: true
|
|
8929
9207
|
};
|
|
8930
9208
|
}
|
|
8931
9209
|
function decodePayload(codec, value) {
|
|
8932
9210
|
if (value == null) return null;
|
|
8933
|
-
if (
|
|
8934
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
8935
|
-
if (typeof value === "string") return codec.decode(
|
|
9211
|
+
if (Buffer31.isBuffer(value)) return codec.decode(value);
|
|
9212
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer31.from(value));
|
|
9213
|
+
if (typeof value === "string") return codec.decode(Buffer31.from(value));
|
|
8936
9214
|
return normalizeRefMeta(value);
|
|
8937
9215
|
}
|
|
8938
9216
|
function requiredResponseString(value, context) {
|
|
8939
|
-
if (typeof value !== "string" && !
|
|
9217
|
+
if (typeof value !== "string" && !Buffer31.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
8940
9218
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
8941
9219
|
}
|
|
8942
9220
|
const result = text(value);
|
|
@@ -8953,7 +9231,7 @@ function requiredNonNegativeInteger(value, context) {
|
|
|
8953
9231
|
return result;
|
|
8954
9232
|
}
|
|
8955
9233
|
function responseBytes(value, context) {
|
|
8956
|
-
if (typeof value !== "string" && !
|
|
9234
|
+
if (typeof value !== "string" && !Buffer31.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
8957
9235
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
8958
9236
|
}
|
|
8959
9237
|
return bytes(value);
|
|
@@ -9038,6 +9316,9 @@ function flowRecordFromResp(value, codec) {
|
|
|
9038
9316
|
field(value, "max_active_ms"),
|
|
9039
9317
|
"FLOW record max_active_ms"
|
|
9040
9318
|
);
|
|
9319
|
+
const rawError = field(value, "error");
|
|
9320
|
+
const error = flowError(rawError, codec);
|
|
9321
|
+
const failureReason = optionalResponseString(field(rawError, "reason"), "FLOW record error reason");
|
|
9041
9322
|
return {
|
|
9042
9323
|
id: requiredTextField(value, "id", "FLOW record"),
|
|
9043
9324
|
type: requiredTextField(value, "type", "FLOW record"),
|
|
@@ -9052,6 +9333,8 @@ function flowRecordFromResp(value, codec) {
|
|
|
9052
9333
|
rootFlowId: optionalResponseString(field(value, "root_flow_id"), "FLOW record root_flow_id"),
|
|
9053
9334
|
correlationId: optionalResponseString(field(value, "correlation_id"), "FLOW record correlation_id"),
|
|
9054
9335
|
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
9336
|
+
...error == null ? {} : { error },
|
|
9337
|
+
...failureReason == null ? {} : { failureReason },
|
|
9055
9338
|
valueRefs: optionalMapField(value, "value_refs", "FLOW record"),
|
|
9056
9339
|
values,
|
|
9057
9340
|
valueSizes: optionalMapField(value, "value_sizes", "FLOW record"),
|
|
@@ -9063,6 +9346,21 @@ function flowRecordFromResp(value, codec) {
|
|
|
9063
9346
|
raw: value
|
|
9064
9347
|
};
|
|
9065
9348
|
}
|
|
9349
|
+
function flowError(value, codec) {
|
|
9350
|
+
if (value == null) return void 0;
|
|
9351
|
+
const reason = optionalResponseString(field(value, "reason"), "FLOW record error reason");
|
|
9352
|
+
if (reason === "max_active_ms") {
|
|
9353
|
+
const maxActiveMs = optionalPositiveResponseInteger(
|
|
9354
|
+
field(value, "max_active_ms"),
|
|
9355
|
+
"FLOW record error max_active_ms"
|
|
9356
|
+
);
|
|
9357
|
+
if (maxActiveMs == null) {
|
|
9358
|
+
throw new TypeError("FLOW record error max_active_ms returned an unexpected response");
|
|
9359
|
+
}
|
|
9360
|
+
return { maxActiveMs, reason };
|
|
9361
|
+
}
|
|
9362
|
+
return decodePayload2(codec, value);
|
|
9363
|
+
}
|
|
9066
9364
|
function decodePayload2(codec, value) {
|
|
9067
9365
|
if (value == null) {
|
|
9068
9366
|
return null;
|
|
@@ -9643,7 +9941,7 @@ function groupAutoPartitionItems(items) {
|
|
|
9643
9941
|
}
|
|
9644
9942
|
|
|
9645
9943
|
// src/client-values.ts
|
|
9646
|
-
import { Buffer as
|
|
9944
|
+
import { Buffer as Buffer32 } from "buffer";
|
|
9647
9945
|
async function valueMGetEntries(client, refs, options = {}) {
|
|
9648
9946
|
const refCount = refs.length;
|
|
9649
9947
|
if (refCount === 0) {
|
|
@@ -9678,12 +9976,12 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9678
9976
|
const item = response[index];
|
|
9679
9977
|
if (item == null) {
|
|
9680
9978
|
entries[index] = { found: false };
|
|
9681
|
-
} else if (
|
|
9979
|
+
} else if (Buffer32.isBuffer(item)) {
|
|
9682
9980
|
entries[index] = { found: true, value: client.codec.decode(item) };
|
|
9683
9981
|
} else if (item instanceof Uint8Array) {
|
|
9684
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
9982
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer32.from(item)) };
|
|
9685
9983
|
} else if (typeof item === "string") {
|
|
9686
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
9984
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer32.from(item)) };
|
|
9687
9985
|
} else {
|
|
9688
9986
|
entries[index] = { found: true, value: item };
|
|
9689
9987
|
}
|
|
@@ -9695,7 +9993,7 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9695
9993
|
import "buffer";
|
|
9696
9994
|
|
|
9697
9995
|
// src/auto-batch-ordering.ts
|
|
9698
|
-
import { Buffer as
|
|
9996
|
+
import { Buffer as Buffer33 } from "buffer";
|
|
9699
9997
|
function autoBatchOrderingPlan(batch) {
|
|
9700
9998
|
const accesses = /* @__PURE__ */ new Map();
|
|
9701
9999
|
const fallbackDependencies = [];
|
|
@@ -9810,13 +10108,13 @@ function flowManyAutoBatchIds(command, name) {
|
|
|
9810
10108
|
return fixedFlowItemIds(
|
|
9811
10109
|
command,
|
|
9812
10110
|
mixed ? 4 : 3,
|
|
9813
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) &&
|
|
10111
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && Buffer33.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
|
|
9814
10112
|
);
|
|
9815
10113
|
}
|
|
9816
10114
|
return fixedFlowItemIds(
|
|
9817
10115
|
command,
|
|
9818
10116
|
mixed ? 4 : 3,
|
|
9819
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10117
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer33.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
|
|
9820
10118
|
);
|
|
9821
10119
|
}
|
|
9822
10120
|
function createManyAutoBatchIds(command) {
|
|
@@ -9829,7 +10127,7 @@ function createManyAutoBatchIds(command) {
|
|
|
9829
10127
|
const ids = fixedFlowItemIds(
|
|
9830
10128
|
command,
|
|
9831
10129
|
width,
|
|
9832
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10130
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer33.isBuffer(command[itemIndex + width - 1]),
|
|
9833
10131
|
markerIndex
|
|
9834
10132
|
);
|
|
9835
10133
|
if (ids != null) return ids;
|
|
@@ -9847,7 +10145,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
|
|
|
9847
10145
|
let cursor = markerIndex + 2;
|
|
9848
10146
|
for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
|
|
9849
10147
|
const id = command[cursor];
|
|
9850
|
-
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !
|
|
10148
|
+
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !Buffer33.isBuffer(command[cursor + 2])) return void 0;
|
|
9851
10149
|
ids.push(id);
|
|
9852
10150
|
cursor += 3;
|
|
9853
10151
|
const afterValues = skipExtendedNamedItems(command, cursor, true);
|
|
@@ -9866,7 +10164,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
|
|
|
9866
10164
|
for (let index = 0; index < count; index += 1) {
|
|
9867
10165
|
const name = command[firstItem + index * 2];
|
|
9868
10166
|
const value = command[firstItem + index * 2 + 1];
|
|
9869
|
-
if (!isAutoBatchResourceValue(name) || (encodedValues ? !
|
|
10167
|
+
if (!isAutoBatchResourceValue(name) || (encodedValues ? !Buffer33.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
|
|
9870
10168
|
}
|
|
9871
10169
|
return firstItem + count * 2;
|
|
9872
10170
|
}
|
|
@@ -9881,7 +10179,7 @@ function runStepsManyAutoBatchIds(command) {
|
|
|
9881
10179
|
ids.push(item);
|
|
9882
10180
|
continue;
|
|
9883
10181
|
}
|
|
9884
|
-
if (typeof item !== "object" || item == null || Array.isArray(item) ||
|
|
10182
|
+
if (typeof item !== "object" || item == null || Array.isArray(item) || Buffer33.isBuffer(item)) return void 0;
|
|
9885
10183
|
const id = item.id;
|
|
9886
10184
|
if (!isAutoBatchResourceValue(id)) return void 0;
|
|
9887
10185
|
ids.push(id);
|
|
@@ -9922,7 +10220,7 @@ function flowValuePutOwner(command, start) {
|
|
|
9922
10220
|
}
|
|
9923
10221
|
var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
|
|
9924
10222
|
function isAutoBatchResourceValue(value) {
|
|
9925
|
-
return typeof value === "string" ||
|
|
10223
|
+
return typeof value === "string" || Buffer33.isBuffer(value);
|
|
9926
10224
|
}
|
|
9927
10225
|
function isFencingToken(value) {
|
|
9928
10226
|
return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
|
|
@@ -9931,7 +10229,7 @@ function nonNegativeItemCount(value) {
|
|
|
9931
10229
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
9932
10230
|
}
|
|
9933
10231
|
function autoBatchResourceKey(namespace, value) {
|
|
9934
|
-
return `${namespace}:${
|
|
10232
|
+
return `${namespace}:${Buffer33.from(value).toString("base64")}`;
|
|
9935
10233
|
}
|
|
9936
10234
|
function autoBatchCommandName(command) {
|
|
9937
10235
|
return commandView(command).name ?? null;
|
|
@@ -10346,9 +10644,9 @@ import "buffer";
|
|
|
10346
10644
|
import "buffer";
|
|
10347
10645
|
|
|
10348
10646
|
// src/client-core-helpers.ts
|
|
10349
|
-
import { Buffer as
|
|
10647
|
+
import { Buffer as Buffer35 } from "buffer";
|
|
10350
10648
|
function bgsaveResponse(response) {
|
|
10351
|
-
if ((typeof response === "string" ||
|
|
10649
|
+
if ((typeof response === "string" || Buffer35.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
|
|
10352
10650
|
return true;
|
|
10353
10651
|
}
|
|
10354
10652
|
return okResponse(response);
|
|
@@ -10359,11 +10657,11 @@ function clientNameResponse(response) {
|
|
|
10359
10657
|
function fetchOrComputeCompletionToken(options) {
|
|
10360
10658
|
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
10361
10659
|
throw new TypeError(
|
|
10362
|
-
"fetch-or-compute completion requires computeToken
|
|
10660
|
+
"fetch-or-compute completion requires computeToken"
|
|
10363
10661
|
);
|
|
10364
10662
|
}
|
|
10365
|
-
if (
|
|
10366
|
-
throw new TypeError("fetch-or-compute computeToken must be a Buffer
|
|
10663
|
+
if (!Buffer35.isBuffer(options.computeToken)) {
|
|
10664
|
+
throw new TypeError("fetch-or-compute computeToken must be a Buffer");
|
|
10367
10665
|
}
|
|
10368
10666
|
return options.computeToken;
|
|
10369
10667
|
}
|
|
@@ -10485,14 +10783,17 @@ var FerricStoreClientBase = class {
|
|
|
10485
10783
|
};
|
|
10486
10784
|
}
|
|
10487
10785
|
async command(...args) {
|
|
10786
|
+
assertAtomicKeyValueCommandSharesSlot(args);
|
|
10488
10787
|
return await executeCommandArgs(this.executor, args);
|
|
10489
10788
|
}
|
|
10490
10789
|
/** Execute an already-built command without a JavaScript variadic-call limit. */
|
|
10491
10790
|
async commandArgs(args) {
|
|
10791
|
+
assertAtomicKeyValueCommandSharesSlot(args);
|
|
10492
10792
|
return await executeCommandArgs(this.executor, args);
|
|
10493
10793
|
}
|
|
10494
10794
|
async pipeline(commands, options) {
|
|
10495
10795
|
const snapshot = snapshotPipelineCommands(commands);
|
|
10796
|
+
for (const command of snapshot) assertAtomicKeyValueCommandSharesSlot(command);
|
|
10496
10797
|
const snapshotOptions = snapshotPipelineOptions(options);
|
|
10497
10798
|
const results = this.executor.executePipeline != null ? await this.executor.executePipeline(snapshot, snapshotOptions) : await executeCommandArraysIndividually(
|
|
10498
10799
|
async (command) => await this.commandArgs(command),
|
|
@@ -10719,14 +11020,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
|
|
|
10719
11020
|
};
|
|
10720
11021
|
|
|
10721
11022
|
// src/store-utilities.ts
|
|
10722
|
-
import { Buffer as
|
|
11023
|
+
import { Buffer as Buffer38 } from "buffer";
|
|
10723
11024
|
function encode(codec, value) {
|
|
10724
11025
|
return codec.encode(value);
|
|
10725
11026
|
}
|
|
10726
11027
|
function decode(codec, value) {
|
|
10727
11028
|
if (value == null) return null;
|
|
10728
|
-
if (
|
|
10729
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
11029
|
+
if (Buffer38.isBuffer(value)) return codec.decode(value);
|
|
11030
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer38.from(value));
|
|
10730
11031
|
return value;
|
|
10731
11032
|
}
|
|
10732
11033
|
function number(value) {
|
|
@@ -11132,12 +11433,15 @@ var TopKStore = class {
|
|
|
11132
11433
|
const width = ownOption(options, "width");
|
|
11133
11434
|
const depth = ownOption(options, "depth");
|
|
11134
11435
|
const decay = ownOption(options, "decay");
|
|
11135
|
-
|
|
11136
|
-
|
|
11137
|
-
throw new TypeError("TOPK.RESERVE width, depth, and decay must be provided together");
|
|
11436
|
+
if (decay != null || Object.hasOwn(options, "decay")) {
|
|
11437
|
+
throw new TypeError("TOPK.RESERVE decay is not supported by FerricStore 0.8");
|
|
11138
11438
|
}
|
|
11139
|
-
|
|
11140
|
-
|
|
11439
|
+
const tuningCount = [width, depth].filter((value) => value != null).length;
|
|
11440
|
+
if (tuningCount !== 0 && tuningCount !== 2) {
|
|
11441
|
+
throw new TypeError("TOPK.RESERVE width and depth must be provided together");
|
|
11442
|
+
}
|
|
11443
|
+
if (tuningCount === 2) {
|
|
11444
|
+
args.push(width, depth);
|
|
11141
11445
|
}
|
|
11142
11446
|
return okResponse(await commandArgs(this.client, args));
|
|
11143
11447
|
}
|
|
@@ -11543,10 +11847,14 @@ var KeyValueStore = class {
|
|
|
11543
11847
|
);
|
|
11544
11848
|
}
|
|
11545
11849
|
async mset(entries) {
|
|
11546
|
-
|
|
11850
|
+
const args = keyValueArgs(["MSET"], this.client.codec, entries);
|
|
11851
|
+
assertKeyValueCommandSharesSlot(args, "MSET");
|
|
11852
|
+
return okResponse(await commandArgs(this.client, args));
|
|
11547
11853
|
}
|
|
11548
11854
|
async msetnx(entries) {
|
|
11549
|
-
|
|
11855
|
+
const args = keyValueArgs(["MSETNX"], this.client.codec, entries);
|
|
11856
|
+
assertKeyValueCommandSharesSlot(args, "MSETNX");
|
|
11857
|
+
return binaryBooleanResponse(await commandArgs(this.client, args));
|
|
11550
11858
|
}
|
|
11551
11859
|
async incr(key) {
|
|
11552
11860
|
return integerReply(await this.client.command("INCR", key));
|
|
@@ -12616,7 +12924,8 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
|
|
|
12616
12924
|
return okResponse(await this.command(
|
|
12617
12925
|
"FETCH_OR_COMPUTE_RESULT",
|
|
12618
12926
|
key,
|
|
12619
|
-
|
|
12927
|
+
computeToken,
|
|
12928
|
+
encoded,
|
|
12620
12929
|
options.ttlMs
|
|
12621
12930
|
));
|
|
12622
12931
|
}
|
|
@@ -12625,7 +12934,7 @@ var FerricStoreClientCore = class extends FerricStoreAdministrationClient {
|
|
|
12625
12934
|
return okResponse(await this.command(
|
|
12626
12935
|
"FETCH_OR_COMPUTE_ERROR",
|
|
12627
12936
|
key,
|
|
12628
|
-
|
|
12937
|
+
computeToken,
|
|
12629
12938
|
message
|
|
12630
12939
|
));
|
|
12631
12940
|
}
|
|
@@ -12751,7 +13060,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
12751
13060
|
}
|
|
12752
13061
|
async effectGet(id, effectKey, options = {}) {
|
|
12753
13062
|
const args = ["FLOW.EFFECT.GET", id, "EFFECT_KEY", effectKey];
|
|
12754
|
-
append(args, "PARTITION", options.partitionKey
|
|
13063
|
+
append(args, "PARTITION", options.partitionKey);
|
|
12755
13064
|
return optionalAdminRecord(await this.commandArgs(args), "FLOW.EFFECT.GET");
|
|
12756
13065
|
}
|
|
12757
13066
|
async effectStatus(command, id, effectKey, options) {
|
|
@@ -12923,7 +13232,7 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
12923
13232
|
}
|
|
12924
13233
|
async governanceLedger(id, options = {}) {
|
|
12925
13234
|
const args = ["FLOW.GOVERNANCE.LEDGER", id];
|
|
12926
|
-
append(args, "PARTITION", options.partitionKey
|
|
13235
|
+
append(args, "PARTITION", options.partitionKey);
|
|
12927
13236
|
append(args, "LIMIT", options.limit);
|
|
12928
13237
|
append(args, "FROM_MS", options.fromMs);
|
|
12929
13238
|
append(args, "TO_MS", options.toMs);
|
|
@@ -12939,7 +13248,7 @@ async function executeProducerWriteWithBackpressure(execute, policy, signal) {
|
|
|
12939
13248
|
try {
|
|
12940
13249
|
return await execute();
|
|
12941
13250
|
} catch (error) {
|
|
12942
|
-
if (!(error instanceof OverloadedError) || attempt >= policy.maxRetries) throw error;
|
|
13251
|
+
if (!(error instanceof OverloadedError) || error.retryable !== true || error.safeToRetry !== true || attempt >= policy.maxRetries) throw error;
|
|
12943
13252
|
const exponential = Math.min(policy.maxDelayMs, policy.baseDelayMs * 2 ** attempt);
|
|
12944
13253
|
const base = Math.min(policy.maxDelayMs, error.retryAfterMs ?? exponential);
|
|
12945
13254
|
const jitter = base * (policy.jitterPct / 100) * Math.random();
|
|
@@ -13204,7 +13513,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13204
13513
|
};
|
|
13205
13514
|
|
|
13206
13515
|
// src/flow-many-snapshot.ts
|
|
13207
|
-
import { Buffer as
|
|
13516
|
+
import { Buffer as Buffer41 } from "buffer";
|
|
13208
13517
|
var encodedOptionFields = ["error", "payload", "reason", "result"];
|
|
13209
13518
|
function snapshotCreateItem(item, codec) {
|
|
13210
13519
|
const snapshot = {
|
|
@@ -13244,7 +13553,7 @@ function snapshotFlowManyOptions(options, codec) {
|
|
|
13244
13553
|
}
|
|
13245
13554
|
function snapshotClaimedItem(item) {
|
|
13246
13555
|
const wire = item[CLAIMED_ITEM_WIRE];
|
|
13247
|
-
const leaseToken =
|
|
13556
|
+
const leaseToken = Buffer41.from(wire?.leaseToken ?? item.leaseToken);
|
|
13248
13557
|
const snapshot = {
|
|
13249
13558
|
...item,
|
|
13250
13559
|
fencingToken: wire?.fencingToken ?? item.fencingToken,
|
|
@@ -13261,15 +13570,15 @@ function snapshotClaimedItem(item) {
|
|
|
13261
13570
|
function snapshotFencedItem(item) {
|
|
13262
13571
|
return Object.freeze({
|
|
13263
13572
|
...item,
|
|
13264
|
-
...item.leaseToken == null ? {} : { leaseToken:
|
|
13573
|
+
...item.leaseToken == null ? {} : { leaseToken: Buffer41.from(item.leaseToken) }
|
|
13265
13574
|
});
|
|
13266
13575
|
}
|
|
13267
13576
|
function snapshotClaimedItemWire(wire, leaseToken) {
|
|
13268
13577
|
return Object.freeze({
|
|
13269
13578
|
fencingToken: wire.fencingToken,
|
|
13270
|
-
id:
|
|
13579
|
+
id: Buffer41.from(wire.id),
|
|
13271
13580
|
leaseToken,
|
|
13272
|
-
partitionKey: wire.partitionKey == null ? wire.partitionKey :
|
|
13581
|
+
partitionKey: wire.partitionKey == null ? wire.partitionKey : Buffer41.from(wire.partitionKey)
|
|
13273
13582
|
});
|
|
13274
13583
|
}
|
|
13275
13584
|
function snapshotArray(values) {
|
|
@@ -13280,7 +13589,7 @@ function snapshotArray(values) {
|
|
|
13280
13589
|
return Object.freeze(snapshot);
|
|
13281
13590
|
}
|
|
13282
13591
|
function snapshotStateMeta(stateMeta) {
|
|
13283
|
-
return snapshotRecord(stateMeta, (value) =>
|
|
13592
|
+
return snapshotRecord(stateMeta, (value) => Buffer41.isBuffer(value) ? Buffer41.from(value) : value);
|
|
13284
13593
|
}
|
|
13285
13594
|
function snapshotCommandRecord(values) {
|
|
13286
13595
|
const seen = /* @__PURE__ */ new WeakMap();
|
|
@@ -13298,7 +13607,7 @@ function snapshotRecord(values, capture) {
|
|
|
13298
13607
|
}
|
|
13299
13608
|
function snapshotCommandArgument(value, seen) {
|
|
13300
13609
|
if (typeof value !== "object" || value == null) return value;
|
|
13301
|
-
if (
|
|
13610
|
+
if (Buffer41.isBuffer(value) || value instanceof Uint8Array) return Buffer41.from(value);
|
|
13302
13611
|
const objectValue = value;
|
|
13303
13612
|
const existing = seen.get(objectValue);
|
|
13304
13613
|
if (existing != null) return existing;
|
|
@@ -14096,6 +14405,9 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14096
14405
|
return new _FerricStoreClient(executor, clientOptions);
|
|
14097
14406
|
}
|
|
14098
14407
|
async valuePut(value, options = {}) {
|
|
14408
|
+
if (options.ownerFlowId != null && options.name != null && options.ttlMs != null) {
|
|
14409
|
+
throw new TypeError("named Flow values cannot have a TTL");
|
|
14410
|
+
}
|
|
14099
14411
|
const args = ["FLOW.VALUE.PUT", this.codec.encode(value), "NOW", options.nowMs ?? nowMs()];
|
|
14100
14412
|
append(args, "PARTITION", options.partitionKey);
|
|
14101
14413
|
append(args, "OWNER_FLOW_ID", options.ownerFlowId);
|
|
@@ -14127,7 +14439,6 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14127
14439
|
append(args, "TRANSITION_TO", options.transitionTo);
|
|
14128
14440
|
append(args, "RUN_AT", options.runAtMs);
|
|
14129
14441
|
append(args, "NOW", options.nowMs ?? nowMs());
|
|
14130
|
-
append(args, "PRIORITY", options.priority);
|
|
14131
14442
|
appendNamedValues(args, this.codec, options);
|
|
14132
14443
|
return await this.commandArgs(args);
|
|
14133
14444
|
}
|
|
@@ -14157,6 +14468,7 @@ var FerricStoreClient = class _FerricStoreClient extends FerricStoreProducerClie
|
|
|
14157
14468
|
append(args, "CORRELATION_ID", options.correlationId);
|
|
14158
14469
|
append(args, "PRIORITY", options.priority);
|
|
14159
14470
|
append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
14471
|
+
append(args, "MAX_ACTIVE_MS", options.maxActiveMs);
|
|
14160
14472
|
appendAttributes(args, options.attributes);
|
|
14161
14473
|
appendStateMeta(args, options.stateMeta);
|
|
14162
14474
|
appendNamedValues(args, this.codec, options);
|
|
@@ -16262,15 +16574,22 @@ var WorkflowWorker = class {
|
|
|
16262
16574
|
);
|
|
16263
16575
|
}
|
|
16264
16576
|
};
|
|
16577
|
+
|
|
16578
|
+
// src/version.ts
|
|
16579
|
+
var FERRICSTORE_SDK_VERSION = "0.2.0";
|
|
16580
|
+
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.8.0";
|
|
16581
|
+
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
16265
16582
|
export {
|
|
16266
16583
|
BitmapStore,
|
|
16267
16584
|
BloomFilterStore,
|
|
16268
16585
|
COMMAND_OPCODES,
|
|
16269
|
-
COMPACT_RESPONSE_OPCODES,
|
|
16270
16586
|
ClaimHydrationError,
|
|
16271
16587
|
ConnectionClosedError,
|
|
16272
16588
|
CountMinSketchStore,
|
|
16273
16589
|
CuckooFilterStore,
|
|
16590
|
+
FERRICSTORE_MINIMUM_SERVER_VERSION,
|
|
16591
|
+
FERRICSTORE_NATIVE_PROTOCOL_VERSION,
|
|
16592
|
+
FERRICSTORE_SDK_VERSION,
|
|
16274
16593
|
FerricStoreClient,
|
|
16275
16594
|
FerricStoreError,
|
|
16276
16595
|
FlowAlreadyExistsError,
|