@ferricstore/ferricstore 0.2.0 → 0.5.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 +72 -3
- package/dist/index.cjs +2618 -554
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +247 -33
- package/dist/index.d.ts +247 -33
- package/dist/index.js +2621 -562
- 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 -5
- package/docs/api/classes/ConnectionClosedError.html +5 -5
- package/docs/api/classes/FerricStoreClient.html +7 -3
- package/docs/api/classes/FerricStoreError.html +5 -5
- package/docs/api/classes/FlowAlreadyExistsError.html +5 -5
- package/docs/api/classes/FlowBatchError.html +5 -5
- package/docs/api/classes/FlowNotFoundError.html +5 -5
- package/docs/api/classes/FlowQueryError.html +42 -0
- package/docs/api/classes/FlowWrongStateError.html +5 -5
- package/docs/api/classes/InvalidCommandError.html +5 -5
- package/docs/api/classes/LeaseRenewalError.html +5 -5
- package/docs/api/classes/LockHeldError.html +5 -5
- package/docs/api/classes/LockNotOwnedError.html +5 -5
- package/docs/api/classes/NativeAdapter.html +3 -3
- package/docs/api/classes/OverloadedError.html +5 -5
- package/docs/api/classes/QueueCompletionError.html +5 -5
- package/docs/api/classes/ReconnectingExecutor.html +4 -4
- package/docs/api/classes/RequestTimeoutError.html +5 -5
- package/docs/api/classes/RerouteError.html +5 -5
- package/docs/api/classes/StaleLeaseError.html +5 -5
- package/docs/api/classes/StalePolicyGenerationError.html +39 -0
- package/docs/api/classes/TopologyNativeAdapterPool.html +3 -3
- package/docs/api/classes/Workflow.html +1 -1
- package/docs/api/classes/WorkflowWorker.html +2 -2
- package/docs/api/functions/classifyServerError.html +1 -1
- package/docs/api/functions/isReconnectableClosedConnectionError.html +1 -1
- package/docs/api/functions/mapException.html +1 -1
- package/docs/api/functions/projectFlowQuery.html +1 -0
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +36 -5
- package/docs/api/interfaces/AdminListOptions.html +1 -1
- package/docs/api/interfaces/CancelOptions.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/FlowEventProjectionField.html +4 -0
- package/docs/api/interfaces/FlowExplainResult.html +10 -0
- package/docs/api/interfaces/FlowPolicyBackoffSnapshot.html +5 -0
- package/docs/api/interfaces/FlowPolicyOptions.html +8 -4
- package/docs/api/interfaces/FlowPolicyRetentionSnapshot.html +3 -0
- package/docs/api/interfaces/FlowPolicyRetrySnapshot.html +4 -0
- package/docs/api/interfaces/FlowPolicySnapshot.html +17 -0
- package/docs/api/interfaces/FlowPolicyStateSnapshot.html +6 -0
- package/docs/api/interfaces/FlowQueryCountResult.html +7 -0
- package/docs/api/interfaces/FlowQueryErrorPosition.html +4 -0
- package/docs/api/interfaces/FlowQueryIndex.html +9 -0
- package/docs/api/interfaces/FlowQueryIndexFormat.html +7 -0
- package/docs/api/interfaces/FlowQueryIndexRegistry.html +3 -0
- package/docs/api/interfaces/FlowQueryIndexStatus.html +8 -0
- package/docs/api/interfaces/FlowQueryPage.html +3 -0
- package/docs/api/interfaces/FlowQueryQuality.html +5 -0
- package/docs/api/interfaces/FlowQueryRecordsResult.html +8 -0
- package/docs/api/interfaces/FlowQueryUsage.html +12 -0
- package/docs/api/interfaces/FlowRunProjectionField.html +4 -0
- 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 +5 -3
- package/docs/api/interfaces/ReclaimOptions.html +1 -1
- 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 +4 -3
- package/docs/api/interfaces/StepContinueOptions.html +3 -3
- package/docs/api/interfaces/TDigestCreateOptions.html +1 -1
- package/docs/api/interfaces/TDigestMergeOptions.html +1 -1
- package/docs/api/interfaces/TransitionOptions.html +2 -2
- package/docs/api/interfaces/TransitionOutcome.html +1 -1
- package/docs/api/modules.html +1 -1
- package/docs/api/types/ConnectionRequestDisposition.html +1 -1
- package/docs/api/types/FlowPolicyBackoffKind.html +1 -0
- package/docs/api/types/FlowProjectionField.html +1 -0
- package/docs/api/types/FlowProjectionShape.html +1 -0
- package/docs/api/types/FlowQueryInteger.html +1 -0
- package/docs/api/types/FlowQueryParameter.html +1 -0
- package/docs/api/types/FlowQueryParameters.html +1 -0
- package/docs/api/types/FlowQueryRecord.html +1 -0
- package/docs/api/types/FlowQueryResult.html +1 -0
- package/docs/api/types/ManagementPairs.html +1 -1
- package/docs/api/types/SearchStateMeta.html +1 -1
- package/docs/api/variables/COMMAND_OPCODES.html +1 -1
- package/docs/api/variables/FERRICSTORE_MINIMUM_SERVER_VERSION.html +1 -1
- package/docs/api/variables/FERRICSTORE_NATIVE_PROTOCOL_VERSION.html +1 -1
- package/docs/api/variables/FERRICSTORE_SDK_VERSION.html +1 -1
- package/docs/api/variables/FlowProjection.html +1 -0
- package/docs/api/variables/MAX_FLOW_POLICY_GENERATION.html +1 -0
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -58,6 +58,9 @@ var FlowWrongStateError = class extends FerricStoreError {
|
|
|
58
58
|
var StaleLeaseError = class extends FerricStoreError {
|
|
59
59
|
code = "stale_lease";
|
|
60
60
|
};
|
|
61
|
+
var StalePolicyGenerationError = class extends FerricStoreError {
|
|
62
|
+
code = "stale_policy_generation";
|
|
63
|
+
};
|
|
61
64
|
var FlowAlreadyExistsError = class extends FerricStoreError {
|
|
62
65
|
code = "flow_already_exists";
|
|
63
66
|
};
|
|
@@ -123,6 +126,9 @@ function classifyServerError(message, raw, cause, status) {
|
|
|
123
126
|
if (code === "stale_lease" || code === "stale_flow_lease" || lower.includes("stale flow lease") || lower.includes("stale lease") || lower.includes("stale token")) {
|
|
124
127
|
return new StaleLeaseError(message, { cause, raw });
|
|
125
128
|
}
|
|
129
|
+
if (code === "stale_generation" || code === "stale_policy_generation" || code === "stale_flow_policy_generation" || lower.includes("stale flow policy generation") || lower.includes("stale policy generation")) {
|
|
130
|
+
return new StalePolicyGenerationError(message, { cause, raw });
|
|
131
|
+
}
|
|
126
132
|
if (code === "flow_not_found" || lower.includes("flow") && (lower.includes("not found") || lower.includes("does not exist"))) {
|
|
127
133
|
return new FlowNotFoundError(message, { cause, raw });
|
|
128
134
|
}
|
|
@@ -1176,10 +1182,151 @@ var NativeHeartbeat = class {
|
|
|
1176
1182
|
};
|
|
1177
1183
|
|
|
1178
1184
|
// src/protocol.ts
|
|
1179
|
-
import { Buffer as
|
|
1185
|
+
import { Buffer as Buffer27 } from "buffer";
|
|
1180
1186
|
|
|
1181
|
-
// src/
|
|
1187
|
+
// src/flow-query-request.ts
|
|
1182
1188
|
import { Buffer as Buffer4 } from "buffer";
|
|
1189
|
+
var FLOW_QUERY_LANGUAGE_VERSION = "FQL1";
|
|
1190
|
+
var FLOW_QUERY_MAX_BYTES = 16 * 1024;
|
|
1191
|
+
var FLOW_QUERY_MAX_PARAMETERS = 64;
|
|
1192
|
+
var FLOW_QUERY_MAX_PARAMETER_NAME_BYTES = 128;
|
|
1193
|
+
var MIN_I64 = -(1n << 63n);
|
|
1194
|
+
var MAX_I64 = (1n << 63n) - 1n;
|
|
1195
|
+
var INDEX_ID = /^[A-Za-z0-9_.:-]{1,64}$/u;
|
|
1196
|
+
function flowQueryArgs(query, params = {}) {
|
|
1197
|
+
validateFlowQueryText(query);
|
|
1198
|
+
const entries = flowQueryParameterEntries(params);
|
|
1199
|
+
const args = ["FLOW.QUERY", FLOW_QUERY_LANGUAGE_VERSION, query];
|
|
1200
|
+
for (const [name, value] of entries) args.push(name, value);
|
|
1201
|
+
return args;
|
|
1202
|
+
}
|
|
1203
|
+
function flowQueryPayload(args) {
|
|
1204
|
+
if (args.length < 2) throw new TypeError("FLOW.QUERY requires version and query");
|
|
1205
|
+
if ((args.length - 2) % 2 !== 0) {
|
|
1206
|
+
throw new TypeError("FLOW.QUERY parameters must be name/value pairs");
|
|
1207
|
+
}
|
|
1208
|
+
const version = commandText(args[0], "FLOW.QUERY version");
|
|
1209
|
+
if (version !== FLOW_QUERY_LANGUAGE_VERSION) {
|
|
1210
|
+
throw new TypeError(`FLOW.QUERY requires version ${FLOW_QUERY_LANGUAGE_VERSION}`);
|
|
1211
|
+
}
|
|
1212
|
+
const query = commandText(args[1], "FLOW.QUERY query");
|
|
1213
|
+
validateFlowQueryText(query);
|
|
1214
|
+
const parameterCount = (args.length - 2) / 2;
|
|
1215
|
+
if (parameterCount > FLOW_QUERY_MAX_PARAMETERS) {
|
|
1216
|
+
throw new TypeError(`FLOW.QUERY accepts at most ${FLOW_QUERY_MAX_PARAMETERS} named parameters`);
|
|
1217
|
+
}
|
|
1218
|
+
const params = /* @__PURE__ */ Object.create(null);
|
|
1219
|
+
for (let index = 2; index < args.length; index += 2) {
|
|
1220
|
+
const name = commandText(args[index], "FLOW.QUERY parameter name");
|
|
1221
|
+
validateFlowQueryParameterName(name);
|
|
1222
|
+
if (Object.hasOwn(params, name)) {
|
|
1223
|
+
throw new TypeError(`FLOW.QUERY parameter ${JSON.stringify(name)} is duplicated`);
|
|
1224
|
+
}
|
|
1225
|
+
params[name] = normalizeFlowQueryParameter(args[index + 1], name);
|
|
1226
|
+
}
|
|
1227
|
+
return {
|
|
1228
|
+
version,
|
|
1229
|
+
query,
|
|
1230
|
+
...parameterCount === 0 ? {} : { params }
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
function validateFlowQueryText(query) {
|
|
1234
|
+
if (typeof query !== "string") throw new TypeError("FLOW.QUERY query must be text");
|
|
1235
|
+
if (query.trim().length === 0) throw new TypeError("FLOW.QUERY query must not be empty");
|
|
1236
|
+
validateUnicodeScalarText(query, "FLOW.QUERY query");
|
|
1237
|
+
if (Buffer4.byteLength(query, "utf8") > FLOW_QUERY_MAX_BYTES) {
|
|
1238
|
+
throw new TypeError(`FLOW.QUERY query exceeds ${FLOW_QUERY_MAX_BYTES} bytes`);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
function validateFlowQueryIndexId(indexId) {
|
|
1242
|
+
if (typeof indexId !== "string" || !INDEX_ID.test(indexId)) {
|
|
1243
|
+
throw new TypeError(
|
|
1244
|
+
"query index id must be 1..64 ASCII letters, digits, '_', '-', ':', or '.'"
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
function hasFlowExplainPrefix(query) {
|
|
1249
|
+
const source = query.trimStart();
|
|
1250
|
+
const prefix = source.slice(0, 7);
|
|
1251
|
+
return prefix.toUpperCase() === "EXPLAIN" && (source.length === 7 || /[\t\n\r ]/u.test(source[7] ?? ""));
|
|
1252
|
+
}
|
|
1253
|
+
function flowQueryParameterEntries(params) {
|
|
1254
|
+
if (typeof params !== "object" || params == null || Array.isArray(params)) {
|
|
1255
|
+
throw new TypeError("FLOW.QUERY params must be a plain object");
|
|
1256
|
+
}
|
|
1257
|
+
const prototype = Object.getPrototypeOf(params);
|
|
1258
|
+
if (prototype !== null && prototype !== Object.prototype) {
|
|
1259
|
+
throw new TypeError("FLOW.QUERY params must be a plain object");
|
|
1260
|
+
}
|
|
1261
|
+
const keys = Reflect.ownKeys(params);
|
|
1262
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
1263
|
+
throw new TypeError("FLOW.QUERY parameter names must be strings");
|
|
1264
|
+
}
|
|
1265
|
+
if (keys.length > FLOW_QUERY_MAX_PARAMETERS) {
|
|
1266
|
+
throw new TypeError(`FLOW.QUERY accepts at most ${FLOW_QUERY_MAX_PARAMETERS} named parameters`);
|
|
1267
|
+
}
|
|
1268
|
+
const names = keys.sort();
|
|
1269
|
+
return names.map((name) => {
|
|
1270
|
+
validateFlowQueryParameterName(name);
|
|
1271
|
+
return [name, normalizeFlowQueryParameter(params[name], name)];
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
function validateFlowQueryParameterName(name) {
|
|
1275
|
+
validateUnicodeScalarText(name, "FLOW.QUERY parameter name");
|
|
1276
|
+
const size = Buffer4.byteLength(name, "utf8");
|
|
1277
|
+
if (size === 0 || size > FLOW_QUERY_MAX_PARAMETER_NAME_BYTES) {
|
|
1278
|
+
throw new TypeError(
|
|
1279
|
+
`FLOW.QUERY parameter names must be 1..${FLOW_QUERY_MAX_PARAMETER_NAME_BYTES} bytes`
|
|
1280
|
+
);
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
function normalizeFlowQueryParameter(value, name) {
|
|
1284
|
+
if (typeof value === "string") {
|
|
1285
|
+
validateUnicodeScalarText(value, `FLOW.QUERY parameter ${JSON.stringify(name)}`);
|
|
1286
|
+
return value;
|
|
1287
|
+
}
|
|
1288
|
+
if (Buffer4.isBuffer(value)) return value;
|
|
1289
|
+
if (value instanceof Uint8Array) return Buffer4.from(value);
|
|
1290
|
+
if (typeof value === "boolean") return value;
|
|
1291
|
+
if (typeof value === "bigint" && value >= MIN_I64 && value <= MAX_I64) return value;
|
|
1292
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1293
|
+
if (!Number.isInteger(value) || Number.isSafeInteger(value)) return value;
|
|
1294
|
+
}
|
|
1295
|
+
throw new TypeError(
|
|
1296
|
+
`FLOW.QUERY parameter ${JSON.stringify(name)} must be text, bytes, boolean, a finite float, or a signed 64-bit integer`
|
|
1297
|
+
);
|
|
1298
|
+
}
|
|
1299
|
+
function commandText(value, context) {
|
|
1300
|
+
if (typeof value === "string") {
|
|
1301
|
+
validateUnicodeScalarText(value, context);
|
|
1302
|
+
return value;
|
|
1303
|
+
}
|
|
1304
|
+
if (Buffer4.isBuffer(value) || value instanceof Uint8Array) {
|
|
1305
|
+
try {
|
|
1306
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
1307
|
+
} catch (error) {
|
|
1308
|
+
throw new TypeError(`${context} must be valid UTF-8`, { cause: error });
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
throw new TypeError(`${context} must be text`);
|
|
1312
|
+
}
|
|
1313
|
+
function validateUnicodeScalarText(value, context) {
|
|
1314
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
1315
|
+
const code = value.charCodeAt(index);
|
|
1316
|
+
if (code >= 55296 && code <= 56319) {
|
|
1317
|
+
const low = value.charCodeAt(index + 1);
|
|
1318
|
+
if (!(low >= 56320 && low <= 57343)) {
|
|
1319
|
+
throw new TypeError(`${context} must be valid UTF-8`);
|
|
1320
|
+
}
|
|
1321
|
+
index += 1;
|
|
1322
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
1323
|
+
throw new TypeError(`${context} must be valid UTF-8`);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
// src/command-grammar.ts
|
|
1329
|
+
import { Buffer as Buffer5 } from "buffer";
|
|
1183
1330
|
|
|
1184
1331
|
// src/command-metadata-flow.ts
|
|
1185
1332
|
var flowStateIdCommands = /* @__PURE__ */ new Set([
|
|
@@ -1570,20 +1717,15 @@ var typeScopedFlowCommands = /* @__PURE__ */ new Set([
|
|
|
1570
1717
|
"FLOW.ATTRIBUTE_VALUES",
|
|
1571
1718
|
"FLOW.ATTRIBUTES",
|
|
1572
1719
|
"FLOW.BUDGET.LIST",
|
|
1573
|
-
"FLOW.FAILURES",
|
|
1574
1720
|
"FLOW.GOVERNANCE.OVERVIEW",
|
|
1575
1721
|
"FLOW.INFO",
|
|
1576
1722
|
"FLOW.LIMIT.LIST",
|
|
1577
|
-
"FLOW.LIST",
|
|
1578
1723
|
"FLOW.POLICY.GET",
|
|
1579
1724
|
"FLOW.POLICY.SET",
|
|
1580
1725
|
"FLOW.RETENTION_CLEANUP",
|
|
1581
1726
|
"FLOW.SCHEDULE.FIRE_DUE",
|
|
1582
1727
|
"FLOW.SCHEDULE.LIST",
|
|
1583
|
-
"FLOW.
|
|
1584
|
-
"FLOW.STATS",
|
|
1585
|
-
"FLOW.STUCK",
|
|
1586
|
-
"FLOW.TERMINALS"
|
|
1728
|
+
"FLOW.STATS"
|
|
1587
1729
|
]);
|
|
1588
1730
|
var flowScheduleCommands = /* @__PURE__ */ new Set([
|
|
1589
1731
|
"FLOW.SCHEDULE.CREATE",
|
|
@@ -1626,8 +1768,8 @@ var secondKeySubcommands = /* @__PURE__ */ new Map([
|
|
|
1626
1768
|
]);
|
|
1627
1769
|
function commandToken(value) {
|
|
1628
1770
|
if (typeof value === "string") return value.toUpperCase();
|
|
1629
|
-
if (
|
|
1630
|
-
return
|
|
1771
|
+
if (Buffer5.isBuffer(value) || value instanceof Uint8Array) {
|
|
1772
|
+
return Buffer5.from(value).toString("utf8").toUpperCase();
|
|
1631
1773
|
}
|
|
1632
1774
|
return void 0;
|
|
1633
1775
|
}
|
|
@@ -1730,7 +1872,7 @@ function safeIntegerArgument(value) {
|
|
|
1730
1872
|
if (typeof value === "bigint") {
|
|
1731
1873
|
return value >= BigInt(Number.MIN_SAFE_INTEGER) && value <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(value) : void 0;
|
|
1732
1874
|
}
|
|
1733
|
-
const source = typeof value === "string" ? value :
|
|
1875
|
+
const source = typeof value === "string" ? value : Buffer5.isBuffer(value) || value instanceof Uint8Array ? Buffer5.from(value).toString("utf8") : void 0;
|
|
1734
1876
|
if (source == null || !/^[+-]?\d+$/u.test(source)) return void 0;
|
|
1735
1877
|
const parsed = BigInt(source);
|
|
1736
1878
|
return parsed >= BigInt(Number.MIN_SAFE_INTEGER) && parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : void 0;
|
|
@@ -1783,7 +1925,7 @@ function hasOwnCommandArgument(args, index, end, section) {
|
|
|
1783
1925
|
}
|
|
1784
1926
|
|
|
1785
1927
|
// src/protocol-core.ts
|
|
1786
|
-
import { Buffer as
|
|
1928
|
+
import { Buffer as Buffer9 } from "buffer";
|
|
1787
1929
|
|
|
1788
1930
|
// src/protocol-constants.ts
|
|
1789
1931
|
import "buffer";
|
|
@@ -1881,7 +2023,6 @@ var COMMAND_OPCODES = {
|
|
|
1881
2023
|
"FLOW.VALUE.PUT": 523,
|
|
1882
2024
|
"FLOW.VALUE.MGET": 524,
|
|
1883
2025
|
"FLOW.SIGNAL": 525,
|
|
1884
|
-
"FLOW.LIST": 526,
|
|
1885
2026
|
"FLOW.CREATE_MANY": 527,
|
|
1886
2027
|
"FLOW.COMPLETE_MANY": 528,
|
|
1887
2028
|
"FLOW.TRANSITION_MANY": 529,
|
|
@@ -1890,13 +2031,7 @@ var COMMAND_OPCODES = {
|
|
|
1890
2031
|
"FLOW.CANCEL_MANY": 532,
|
|
1891
2032
|
"FLOW.RECLAIM": 533,
|
|
1892
2033
|
"FLOW.REWIND": 534,
|
|
1893
|
-
"FLOW.TERMINALS": 535,
|
|
1894
|
-
"FLOW.FAILURES": 536,
|
|
1895
|
-
"FLOW.BY_PARENT": 537,
|
|
1896
|
-
"FLOW.BY_ROOT": 538,
|
|
1897
|
-
"FLOW.BY_CORRELATION": 539,
|
|
1898
2034
|
"FLOW.INFO": 540,
|
|
1899
|
-
"FLOW.STUCK": 541,
|
|
1900
2035
|
"FLOW.POLICY.SET": 542,
|
|
1901
2036
|
"FLOW.POLICY.GET": 543,
|
|
1902
2037
|
"FLOW.SPAWN_CHILDREN": 544,
|
|
@@ -1915,7 +2050,7 @@ var COMMAND_OPCODES = {
|
|
|
1915
2050
|
"FLOW.STATS": 557,
|
|
1916
2051
|
"FLOW.ATTRIBUTES": 558,
|
|
1917
2052
|
"FLOW.ATTRIBUTE_VALUES": 559,
|
|
1918
|
-
"FLOW.
|
|
2053
|
+
"FLOW.QUERY": 561,
|
|
1919
2054
|
"FLOW.EFFECT.RESERVE": 576,
|
|
1920
2055
|
"FLOW.EFFECT.CONFIRM": 577,
|
|
1921
2056
|
"FLOW.EFFECT.FAIL": 578,
|
|
@@ -1998,11 +2133,13 @@ var OPCODES = {
|
|
|
1998
2133
|
flowRetryMany: COMMAND_OPCODES["FLOW.RETRY_MANY"],
|
|
1999
2134
|
flowFailMany: COMMAND_OPCODES["FLOW.FAIL_MANY"],
|
|
2000
2135
|
flowReclaim: COMMAND_OPCODES["FLOW.RECLAIM"],
|
|
2136
|
+
flowPolicySet: COMMAND_OPCODES["FLOW.POLICY.SET"],
|
|
2137
|
+
flowPolicyGet: COMMAND_OPCODES["FLOW.POLICY.GET"],
|
|
2001
2138
|
flowSpawnChildren: COMMAND_OPCODES["FLOW.SPAWN_CHILDREN"],
|
|
2002
2139
|
flowStepContinue: COMMAND_OPCODES["FLOW.STEP_CONTINUE"],
|
|
2003
2140
|
flowStartAndClaim: COMMAND_OPCODES["FLOW.START_AND_CLAIM"],
|
|
2004
2141
|
flowRunStepsMany: COMMAND_OPCODES["FLOW.RUN_STEPS_MANY"],
|
|
2005
|
-
|
|
2142
|
+
flowQuery: COMMAND_OPCODES["FLOW.QUERY"]
|
|
2006
2143
|
};
|
|
2007
2144
|
var COMPACT_FLOW_CLAIM_JOBS = 128;
|
|
2008
2145
|
var COMPACT_OK_LIST = 129;
|
|
@@ -2029,11 +2166,12 @@ var COMPACT_FLOW_TRANSITION_MANY_REQUEST = 155;
|
|
|
2029
2166
|
var COMPACT_FLOW_TRANSITION_MANY_OK_REQUEST = 156;
|
|
2030
2167
|
var COMPACT_FLOW_VALUE_MGET_REQUEST = 157;
|
|
2031
2168
|
var COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST = 158;
|
|
2032
|
-
var
|
|
2169
|
+
var COMPACT_FLOW_QUERY_RESULT = 160;
|
|
2033
2170
|
var COMPACT_PIPELINE_DECODED = /* @__PURE__ */ Symbol("ferricstore.compactPipelineDecoded");
|
|
2034
2171
|
var NULL_U32 = 4294967295;
|
|
2035
|
-
var
|
|
2036
|
-
var
|
|
2172
|
+
var MIN_I642 = -9223372036854775808n;
|
|
2173
|
+
var MAX_I642 = 9223372036854775807n;
|
|
2174
|
+
var MAX_U64 = 18446744073709551615n;
|
|
2037
2175
|
var MAX_SAFE_INTEGER_BIGINT = BigInt(Number.MAX_SAFE_INTEGER);
|
|
2038
2176
|
var MIN_SAFE_INTEGER_BIGINT = BigInt(Number.MIN_SAFE_INTEGER);
|
|
2039
2177
|
var FLOW_RECORD_FIELD_KEYS = [
|
|
@@ -2082,16 +2220,16 @@ var FLOW_RECORD_FIELD_KEYS = [
|
|
|
2082
2220
|
];
|
|
2083
2221
|
|
|
2084
2222
|
// src/protocol-text.ts
|
|
2085
|
-
import { Buffer as
|
|
2223
|
+
import { Buffer as Buffer7 } from "buffer";
|
|
2086
2224
|
function toBuffer(value) {
|
|
2087
|
-
if (
|
|
2088
|
-
if (value instanceof Uint8Array) return
|
|
2089
|
-
if (typeof value === "string") return
|
|
2225
|
+
if (Buffer7.isBuffer(value)) return value;
|
|
2226
|
+
if (value instanceof Uint8Array) return Buffer7.from(value);
|
|
2227
|
+
if (typeof value === "string") return Buffer7.from(value);
|
|
2090
2228
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2091
|
-
return
|
|
2229
|
+
return Buffer7.from(String(value));
|
|
2092
2230
|
}
|
|
2093
|
-
if (typeof value === "symbol") return
|
|
2094
|
-
if (value == null) return
|
|
2231
|
+
if (typeof value === "symbol") return Buffer7.from(value.description ?? value.toString());
|
|
2232
|
+
if (value == null) return Buffer7.alloc(0);
|
|
2095
2233
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2096
2234
|
}
|
|
2097
2235
|
function asText(value) {
|
|
@@ -2099,14 +2237,14 @@ function asText(value) {
|
|
|
2099
2237
|
}
|
|
2100
2238
|
function optionalText(value) {
|
|
2101
2239
|
if (value == null || value === "") return void 0;
|
|
2102
|
-
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" ||
|
|
2240
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2103
2241
|
return asText(value);
|
|
2104
2242
|
}
|
|
2105
2243
|
return void 0;
|
|
2106
2244
|
}
|
|
2107
2245
|
function commandTokenIs(value, expected) {
|
|
2108
2246
|
if (typeof value === "string") return value.toUpperCase() === expected;
|
|
2109
|
-
if (
|
|
2247
|
+
if (Buffer7.isBuffer(value) || value instanceof Uint8Array) {
|
|
2110
2248
|
return asText(value).toUpperCase() === expected;
|
|
2111
2249
|
}
|
|
2112
2250
|
return false;
|
|
@@ -2120,7 +2258,7 @@ function commandNameIs(value, expected) {
|
|
|
2120
2258
|
}
|
|
2121
2259
|
|
|
2122
2260
|
// src/request-context.ts
|
|
2123
|
-
import { Buffer as
|
|
2261
|
+
import { Buffer as Buffer8 } from "buffer";
|
|
2124
2262
|
var requestContextCommands = /* @__PURE__ */ new Set([
|
|
2125
2263
|
"INVOCATION.CREATE",
|
|
2126
2264
|
"INVOCATION.DEFINITION.GET",
|
|
@@ -2175,9 +2313,9 @@ function requestContextCommandToken(value) {
|
|
|
2175
2313
|
const upper = value.toUpperCase();
|
|
2176
2314
|
return isRequestContextCommand(upper) ? upper : void 0;
|
|
2177
2315
|
}
|
|
2178
|
-
if (
|
|
2316
|
+
if (Buffer8.isBuffer(value) || value instanceof Uint8Array) {
|
|
2179
2317
|
if (value[0] !== 73 && value[0] !== 105) return void 0;
|
|
2180
|
-
const command =
|
|
2318
|
+
const command = Buffer8.from(value).toString("utf8").toUpperCase();
|
|
2181
2319
|
return isRequestContextCommand(command) ? command : void 0;
|
|
2182
2320
|
}
|
|
2183
2321
|
return void 0;
|
|
@@ -2208,12 +2346,12 @@ function requestContextText(context, fieldName) {
|
|
|
2208
2346
|
return value;
|
|
2209
2347
|
}
|
|
2210
2348
|
function isPlainObject(value) {
|
|
2211
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2349
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer8.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2212
2350
|
}
|
|
2213
2351
|
function commandToken2(value) {
|
|
2214
2352
|
if (typeof value === "string") return value.toUpperCase();
|
|
2215
|
-
if (
|
|
2216
|
-
return
|
|
2353
|
+
if (Buffer8.isBuffer(value) || value instanceof Uint8Array) {
|
|
2354
|
+
return Buffer8.from(value).toString("utf8").toUpperCase();
|
|
2217
2355
|
}
|
|
2218
2356
|
return "";
|
|
2219
2357
|
}
|
|
@@ -2303,17 +2441,17 @@ function requestFrameTooLarge(maxBytes) {
|
|
|
2303
2441
|
);
|
|
2304
2442
|
}
|
|
2305
2443
|
function binaryValueByteLength(value) {
|
|
2306
|
-
if (
|
|
2307
|
-
if (typeof value === "string") return
|
|
2444
|
+
if (Buffer9.isBuffer(value) || value instanceof Uint8Array) return value.byteLength;
|
|
2445
|
+
if (typeof value === "string") return Buffer9.byteLength(value);
|
|
2308
2446
|
if (typeof value === "number" || typeof value === "bigint" || typeof value === "boolean") {
|
|
2309
|
-
return
|
|
2447
|
+
return Buffer9.byteLength(String(value));
|
|
2310
2448
|
}
|
|
2311
|
-
if (typeof value === "symbol") return
|
|
2449
|
+
if (typeof value === "symbol") return Buffer9.byteLength(value.description ?? value.toString());
|
|
2312
2450
|
if (value == null) return 0;
|
|
2313
2451
|
return toBuffer(value).byteLength;
|
|
2314
2452
|
}
|
|
2315
2453
|
function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
2316
|
-
if (
|
|
2454
|
+
if (Buffer9.isBuffer(value)) {
|
|
2317
2455
|
value.copy(output, offset);
|
|
2318
2456
|
return;
|
|
2319
2457
|
}
|
|
@@ -2332,7 +2470,7 @@ function writeCustomPayload(output, offset, value, knownByteLength) {
|
|
|
2332
2470
|
} else {
|
|
2333
2471
|
throw new FerricStoreError(`unsupported binary command argument type: ${typeof value}`);
|
|
2334
2472
|
}
|
|
2335
|
-
output.write(text3, offset, knownByteLength ??
|
|
2473
|
+
output.write(text3, offset, knownByteLength ?? Buffer9.byteLength(text3), "utf8");
|
|
2336
2474
|
}
|
|
2337
2475
|
function compactBinaryEncodedLength(value) {
|
|
2338
2476
|
return 4 + compactBinaryByteLength(value);
|
|
@@ -2345,10 +2483,10 @@ function compactBinaryByteLength(value) {
|
|
|
2345
2483
|
return byteLength;
|
|
2346
2484
|
}
|
|
2347
2485
|
function isCompactBinaryArgument(value) {
|
|
2348
|
-
return typeof value === "string" ||
|
|
2486
|
+
return typeof value === "string" || Buffer9.isBuffer(value) || value instanceof Uint8Array;
|
|
2349
2487
|
}
|
|
2350
2488
|
function isCompactBinaryScalar(value) {
|
|
2351
|
-
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" ||
|
|
2489
|
+
return value == null || typeof value === "string" || typeof value === "number" || typeof value === "bigint" || typeof value === "boolean" || typeof value === "symbol" || Buffer9.isBuffer(value) || value instanceof Uint8Array;
|
|
2352
2490
|
}
|
|
2353
2491
|
function compactOptionalBinaryEncodedLength(value) {
|
|
2354
2492
|
return value == null ? 4 : compactBinaryEncodedLength(value);
|
|
@@ -2414,7 +2552,7 @@ function integerArg(value) {
|
|
|
2414
2552
|
throw new FerricStoreError("integer command argument must be an integer");
|
|
2415
2553
|
}
|
|
2416
2554
|
const integer2 = BigInt(source);
|
|
2417
|
-
if (integer2 <
|
|
2555
|
+
if (integer2 < MIN_I642 || integer2 > MAX_I642) {
|
|
2418
2556
|
throw new FerricStoreError("integer command argument exceeds the signed 64-bit range");
|
|
2419
2557
|
}
|
|
2420
2558
|
return integer2 >= MIN_SAFE_INTEGER_BIGINT && integer2 <= MAX_SAFE_INTEGER_BIGINT ? Number(integer2) : integer2;
|
|
@@ -2445,7 +2583,7 @@ function independentMode(value) {
|
|
|
2445
2583
|
return 0;
|
|
2446
2584
|
}
|
|
2447
2585
|
function optionalI64(value) {
|
|
2448
|
-
return typeof value === "number" ? BigInt(value) :
|
|
2586
|
+
return typeof value === "number" ? BigInt(value) : MIN_I642;
|
|
2449
2587
|
}
|
|
2450
2588
|
function compactClaimReturnMode(value) {
|
|
2451
2589
|
const mode = value == null ? "" : asText(value).toUpperCase();
|
|
@@ -2479,18 +2617,18 @@ function setOwnValue2(target, key, value) {
|
|
|
2479
2617
|
}
|
|
2480
2618
|
|
|
2481
2619
|
// src/protocol-flow-options.ts
|
|
2482
|
-
import { Buffer as
|
|
2620
|
+
import { Buffer as Buffer10 } from "buffer";
|
|
2483
2621
|
|
|
2484
2622
|
// src/protocol-flow-option-value.ts
|
|
2485
|
-
function setFlowOptionValue(payload,
|
|
2486
|
-
if (!repeat || !Object.hasOwn(payload,
|
|
2487
|
-
setOwnValue2(payload,
|
|
2623
|
+
function setFlowOptionValue(payload, field3, value, repeat) {
|
|
2624
|
+
if (!repeat || !Object.hasOwn(payload, field3)) {
|
|
2625
|
+
setOwnValue2(payload, field3, value);
|
|
2488
2626
|
return;
|
|
2489
2627
|
}
|
|
2490
|
-
const previous = payload[
|
|
2628
|
+
const previous = payload[field3];
|
|
2491
2629
|
setOwnValue2(
|
|
2492
2630
|
payload,
|
|
2493
|
-
|
|
2631
|
+
field3,
|
|
2494
2632
|
Array.isArray(previous) ? [...previous, value] : [previous, value]
|
|
2495
2633
|
);
|
|
2496
2634
|
}
|
|
@@ -2533,44 +2671,30 @@ function optionMap(args) {
|
|
|
2533
2671
|
index += 3;
|
|
2534
2672
|
continue;
|
|
2535
2673
|
}
|
|
2536
|
-
const
|
|
2674
|
+
const field3 = OPTION_FIELDS[token] ?? token.toLowerCase();
|
|
2537
2675
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow options")) {
|
|
2538
2676
|
throw new FerricStoreError(`${token} requires a value`);
|
|
2539
2677
|
}
|
|
2540
2678
|
const value = args[index + 1];
|
|
2541
|
-
if (BOOL_OPTION_FIELDS.has(
|
|
2679
|
+
if (BOOL_OPTION_FIELDS.has(field3) && !isBoolToken(value)) {
|
|
2542
2680
|
return void 0;
|
|
2543
2681
|
}
|
|
2544
|
-
setOwnValue2(payload,
|
|
2682
|
+
setOwnValue2(payload, field3, BOOL_OPTION_FIELDS.has(field3) ? boolArg(value) : value);
|
|
2545
2683
|
index += 2;
|
|
2546
2684
|
}
|
|
2547
2685
|
return payload;
|
|
2548
2686
|
}
|
|
2549
|
-
function ensureObjectField(payload,
|
|
2550
|
-
const value = payload[
|
|
2687
|
+
function ensureObjectField(payload, field3) {
|
|
2688
|
+
const value = payload[field3];
|
|
2551
2689
|
if (isPlainObject2(value)) {
|
|
2552
2690
|
return value;
|
|
2553
2691
|
}
|
|
2554
2692
|
const next = {};
|
|
2555
|
-
setOwnValue2(payload,
|
|
2693
|
+
setOwnValue2(payload, field3, next);
|
|
2556
2694
|
return next;
|
|
2557
2695
|
}
|
|
2558
|
-
function normalizeFlowSearchStateMeta(payload) {
|
|
2559
|
-
const stateMeta = payload.state_meta;
|
|
2560
|
-
if (!isPlainObject2(stateMeta) || Object.keys(stateMeta).length === 0) {
|
|
2561
|
-
return;
|
|
2562
|
-
}
|
|
2563
|
-
if (Object.values(stateMeta).every(isPlainObject2)) {
|
|
2564
|
-
return;
|
|
2565
|
-
}
|
|
2566
|
-
const state = payload.state;
|
|
2567
|
-
if (state == null) {
|
|
2568
|
-
throw new FerricStoreError("FLOW.SEARCH STATE_META filters require STATE or nested state metadata");
|
|
2569
|
-
}
|
|
2570
|
-
payload.state_meta = { [asText(state)]: stateMeta };
|
|
2571
|
-
}
|
|
2572
2696
|
function isPlainObject2(value) {
|
|
2573
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
2697
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer10.isBuffer(value) && !(value instanceof Uint8Array);
|
|
2574
2698
|
}
|
|
2575
2699
|
function parseFlowOptions(args, start, end, config) {
|
|
2576
2700
|
const payload = {};
|
|
@@ -2664,9 +2788,9 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2664
2788
|
case "TRANSITION_TO":
|
|
2665
2789
|
case "TO_EVENT":
|
|
2666
2790
|
case "EXPECT_STATE": {
|
|
2667
|
-
const
|
|
2791
|
+
const field3 = token === "IDEMPOTENCY" ? "idempotency_key" : token.toLowerCase();
|
|
2668
2792
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2669
|
-
setFlowOptionValue(payload,
|
|
2793
|
+
setFlowOptionValue(payload, field3, args[index + 1], token === "IF_STATE");
|
|
2670
2794
|
index += 2;
|
|
2671
2795
|
break;
|
|
2672
2796
|
}
|
|
@@ -2674,8 +2798,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2674
2798
|
case "RESULT":
|
|
2675
2799
|
case "ERROR":
|
|
2676
2800
|
case "REASON": {
|
|
2677
|
-
const
|
|
2678
|
-
if (!putScalar(payload,
|
|
2801
|
+
const field3 = token === "LEASE_TOKEN" ? "lease_token" : token.toLowerCase();
|
|
2802
|
+
if (!putScalar(payload, field3, args, index + 1, end)) return void 0;
|
|
2679
2803
|
index += 2;
|
|
2680
2804
|
break;
|
|
2681
2805
|
}
|
|
@@ -2697,8 +2821,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2697
2821
|
case "VALUE_REF":
|
|
2698
2822
|
case "STATE_META": {
|
|
2699
2823
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options") || !hasOwnCommandArgument(args, index + 2, end, "Flow options")) return void 0;
|
|
2700
|
-
const
|
|
2701
|
-
const values = ensureObjectField(payload,
|
|
2824
|
+
const field3 = token === "ATTRIBUTE" ? "attributes" : token === "ATTRIBUTE_MERGE" ? "attributes_merge" : token === "VALUE_REF" ? "value_refs" : "state_meta";
|
|
2825
|
+
const values = ensureObjectField(payload, field3);
|
|
2702
2826
|
setOwnValue2(values, asText(args[index + 1]), args[index + 2]);
|
|
2703
2827
|
index += 3;
|
|
2704
2828
|
break;
|
|
@@ -2707,8 +2831,8 @@ function parseFlowOptions(args, start, end, config) {
|
|
|
2707
2831
|
case "OVERRIDE_VALUE":
|
|
2708
2832
|
case "ATTRIBUTE_DELETE": {
|
|
2709
2833
|
if (!hasOwnCommandArgument(args, index + 1, end, "Flow options")) return void 0;
|
|
2710
|
-
const
|
|
2711
|
-
const values = ensureArrayField(payload,
|
|
2834
|
+
const field3 = token === "DROP_VALUE" ? "drop_values" : token === "OVERRIDE_VALUE" ? "override_values" : "attributes_delete";
|
|
2835
|
+
const values = ensureArrayField(payload, field3);
|
|
2712
2836
|
values.push(args[index + 1]);
|
|
2713
2837
|
index += 2;
|
|
2714
2838
|
break;
|
|
@@ -2825,13 +2949,13 @@ function putScalar(payload, key, args, index, end) {
|
|
|
2825
2949
|
setOwnValue2(payload, key, args[index]);
|
|
2826
2950
|
return true;
|
|
2827
2951
|
}
|
|
2828
|
-
function ensureArrayField(payload,
|
|
2829
|
-
const value = payload[
|
|
2952
|
+
function ensureArrayField(payload, field3) {
|
|
2953
|
+
const value = payload[field3];
|
|
2830
2954
|
if (Array.isArray(value)) {
|
|
2831
2955
|
return value;
|
|
2832
2956
|
}
|
|
2833
2957
|
const next = [];
|
|
2834
|
-
setOwnValue2(payload,
|
|
2958
|
+
setOwnValue2(payload, field3, next);
|
|
2835
2959
|
return next;
|
|
2836
2960
|
}
|
|
2837
2961
|
function putNumber(payload, key, args, index, end) {
|
|
@@ -3052,8 +3176,8 @@ function flowHistoryPayload(args) {
|
|
|
3052
3176
|
case "CONSISTENT_PROJECTION":
|
|
3053
3177
|
case "VALUES": {
|
|
3054
3178
|
if (!isBoolToken(value)) return void 0;
|
|
3055
|
-
const
|
|
3056
|
-
payload[
|
|
3179
|
+
const field3 = token === "REV" ? "rev" : token === "INCLUDE_COLD" ? "include_cold" : token === "CONSISTENT_PROJECTION" ? "consistent_projection" : "values";
|
|
3180
|
+
payload[field3] = boolArg(value);
|
|
3057
3181
|
break;
|
|
3058
3182
|
}
|
|
3059
3183
|
default:
|
|
@@ -3065,9 +3189,9 @@ function flowHistoryPayload(args) {
|
|
|
3065
3189
|
function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
3066
3190
|
if (args.length < leadingFields.length) return void 0;
|
|
3067
3191
|
const payload = {};
|
|
3068
|
-
for (const [index,
|
|
3192
|
+
for (const [index, field3] of leadingFields.entries()) {
|
|
3069
3193
|
hasOwnCommandArgument(args, index, args.length, "Flow admin arguments");
|
|
3070
|
-
setOwnValue2(payload,
|
|
3194
|
+
setOwnValue2(payload, field3, args[index]);
|
|
3071
3195
|
}
|
|
3072
3196
|
for (let index = leadingFields.length; index < args.length; ) {
|
|
3073
3197
|
hasOwnCommandArgument(args, index, args.length, "Flow admin arguments");
|
|
@@ -3075,15 +3199,15 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3075
3199
|
if (token == null) return void 0;
|
|
3076
3200
|
if (["ATTRIBUTE", "ATTRIBUTE_MERGE", "STATE_META", "VALUE", "VALUE_REF"].includes(token)) {
|
|
3077
3201
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments") || !hasOwnCommandArgument(args, index + 2, args.length, "Flow admin arguments")) return void 0;
|
|
3078
|
-
const
|
|
3079
|
-
setOwnValue2(ensureObjectField(payload,
|
|
3202
|
+
const field4 = token === "ATTRIBUTE" ? "attributes" : token === "ATTRIBUTE_MERGE" ? "attributes_merge" : token === "STATE_META" ? "state_meta" : token === "VALUE" ? "values" : "value_refs";
|
|
3203
|
+
setOwnValue2(ensureObjectField(payload, field4), asText(args[index + 1]), args[index + 2]);
|
|
3080
3204
|
index += 3;
|
|
3081
3205
|
continue;
|
|
3082
3206
|
}
|
|
3083
3207
|
if (token === "ATTRIBUTE_DELETE" || token === "DROP_VALUE" || token === "OVERRIDE_VALUE") {
|
|
3084
3208
|
if (!hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments")) return void 0;
|
|
3085
|
-
const
|
|
3086
|
-
ensureArrayField(payload,
|
|
3209
|
+
const field4 = token === "ATTRIBUTE_DELETE" ? "attributes_delete" : token === "DROP_VALUE" ? "drop_values" : "override_values";
|
|
3210
|
+
ensureArrayField(payload, field4).push(args[index + 1]);
|
|
3087
3211
|
index += 2;
|
|
3088
3212
|
continue;
|
|
3089
3213
|
}
|
|
@@ -3102,13 +3226,13 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3102
3226
|
index += 2 + count;
|
|
3103
3227
|
continue;
|
|
3104
3228
|
}
|
|
3105
|
-
const
|
|
3106
|
-
if (
|
|
3229
|
+
const field3 = FLOW_ADMIN_FIELDS[token];
|
|
3230
|
+
if (field3 == null || !hasOwnCommandArgument(args, index + 1, args.length, "Flow admin arguments")) {
|
|
3107
3231
|
return void 0;
|
|
3108
3232
|
}
|
|
3109
3233
|
const rawValue = args[index + 1];
|
|
3110
|
-
if (FLOW_ADMIN_BOOLEAN_FIELDS.has(
|
|
3111
|
-
setOwnValue2(payload,
|
|
3234
|
+
if (FLOW_ADMIN_BOOLEAN_FIELDS.has(field3) && !isBoolToken(rawValue)) return void 0;
|
|
3235
|
+
setOwnValue2(payload, field3, FLOW_ADMIN_BOOLEAN_FIELDS.has(field3) ? boolArg(rawValue) : rawValue);
|
|
3112
3236
|
index += 2;
|
|
3113
3237
|
}
|
|
3114
3238
|
const serverBlockMs = opcode === COMMAND_OPCODES["FLOW.SCHEDULE.FIRE_DUE"] && payload.block_ms != null ? blockDurationMs(payload.block_ms, 1) : void 0;
|
|
@@ -3116,7 +3240,7 @@ function flowAdminPayload(opcode, args, leadingFields = []) {
|
|
|
3116
3240
|
}
|
|
3117
3241
|
|
|
3118
3242
|
// src/protocol-flow-compact.ts
|
|
3119
|
-
import { Buffer as
|
|
3243
|
+
import { Buffer as Buffer12 } from "buffer";
|
|
3120
3244
|
|
|
3121
3245
|
// src/protocol-flow-compact-common.ts
|
|
3122
3246
|
function compactManyRequestTag(value, regularTag, okOnSuccessTag) {
|
|
@@ -3225,7 +3349,7 @@ function parseNamedCountMap(values, start) {
|
|
|
3225
3349
|
}
|
|
3226
3350
|
|
|
3227
3351
|
// src/protocol-flow-compact-transition.ts
|
|
3228
|
-
import { Buffer as
|
|
3352
|
+
import { Buffer as Buffer11 } from "buffer";
|
|
3229
3353
|
function compactFlowTransitionManyPayload(partition, fromState, toState, rawItems, mixed, options, maxBodyBytes) {
|
|
3230
3354
|
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) {
|
|
3231
3355
|
return void 0;
|
|
@@ -3277,7 +3401,7 @@ function compactFlowTransitionManyPayload(partition, fromState, toState, rawItem
|
|
|
3277
3401
|
total += 4 + idLength + 4 + itemPartitionLength + 8 + 4 + leaseLength;
|
|
3278
3402
|
}
|
|
3279
3403
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3280
|
-
const out =
|
|
3404
|
+
const out = Buffer11.allocUnsafe(total);
|
|
3281
3405
|
let offset = 0;
|
|
3282
3406
|
out.writeUInt8(tag, offset);
|
|
3283
3407
|
offset += 1;
|
|
@@ -3335,7 +3459,7 @@ function compactFlowCreateManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3335
3459
|
}
|
|
3336
3460
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3337
3461
|
const tag = mixed ? COMPACT_FLOW_CREATE_MANY_MIXED_REQUEST : auto ? COMPACT_FLOW_CREATE_MANY_REQUEST : COMPACT_FLOW_CREATE_MANY_PARTITION_REQUEST;
|
|
3338
|
-
const out =
|
|
3462
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3339
3463
|
let offset = 0;
|
|
3340
3464
|
out.writeUInt8(tag, offset++);
|
|
3341
3465
|
offset = writeBinary(out, offset, toBuffer(options.type));
|
|
@@ -3380,7 +3504,7 @@ function compactFlowClaimDuePayload(type, options, maxBodyBytes) {
|
|
|
3380
3504
|
total += 1;
|
|
3381
3505
|
}
|
|
3382
3506
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3383
|
-
const out =
|
|
3507
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3384
3508
|
let offset = 0;
|
|
3385
3509
|
out.writeUInt8(COMPACT_FLOW_CLAIM_DUE_REQUEST, offset++);
|
|
3386
3510
|
offset = writeBinary(out, offset, toBuffer(type));
|
|
@@ -3434,7 +3558,7 @@ function compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto
|
|
|
3434
3558
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3435
3559
|
}
|
|
3436
3560
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3437
|
-
const out =
|
|
3561
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3438
3562
|
let offset = 0;
|
|
3439
3563
|
out.writeUInt8(
|
|
3440
3564
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_COMPLETE_MANY_OK_REQUEST : COMPACT_FLOW_COMPLETE_MANY_REQUEST,
|
|
@@ -3481,7 +3605,7 @@ function compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options,
|
|
|
3481
3605
|
total += compactBinaryEncodedLength(rawItems[rawIndex]) + compactOptionalBinaryEncodedLength(mixed ? rawItems[rawIndex + 1] : null) + compactBinaryEncodedLength(rawItems[rawIndex + width - 2]) + 8;
|
|
3482
3606
|
}
|
|
3483
3607
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3484
|
-
const out =
|
|
3608
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3485
3609
|
let offset = 0;
|
|
3486
3610
|
out.writeUInt8(
|
|
3487
3611
|
returnMode === "OK_ON_SUCCESS" ? COMPACT_FLOW_RETRY_MANY_OK_REQUEST : COMPACT_FLOW_RETRY_MANY_REQUEST,
|
|
@@ -3569,7 +3693,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3569
3693
|
total += 4 + idLength + 4 + itemPartitionLength + 8;
|
|
3570
3694
|
}
|
|
3571
3695
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3572
|
-
const out =
|
|
3696
|
+
const out = Buffer12.allocUnsafe(total);
|
|
3573
3697
|
let offset = 0;
|
|
3574
3698
|
out.writeUInt8(tag, offset);
|
|
3575
3699
|
offset += 1;
|
|
@@ -3592,6 +3716,7 @@ function compactFlowCancelManyPayload(args, maxBodyBytes) {
|
|
|
3592
3716
|
offset += 8;
|
|
3593
3717
|
}
|
|
3594
3718
|
return {
|
|
3719
|
+
compactResponseItems: count,
|
|
3595
3720
|
flags: FLAG_CUSTOM_PAYLOAD,
|
|
3596
3721
|
opcode: COMMAND_OPCODES["FLOW.CANCEL_MANY"],
|
|
3597
3722
|
payload: out
|
|
@@ -3605,7 +3730,7 @@ function isOptionalSafeIntegerNumber(value) {
|
|
|
3605
3730
|
}
|
|
3606
3731
|
|
|
3607
3732
|
// src/protocol-flow-compact-single.ts
|
|
3608
|
-
import { Buffer as
|
|
3733
|
+
import { Buffer as Buffer13 } from "buffer";
|
|
3609
3734
|
function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
3610
3735
|
if (refs.length > 4294967295 || maxBytes != null && (typeof maxBytes !== "number" || !Number.isSafeInteger(maxBytes) || maxBytes < 0)) return void 0;
|
|
3611
3736
|
const minimum = 13 + refs.length * 4;
|
|
@@ -3622,7 +3747,7 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3622
3747
|
total += 4 + byteLength;
|
|
3623
3748
|
}
|
|
3624
3749
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3625
|
-
const out =
|
|
3750
|
+
const out = Buffer13.allocUnsafe(total);
|
|
3626
3751
|
let offset = 0;
|
|
3627
3752
|
out.writeUInt8(COMPACT_FLOW_VALUE_MGET_REQUEST, offset);
|
|
3628
3753
|
offset += 1;
|
|
@@ -3635,47 +3760,6 @@ function compactFlowValueMGetPayload(refs, maxBytes, maxBodyBytes) {
|
|
|
3635
3760
|
}
|
|
3636
3761
|
return { flags: FLAG_CUSTOM_PAYLOAD, opcode: OPCODES.flowValueMGet, payload: out };
|
|
3637
3762
|
}
|
|
3638
|
-
function compactFlowListPayload(args, maxBodyBytes) {
|
|
3639
|
-
const type = args[0];
|
|
3640
|
-
if (!isCompactBinaryArgument(type)) return void 0;
|
|
3641
|
-
let state;
|
|
3642
|
-
let count = 100;
|
|
3643
|
-
let returnMode = 0;
|
|
3644
|
-
const seen = /* @__PURE__ */ new Set();
|
|
3645
|
-
for (let index = 1; index < args.length; index += 2) {
|
|
3646
|
-
if (index + 1 >= args.length) return void 0;
|
|
3647
|
-
const token = asText(args[index]).toUpperCase();
|
|
3648
|
-
if (seen.has(token)) return void 0;
|
|
3649
|
-
seen.add(token);
|
|
3650
|
-
if (token === "STATE") {
|
|
3651
|
-
if (!isCompactBinaryArgument(args[index + 1])) return void 0;
|
|
3652
|
-
state = args[index + 1];
|
|
3653
|
-
} else if (token === "COUNT") {
|
|
3654
|
-
const value = safeIntegerNumberArg(args[index + 1]);
|
|
3655
|
-
if (value <= 0) return void 0;
|
|
3656
|
-
count = value;
|
|
3657
|
-
} else if (token === "RETURN") {
|
|
3658
|
-
if (!commandTokenIs(args[index + 1], "META")) return void 0;
|
|
3659
|
-
returnMode = 1;
|
|
3660
|
-
} else {
|
|
3661
|
-
return void 0;
|
|
3662
|
-
}
|
|
3663
|
-
}
|
|
3664
|
-
const typeLength = compactBinaryByteLength(type);
|
|
3665
|
-
const stateLength = state == null ? 0 : compactBinaryByteLength(state);
|
|
3666
|
-
const total = 1 + 4 + typeLength + 4 + stateLength + 8 + 1;
|
|
3667
|
-
assertCompactPayloadFits(total, maxBodyBytes);
|
|
3668
|
-
const out = Buffer12.allocUnsafe(total);
|
|
3669
|
-
let offset = 0;
|
|
3670
|
-
out.writeUInt8(COMPACT_FLOW_LIST_REQUEST, offset);
|
|
3671
|
-
offset += 1;
|
|
3672
|
-
offset = writeBinaryValue(out, offset, type, typeLength);
|
|
3673
|
-
offset = writeOptionalBinaryValue(out, offset, state, stateLength);
|
|
3674
|
-
out.writeBigInt64BE(BigInt(count), offset);
|
|
3675
|
-
offset += 8;
|
|
3676
|
-
out.writeUInt8(returnMode, offset);
|
|
3677
|
-
return { flags: FLAG_CUSTOM_PAYLOAD, opcode: COMMAND_OPCODES["FLOW.LIST"], payload: out };
|
|
3678
|
-
}
|
|
3679
3763
|
|
|
3680
3764
|
// src/protocol-flow-routing.ts
|
|
3681
3765
|
function withFlowPartitionRouting(command, payload) {
|
|
@@ -3724,15 +3808,6 @@ function expandFlowClaimStates(args) {
|
|
|
3724
3808
|
}
|
|
3725
3809
|
|
|
3726
3810
|
// src/protocol-flow.ts
|
|
3727
|
-
function hasFlowCommandOnlyOption(command, args) {
|
|
3728
|
-
if (command !== "FLOW.SEARCH") return false;
|
|
3729
|
-
for (let index = 1; index < args.length; ) {
|
|
3730
|
-
const token = asText(args[index]).toUpperCase();
|
|
3731
|
-
if (token === "INDEXED_STATE_META") return true;
|
|
3732
|
-
index += token === "ATTRIBUTE" || token === "STATE_META" ? 3 : 2;
|
|
3733
|
-
}
|
|
3734
|
-
return false;
|
|
3735
|
-
}
|
|
3736
3811
|
function flowCreatePayload(args) {
|
|
3737
3812
|
if (args.length < 7) return void 0;
|
|
3738
3813
|
const id = args[0];
|
|
@@ -3789,9 +3864,9 @@ function flowValueMGetPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3789
3864
|
}
|
|
3790
3865
|
if (allowCompact) {
|
|
3791
3866
|
const compact = compactFlowValueMGetPayload(refs, payload.max_bytes, maxBodyBytes);
|
|
3792
|
-
if (compact != null) return compact;
|
|
3867
|
+
if (compact != null) return { ...compact, compactResponseItems: refs.length };
|
|
3793
3868
|
}
|
|
3794
|
-
return { opcode: OPCODES.flowValueMGet, payload };
|
|
3869
|
+
return { compactResponseItems: refs.length, opcode: OPCODES.flowValueMGet, payload };
|
|
3795
3870
|
}
|
|
3796
3871
|
function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
3797
3872
|
if (args.length < 2) return void 0;
|
|
@@ -3827,7 +3902,7 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3827
3902
|
if (items2 == null) return void 0;
|
|
3828
3903
|
const payload2 = { ...options, items: items2 };
|
|
3829
3904
|
if (!auto && !mixed) payload2.partition_key = partition;
|
|
3830
|
-
return { opcode: OPCODES.flowCreateMany, payload: payload2 };
|
|
3905
|
+
return { compactResponseItems: items2.length, opcode: OPCODES.flowCreateMany, payload: payload2 };
|
|
3831
3906
|
}
|
|
3832
3907
|
const rawItems = denseCommandArgumentTail(args, itemsIndex + 1, "ITEMS");
|
|
3833
3908
|
const width = mixed ? 3 : 2;
|
|
@@ -3841,7 +3916,9 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3841
3916
|
options,
|
|
3842
3917
|
maxBodyBytes
|
|
3843
3918
|
);
|
|
3844
|
-
if (compact != null)
|
|
3919
|
+
if (compact != null) {
|
|
3920
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
3921
|
+
}
|
|
3845
3922
|
}
|
|
3846
3923
|
const items = [];
|
|
3847
3924
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -3853,7 +3930,7 @@ function flowCreateManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
3853
3930
|
}
|
|
3854
3931
|
const payload = { ...options, items };
|
|
3855
3932
|
if (!auto && !mixed) payload.partition_key = partition;
|
|
3856
|
-
return { opcode: OPCODES.flowCreateMany, payload };
|
|
3933
|
+
return { compactResponseItems: items.length, opcode: OPCODES.flowCreateMany, payload };
|
|
3857
3934
|
}
|
|
3858
3935
|
function flowClaimDuePayload(args, maxBodyBytes, allowCompact) {
|
|
3859
3936
|
if (args.length < 1) return void 0;
|
|
@@ -4016,7 +4093,9 @@ function flowClaimedManyPayload(command, opcode, args, maxBodyBytes = Number.MAX
|
|
|
4016
4093
|
if (rawItems.length === 0 || rawItems.length % width !== 0) return void 0;
|
|
4017
4094
|
if (allowCompact) {
|
|
4018
4095
|
const compact = command === "FLOW.RETRY_MANY" ? compactFlowRetryManyPayload(partition, rawItems, mixed, auto, options, maxBodyBytes) : compactFlowCompleteManyPayload(opcode, partition, rawItems, mixed, auto, options, maxBodyBytes);
|
|
4019
|
-
if (compact != null)
|
|
4096
|
+
if (compact != null) {
|
|
4097
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
4098
|
+
}
|
|
4020
4099
|
}
|
|
4021
4100
|
const items = [];
|
|
4022
4101
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -4028,7 +4107,7 @@ function flowClaimedManyPayload(command, opcode, args, maxBodyBytes = Number.MAX
|
|
|
4028
4107
|
}
|
|
4029
4108
|
const payload = { ...options, items };
|
|
4030
4109
|
if (!auto && !mixed) payload.partition_key = partition;
|
|
4031
|
-
return { opcode, payload };
|
|
4110
|
+
return { compactResponseItems: items.length, opcode, payload };
|
|
4032
4111
|
}
|
|
4033
4112
|
function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
4034
4113
|
if (args.length < 4) return void 0;
|
|
@@ -4068,7 +4147,9 @@ function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
4068
4147
|
options,
|
|
4069
4148
|
maxBodyBytes
|
|
4070
4149
|
) : void 0;
|
|
4071
|
-
if (compact != null)
|
|
4150
|
+
if (compact != null) {
|
|
4151
|
+
return { ...compact, compactResponseItems: rawItems.length / width };
|
|
4152
|
+
}
|
|
4072
4153
|
}
|
|
4073
4154
|
const items = [];
|
|
4074
4155
|
for (let index = 0; index < rawItems.length; index += width) {
|
|
@@ -4088,7 +4169,11 @@ function flowTransitionManyPayload(args, maxBodyBytes, allowCompact) {
|
|
|
4088
4169
|
items
|
|
4089
4170
|
};
|
|
4090
4171
|
if (!mixed) payload.partition_key = args[0];
|
|
4091
|
-
return {
|
|
4172
|
+
return {
|
|
4173
|
+
compactResponseItems: items.length,
|
|
4174
|
+
opcode: OPCODES.flowTransitionMany,
|
|
4175
|
+
payload
|
|
4176
|
+
};
|
|
4092
4177
|
}
|
|
4093
4178
|
function flowSpawnChildrenPayload(args) {
|
|
4094
4179
|
if (args.length < 2) return void 0;
|
|
@@ -4131,13 +4216,6 @@ function flowSpawnChildrenPayload(args) {
|
|
|
4131
4216
|
payload: { id: args[0], ...options, children }
|
|
4132
4217
|
};
|
|
4133
4218
|
}
|
|
4134
|
-
function flowSearchPayload(args) {
|
|
4135
|
-
if (args.length < 1) return void 0;
|
|
4136
|
-
const payload = optionMap(args.slice(1));
|
|
4137
|
-
if (payload == null) return void 0;
|
|
4138
|
-
normalizeFlowSearchStateMeta(payload);
|
|
4139
|
-
return { opcode: OPCODES.flowSearch, payload: { type: args[0], ...payload } };
|
|
4140
|
-
}
|
|
4141
4219
|
|
|
4142
4220
|
// src/protocol-flow-signal.ts
|
|
4143
4221
|
function flowSignalPayload(args) {
|
|
@@ -4162,6 +4240,162 @@ function flowSignalPayload(args) {
|
|
|
4162
4240
|
return { opcode: OPCODES.flowSignal, payload: { id: args[0], ...options } };
|
|
4163
4241
|
}
|
|
4164
4242
|
|
|
4243
|
+
// src/protocol-flow-policy.ts
|
|
4244
|
+
import { Buffer as Buffer14 } from "buffer";
|
|
4245
|
+
var BACKOFF_FIELDS = {
|
|
4246
|
+
BASE_MS: "base_ms",
|
|
4247
|
+
MAX_MS: "max_ms",
|
|
4248
|
+
JITTER_PCT: "jitter_pct"
|
|
4249
|
+
};
|
|
4250
|
+
var RETENTION_FIELDS = {
|
|
4251
|
+
RETENTION_TTL: "ttl_ms",
|
|
4252
|
+
RETENTION_TTL_MS: "ttl_ms",
|
|
4253
|
+
HISTORY_MAX_EVENTS: "history_max_events"
|
|
4254
|
+
};
|
|
4255
|
+
function flowPolicySetPayload(args) {
|
|
4256
|
+
if (!hasOwnCommandArgument(args, 0, args.length, "Flow policy arguments")) return void 0;
|
|
4257
|
+
if (!isBinaryArgument(args[0])) return void 0;
|
|
4258
|
+
const payload = { type: args[0] };
|
|
4259
|
+
const states = {};
|
|
4260
|
+
let target = payload;
|
|
4261
|
+
for (let index = 1; index < args.length; index += 2) {
|
|
4262
|
+
if (!hasOwnCommandArgument(args, index, args.length, "Flow policy arguments") || !hasOwnCommandArgument(args, index + 1, args.length, "Flow policy arguments")) return void 0;
|
|
4263
|
+
const token = optionalText(args[index])?.toUpperCase();
|
|
4264
|
+
const value = args[index + 1];
|
|
4265
|
+
if (token == null || value == null) return void 0;
|
|
4266
|
+
if (token === "STATE") {
|
|
4267
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4268
|
+
const state = asText(value);
|
|
4269
|
+
target = {};
|
|
4270
|
+
setOwnValue2(states, state, target);
|
|
4271
|
+
setOwnValue2(payload, "states", states);
|
|
4272
|
+
continue;
|
|
4273
|
+
}
|
|
4274
|
+
if (token === "MODE") {
|
|
4275
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4276
|
+
const mode = optionalText(value)?.toLowerCase();
|
|
4277
|
+
if (target === payload || mode !== "fifo" && mode !== "parallel") return void 0;
|
|
4278
|
+
setOwnValue2(target, "mode", mode);
|
|
4279
|
+
continue;
|
|
4280
|
+
}
|
|
4281
|
+
if (token === "EXPECTED_GENERATION") {
|
|
4282
|
+
if (target !== payload) return void 0;
|
|
4283
|
+
const generation = integerOption(value);
|
|
4284
|
+
if (generation == null || generation < 0) return void 0;
|
|
4285
|
+
setOwnValue2(payload, "expected_generation", generation);
|
|
4286
|
+
continue;
|
|
4287
|
+
}
|
|
4288
|
+
if (token === "REPLACE") {
|
|
4289
|
+
if (target !== payload || !isBoolToken(value)) return void 0;
|
|
4290
|
+
setOwnValue2(payload, "replace", boolArg(value));
|
|
4291
|
+
continue;
|
|
4292
|
+
}
|
|
4293
|
+
if (token === "MAX_ACTIVE_MS") {
|
|
4294
|
+
if (target !== payload) return void 0;
|
|
4295
|
+
const maxActiveMs = maxActiveOption(value);
|
|
4296
|
+
if (maxActiveMs == null) return void 0;
|
|
4297
|
+
setOwnValue2(payload, "max_active_ms", maxActiveMs);
|
|
4298
|
+
continue;
|
|
4299
|
+
}
|
|
4300
|
+
if (token === "INDEXED_STATE_META") {
|
|
4301
|
+
if (target !== payload || !isBinaryArgument(value)) return void 0;
|
|
4302
|
+
setOwnValue2(payload, "indexed_state_meta", value);
|
|
4303
|
+
continue;
|
|
4304
|
+
}
|
|
4305
|
+
if (token === "INDEXED_ATTRIBUTES") {
|
|
4306
|
+
if (target !== payload) return void 0;
|
|
4307
|
+
const names = indexedAttributes(value);
|
|
4308
|
+
if (names == null) return void 0;
|
|
4309
|
+
setOwnValue2(payload, "indexed_attributes", names);
|
|
4310
|
+
continue;
|
|
4311
|
+
}
|
|
4312
|
+
if (token === "MAX_RETRIES") {
|
|
4313
|
+
const parsed = integerOption(value);
|
|
4314
|
+
if (parsed == null) return void 0;
|
|
4315
|
+
setOwnValue2(objectField(target, "retry"), "max_retries", parsed);
|
|
4316
|
+
continue;
|
|
4317
|
+
}
|
|
4318
|
+
if (token === "EXHAUSTED_TO") {
|
|
4319
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4320
|
+
setOwnValue2(objectField(target, "retry"), "exhausted_to", value);
|
|
4321
|
+
continue;
|
|
4322
|
+
}
|
|
4323
|
+
const backoffField = BACKOFF_FIELDS[token];
|
|
4324
|
+
if (backoffField != null) {
|
|
4325
|
+
const parsed = integerOption(value);
|
|
4326
|
+
if (parsed == null) return void 0;
|
|
4327
|
+
setOwnValue2(objectField(objectField(target, "retry"), "backoff"), backoffField, parsed);
|
|
4328
|
+
continue;
|
|
4329
|
+
}
|
|
4330
|
+
if (token === "BACKOFF") {
|
|
4331
|
+
if (!isBinaryArgument(value)) return void 0;
|
|
4332
|
+
const kind = optionalText(value)?.toLowerCase();
|
|
4333
|
+
if (kind == null) return void 0;
|
|
4334
|
+
setOwnValue2(objectField(objectField(target, "retry"), "backoff"), "kind", kind);
|
|
4335
|
+
continue;
|
|
4336
|
+
}
|
|
4337
|
+
const retentionField = RETENTION_FIELDS[token];
|
|
4338
|
+
if (retentionField != null) {
|
|
4339
|
+
if (target === payload) return void 0;
|
|
4340
|
+
const parsed = integerOption(value);
|
|
4341
|
+
if (parsed == null) return void 0;
|
|
4342
|
+
setOwnValue2(objectField(target, "retention"), retentionField, parsed);
|
|
4343
|
+
continue;
|
|
4344
|
+
}
|
|
4345
|
+
return void 0;
|
|
4346
|
+
}
|
|
4347
|
+
return { opcode: OPCODES.flowPolicySet, payload };
|
|
4348
|
+
}
|
|
4349
|
+
function flowPolicyGetPayload(args) {
|
|
4350
|
+
if (!hasOwnCommandArgument(args, 0, args.length, "Flow policy arguments")) return void 0;
|
|
4351
|
+
if (!isBinaryArgument(args[0])) return void 0;
|
|
4352
|
+
if (args.length !== 1 && args.length !== 3) return void 0;
|
|
4353
|
+
const payload = { type: args[0] };
|
|
4354
|
+
if (args.length === 3) {
|
|
4355
|
+
if (!hasOwnCommandArgument(args, 1, args.length, "Flow policy arguments") || !hasOwnCommandArgument(args, 2, args.length, "Flow policy arguments") || optionalText(args[1])?.toUpperCase() !== "STATE" || !isBinaryArgument(args[2])) return void 0;
|
|
4356
|
+
setOwnValue2(payload, "state", args[2]);
|
|
4357
|
+
}
|
|
4358
|
+
return { opcode: OPCODES.flowPolicyGet, payload };
|
|
4359
|
+
}
|
|
4360
|
+
function integerOption(value) {
|
|
4361
|
+
try {
|
|
4362
|
+
return safeIntegerNumberArg(value);
|
|
4363
|
+
} catch {
|
|
4364
|
+
return void 0;
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
function maxActiveOption(value) {
|
|
4368
|
+
if (isBinaryArgument(value) && asText(value).toLowerCase() === "infinity") {
|
|
4369
|
+
return "infinity";
|
|
4370
|
+
}
|
|
4371
|
+
return integerOption(value);
|
|
4372
|
+
}
|
|
4373
|
+
function isBinaryArgument(value) {
|
|
4374
|
+
return typeof value === "string" || Buffer14.isBuffer(value) || value instanceof Uint8Array;
|
|
4375
|
+
}
|
|
4376
|
+
function objectField(target, name) {
|
|
4377
|
+
const existing = Object.hasOwn(target, name) ? target[name] : void 0;
|
|
4378
|
+
if (typeof existing === "object" && existing != null && !Array.isArray(existing)) {
|
|
4379
|
+
return existing;
|
|
4380
|
+
}
|
|
4381
|
+
const value = {};
|
|
4382
|
+
setOwnValue2(target, name, value);
|
|
4383
|
+
return value;
|
|
4384
|
+
}
|
|
4385
|
+
function indexedAttributes(value) {
|
|
4386
|
+
if (Array.isArray(value)) {
|
|
4387
|
+
return value.every((item) => typeof item === "string") ? value : void 0;
|
|
4388
|
+
}
|
|
4389
|
+
const source = optionalText(value);
|
|
4390
|
+
if (source == null) return void 0;
|
|
4391
|
+
try {
|
|
4392
|
+
const parsed = JSON.parse(source);
|
|
4393
|
+
return Array.isArray(parsed) && parsed.every((item) => typeof item === "string") ? parsed : void 0;
|
|
4394
|
+
} catch {
|
|
4395
|
+
return void 0;
|
|
4396
|
+
}
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4165
4399
|
// src/protocol-connection-policy.ts
|
|
4166
4400
|
function assertCommandDoesNotRequirePinnedConnection(args) {
|
|
4167
4401
|
const outer = commandName(args[0]);
|
|
@@ -4209,7 +4443,7 @@ function commandRequiresOrderedPipelineExecution(args) {
|
|
|
4209
4443
|
}
|
|
4210
4444
|
|
|
4211
4445
|
// src/protocol-compact-request.ts
|
|
4212
|
-
import { Buffer as
|
|
4446
|
+
import { Buffer as Buffer15 } from "buffer";
|
|
4213
4447
|
function compactMsetPayload(args, maxBodyBytes) {
|
|
4214
4448
|
if (args.length % 2 !== 0) throw new FerricStoreError("MSET requires key/value pairs");
|
|
4215
4449
|
const minimum = 6 + args.length * 4;
|
|
@@ -4228,7 +4462,7 @@ function compactMsetPayload(args, maxBodyBytes) {
|
|
|
4228
4462
|
total += 4 + byteLength;
|
|
4229
4463
|
}
|
|
4230
4464
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4231
|
-
const out =
|
|
4465
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4232
4466
|
let offset = writeCompactPipelineHeader(out, 1, args.length / 2);
|
|
4233
4467
|
for (let index = 0; index < args.length; index += 1) {
|
|
4234
4468
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4252,7 +4486,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4252
4486
|
total += 4 + byteLength;
|
|
4253
4487
|
}
|
|
4254
4488
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4255
|
-
const out =
|
|
4489
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4256
4490
|
let offset = writeCompactPipelineHeader(out, mode, args.length);
|
|
4257
4491
|
for (let index = 0; index < args.length; index += 1) {
|
|
4258
4492
|
offset = writeBinaryValue(out, offset, args[index], byteLengths[index] ?? 0);
|
|
@@ -4262,7 +4496,7 @@ function compactKeyPipelinePayload(opcode, args, mode, maxBodyBytes) {
|
|
|
4262
4496
|
function compactPipelinePayload(commands, maxBodyBytes) {
|
|
4263
4497
|
if (commands.length === 0) {
|
|
4264
4498
|
assertCompactPayloadFits(6, maxBodyBytes);
|
|
4265
|
-
const out =
|
|
4499
|
+
const out = Buffer15.allocUnsafe(6);
|
|
4266
4500
|
writeCompactPipelineHeader(out, 128 | 2, 0);
|
|
4267
4501
|
return out;
|
|
4268
4502
|
}
|
|
@@ -4304,7 +4538,7 @@ function compactSetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4304
4538
|
total += 8 + keyByteLength + valueByteLength;
|
|
4305
4539
|
}
|
|
4306
4540
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4307
|
-
const out =
|
|
4541
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4308
4542
|
let offset = writeCompactPipelineHeader(out, 128 | 1, commands.length);
|
|
4309
4543
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4310
4544
|
offset = writeBinaryValue(out, offset, argumentValues[index * 2], argumentByteLengths[index * 2] ?? 0);
|
|
@@ -4339,7 +4573,7 @@ function compactGetPipelinePayload(commands, maxBodyBytes) {
|
|
|
4339
4573
|
total += 4 + keyByteLength;
|
|
4340
4574
|
}
|
|
4341
4575
|
assertCompactPayloadFits(total, maxBodyBytes);
|
|
4342
|
-
const out =
|
|
4576
|
+
const out = Buffer15.allocUnsafe(total);
|
|
4343
4577
|
let offset = writeCompactPipelineHeader(out, 128 | 2, commands.length);
|
|
4344
4578
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4345
4579
|
offset = writeBinaryValue(out, offset, keys[index], keyByteLengths[index] ?? 0);
|
|
@@ -4353,7 +4587,7 @@ function compactArgumentsEligible(args, sparseMessage) {
|
|
|
4353
4587
|
}
|
|
4354
4588
|
return true;
|
|
4355
4589
|
}
|
|
4356
|
-
function compactPipelineEligible(commands,
|
|
4590
|
+
function compactPipelineEligible(commands, commandName5, argumentCount) {
|
|
4357
4591
|
for (let index = 0; index < commands.length; index += 1) {
|
|
4358
4592
|
const command = commands[index];
|
|
4359
4593
|
if (!Object.hasOwn(commands, index) || !Array.isArray(command)) {
|
|
@@ -4365,7 +4599,7 @@ function compactPipelineEligible(commands, commandName4, argumentCount) {
|
|
|
4365
4599
|
throw new TypeError("pipeline command arguments must be dense");
|
|
4366
4600
|
}
|
|
4367
4601
|
}
|
|
4368
|
-
if (!commandNameIs(command[0],
|
|
4602
|
+
if (!commandNameIs(command[0], commandName5)) return false;
|
|
4369
4603
|
for (let argumentIndex = 1; argumentIndex < argumentCount; argumentIndex += 1) {
|
|
4370
4604
|
if (!isCompactBinaryScalar(command[argumentIndex])) return false;
|
|
4371
4605
|
}
|
|
@@ -4380,7 +4614,7 @@ function writeCompactPipelineHeader(out, mode, count) {
|
|
|
4380
4614
|
}
|
|
4381
4615
|
|
|
4382
4616
|
// src/protocol-kv.ts
|
|
4383
|
-
import { Buffer as
|
|
4617
|
+
import { Buffer as Buffer16 } from "buffer";
|
|
4384
4618
|
function collectionProtocolCommand(command, args) {
|
|
4385
4619
|
switch (command) {
|
|
4386
4620
|
case "CAS":
|
|
@@ -4451,8 +4685,8 @@ function stringSetPayload(args) {
|
|
|
4451
4685
|
if (value == null || token === "EX" && value > Math.floor(Number.MAX_SAFE_INTEGER / 1e3)) {
|
|
4452
4686
|
return void 0;
|
|
4453
4687
|
}
|
|
4454
|
-
const
|
|
4455
|
-
setOwnValue2(payload,
|
|
4688
|
+
const field3 = token === "EX" || token === "PX" ? "ttl" : token.toLowerCase();
|
|
4689
|
+
setOwnValue2(payload, field3, token === "EX" ? value * 1e3 : value);
|
|
4456
4690
|
expirySeen = true;
|
|
4457
4691
|
index += 2;
|
|
4458
4692
|
} else if (token === "NX") {
|
|
@@ -4551,25 +4785,25 @@ function hashSetCommand(args) {
|
|
|
4551
4785
|
if (!isBinaryCommandArgument(args[0]) || args.length < 3 || args.length % 2 !== 1) return void 0;
|
|
4552
4786
|
const fields = /* @__PURE__ */ Object.create(null);
|
|
4553
4787
|
for (let index = 1; index < args.length; index += 2) {
|
|
4554
|
-
const
|
|
4788
|
+
const field3 = args[index];
|
|
4555
4789
|
const value = args[index + 1];
|
|
4556
|
-
if (typeof
|
|
4557
|
-
setOwnValue2(fields,
|
|
4790
|
+
if (typeof field3 !== "string" || !isBinaryCommandArgument(value)) return void 0;
|
|
4791
|
+
setOwnValue2(fields, field3, value);
|
|
4558
4792
|
}
|
|
4559
4793
|
return { opcode: COMMAND_OPCODES.HSET, payload: { fields, key: args[0] } };
|
|
4560
4794
|
}
|
|
4561
4795
|
function keyOnlyCommand(opcode, args) {
|
|
4562
4796
|
return args.length === 1 && isBinaryCommandArgument(args[0]) ? { opcode, payload: { key: args[0] } } : void 0;
|
|
4563
4797
|
}
|
|
4564
|
-
function binaryFieldsCommand(opcode, args,
|
|
4798
|
+
function binaryFieldsCommand(opcode, args, field3, length) {
|
|
4565
4799
|
if (args.length !== length || !isBinaryCommandArgument(args[0]) || !isBinaryCommandArgument(args[1])) return void 0;
|
|
4566
|
-
return { opcode, payload: { [
|
|
4800
|
+
return { opcode, payload: { [field3]: args[1], key: args[0] } };
|
|
4567
4801
|
}
|
|
4568
|
-
function binaryListCommand(opcode, args,
|
|
4802
|
+
function binaryListCommand(opcode, args, field3) {
|
|
4569
4803
|
if (!isBinaryCommandArgument(args[0]) || args.length < 2) return void 0;
|
|
4570
4804
|
const values = args.slice(1);
|
|
4571
4805
|
if (!values.every(isBinaryCommandArgument)) return void 0;
|
|
4572
|
-
return { opcode, payload: { [
|
|
4806
|
+
return { opcode, payload: { [field3]: values, key: args[0] } };
|
|
4573
4807
|
}
|
|
4574
4808
|
function listPopCommand(opcode, args) {
|
|
4575
4809
|
if (!isBinaryCommandArgument(args[0]) || args.length !== 1 && args.length !== 2) return void 0;
|
|
@@ -4627,17 +4861,35 @@ function parsedNumber(value) {
|
|
|
4627
4861
|
}
|
|
4628
4862
|
}
|
|
4629
4863
|
function isBinaryCommandArgument(value) {
|
|
4630
|
-
return typeof value === "string" ||
|
|
4864
|
+
return typeof value === "string" || Buffer16.isBuffer(value);
|
|
4631
4865
|
}
|
|
4632
4866
|
function isDirectKvValueArgument(value) {
|
|
4633
4867
|
return isBinaryCommandArgument(value) || typeof value === "object" && value != null;
|
|
4634
4868
|
}
|
|
4635
4869
|
function binaryToken(value) {
|
|
4636
|
-
return typeof value === "string" ? value.toUpperCase() :
|
|
4870
|
+
return typeof value === "string" ? value.toUpperCase() : Buffer16.isBuffer(value) ? value.toString("utf8").toUpperCase() : void 0;
|
|
4871
|
+
}
|
|
4872
|
+
|
|
4873
|
+
// src/protocol-value.ts
|
|
4874
|
+
import { Buffer as Buffer17 } from "buffer";
|
|
4875
|
+
|
|
4876
|
+
// src/protocol-map-key.ts
|
|
4877
|
+
import { isUtf8 } from "buffer";
|
|
4878
|
+
function setProtocolMapEntry(target, encodedKey, value) {
|
|
4879
|
+
if (typeof encodedKey === "string" && !encodedKey.isWellFormed()) {
|
|
4880
|
+
throw new FerricStoreError("native protocol map key must be valid UTF-8");
|
|
4881
|
+
}
|
|
4882
|
+
if (typeof encodedKey !== "string" && !isUtf8(encodedKey)) {
|
|
4883
|
+
throw new FerricStoreError("native protocol map key must be valid UTF-8");
|
|
4884
|
+
}
|
|
4885
|
+
const key = typeof encodedKey === "string" ? encodedKey : encodedKey.toString("utf8");
|
|
4886
|
+
if (Object.hasOwn(target, key)) {
|
|
4887
|
+
throw new FerricStoreError(`native protocol response contains duplicate map key ${JSON.stringify(key)}`);
|
|
4888
|
+
}
|
|
4889
|
+
setOwnValue2(target, key, value);
|
|
4637
4890
|
}
|
|
4638
4891
|
|
|
4639
4892
|
// src/protocol-value.ts
|
|
4640
|
-
import { Buffer as Buffer15 } from "buffer";
|
|
4641
4893
|
function planValueWithLimit(value, maxBytes) {
|
|
4642
4894
|
const budget = {
|
|
4643
4895
|
maxBytes,
|
|
@@ -4692,7 +4944,7 @@ function planContainerValue(value, budget, ancestors, depth) {
|
|
|
4692
4944
|
let byteLength = 5;
|
|
4693
4945
|
let index = 0;
|
|
4694
4946
|
for (const [key, item] of entries) {
|
|
4695
|
-
const keyByteLength =
|
|
4947
|
+
const keyByteLength = Buffer17.byteLength(key);
|
|
4696
4948
|
consumeEncodeBytes(budget, 4 + keyByteLength);
|
|
4697
4949
|
const valuePlan = planValueAt(item, budget, ancestors, depth + 1);
|
|
4698
4950
|
entryPlans[index] = { key, keyByteLength, value: valuePlan };
|
|
@@ -4731,17 +4983,21 @@ function planScalarValue(value, budget) {
|
|
|
4731
4983
|
return { byteLength: 9, tag: 3, value: BigInt(value) };
|
|
4732
4984
|
}
|
|
4733
4985
|
if (typeof value === "bigint") {
|
|
4734
|
-
if (value
|
|
4735
|
-
|
|
4986
|
+
if (value >= MIN_I642 && value <= MAX_I642) {
|
|
4987
|
+
consumeEncodeBytes(budget, 9);
|
|
4988
|
+
return { byteLength: 9, tag: 3, value };
|
|
4736
4989
|
}
|
|
4737
|
-
|
|
4738
|
-
|
|
4990
|
+
if (value > MAX_I642 && value <= MAX_U64) {
|
|
4991
|
+
consumeEncodeBytes(budget, 9);
|
|
4992
|
+
return { byteLength: 9, tag: 8, value };
|
|
4993
|
+
}
|
|
4994
|
+
throw new FerricStoreError("integer exceeds the signed or unsigned 64-bit native range");
|
|
4739
4995
|
}
|
|
4740
4996
|
if (typeof value === "number") {
|
|
4741
4997
|
consumeEncodeBytes(budget, 9);
|
|
4742
4998
|
return { byteLength: 9, tag: 7, value };
|
|
4743
4999
|
}
|
|
4744
|
-
if (typeof value === "string" ||
|
|
5000
|
+
if (typeof value === "string" || Buffer17.isBuffer(value) || value instanceof Uint8Array) {
|
|
4745
5001
|
const valueByteLength = binaryValueByteLength(value);
|
|
4746
5002
|
const byteLength = 5 + valueByteLength;
|
|
4747
5003
|
consumeEncodeBytes(budget, byteLength);
|
|
@@ -4765,7 +5021,7 @@ function writeValuePlan(output, start, plan) {
|
|
|
4765
5021
|
offset += 4;
|
|
4766
5022
|
if (typeof plan.value === "string") {
|
|
4767
5023
|
output.write(plan.value, offset, plan.valueByteLength, "utf8");
|
|
4768
|
-
} else if (
|
|
5024
|
+
} else if (Buffer17.isBuffer(plan.value)) {
|
|
4769
5025
|
plan.value.copy(output, offset);
|
|
4770
5026
|
} else {
|
|
4771
5027
|
output.set(plan.value, offset);
|
|
@@ -4790,6 +5046,9 @@ function writeValuePlan(output, start, plan) {
|
|
|
4790
5046
|
case 7:
|
|
4791
5047
|
output.writeDoubleBE(plan.value, offset);
|
|
4792
5048
|
return offset + 8;
|
|
5049
|
+
case 8:
|
|
5050
|
+
output.writeBigUInt64BE(plan.value, offset);
|
|
5051
|
+
return offset + 8;
|
|
4793
5052
|
}
|
|
4794
5053
|
}
|
|
4795
5054
|
function consumeEncodeBytes(budget, bytes2) {
|
|
@@ -4847,7 +5106,7 @@ function decodeValueAt(data, offset, limits, budget, depth) {
|
|
|
4847
5106
|
const key = readBinary(data, offset);
|
|
4848
5107
|
offset = key.offset;
|
|
4849
5108
|
const item = decodeValueAt(data, offset, limits, budget, depth + 1);
|
|
4850
|
-
|
|
5109
|
+
setProtocolMapEntry(value, key.value, item.value);
|
|
4851
5110
|
offset = item.offset;
|
|
4852
5111
|
}
|
|
4853
5112
|
return { value, offset };
|
|
@@ -4856,6 +5115,14 @@ function decodeValueAt(data, offset, limits, budget, depth) {
|
|
|
4856
5115
|
requireAvailable(data, offset, 8);
|
|
4857
5116
|
return { value: data.readDoubleBE(offset), offset: offset + 8 };
|
|
4858
5117
|
}
|
|
5118
|
+
if (tag === 8) {
|
|
5119
|
+
requireAvailable(data, offset, 8);
|
|
5120
|
+
const integer2 = data.readBigUInt64BE(offset);
|
|
5121
|
+
return {
|
|
5122
|
+
value: integer2 <= MAX_SAFE_INTEGER_BIGINT ? Number(integer2) : integer2,
|
|
5123
|
+
offset: offset + 8
|
|
5124
|
+
};
|
|
5125
|
+
}
|
|
4859
5126
|
throw new FerricStoreError(`unknown protocol value tag ${tag}`);
|
|
4860
5127
|
}
|
|
4861
5128
|
function decodeValueWithBudget(data, offset, budget) {
|
|
@@ -4899,20 +5166,20 @@ function requireAvailable(data, offset, size) {
|
|
|
4899
5166
|
}
|
|
4900
5167
|
|
|
4901
5168
|
// src/key-slot-validation.ts
|
|
4902
|
-
import { Buffer as
|
|
5169
|
+
import { Buffer as Buffer19 } from "buffer";
|
|
4903
5170
|
|
|
4904
5171
|
// src/topology-utilities.ts
|
|
4905
|
-
import { Buffer as
|
|
5172
|
+
import { Buffer as Buffer18 } from "buffer";
|
|
4906
5173
|
function isPlainObject3(value) {
|
|
4907
|
-
return typeof value === "object" && value != null && !Array.isArray(value) && !
|
|
5174
|
+
return typeof value === "object" && value != null && !Array.isArray(value) && !Buffer18.isBuffer(value);
|
|
4908
5175
|
}
|
|
4909
5176
|
function getField(source, ...keys) {
|
|
4910
5177
|
if (source instanceof Map) {
|
|
4911
5178
|
for (const key of keys) {
|
|
4912
5179
|
if (source.has(key)) return source.get(key);
|
|
4913
|
-
const bufferKey =
|
|
5180
|
+
const bufferKey = Buffer18.from(key);
|
|
4914
5181
|
for (const [itemKey, value] of source.entries()) {
|
|
4915
|
-
if (
|
|
5182
|
+
if (Buffer18.isBuffer(itemKey) && itemKey.equals(bufferKey)) return value;
|
|
4916
5183
|
}
|
|
4917
5184
|
}
|
|
4918
5185
|
return void 0;
|
|
@@ -4926,14 +5193,14 @@ function getField(source, ...keys) {
|
|
|
4926
5193
|
}
|
|
4927
5194
|
function textOrUndefined(value) {
|
|
4928
5195
|
if (typeof value === "string") return value;
|
|
4929
|
-
if (
|
|
5196
|
+
if (Buffer18.isBuffer(value)) return value.toString("utf8");
|
|
4930
5197
|
return void 0;
|
|
4931
5198
|
}
|
|
4932
5199
|
function numberOrUndefined(value) {
|
|
4933
5200
|
return typeof value === "number" && Number.isSafeInteger(value) ? value : void 0;
|
|
4934
5201
|
}
|
|
4935
|
-
function nativeEventName(
|
|
4936
|
-
return textOrUndefined(getField(
|
|
5202
|
+
function nativeEventName(event2) {
|
|
5203
|
+
return textOrUndefined(getField(event2.value, "event"))?.toUpperCase();
|
|
4937
5204
|
}
|
|
4938
5205
|
function endpointFromRange(item) {
|
|
4939
5206
|
const endpointValue = getField(item, "endpoint");
|
|
@@ -5101,7 +5368,7 @@ function stringHashRange(key) {
|
|
|
5101
5368
|
var validatedCommands = /* @__PURE__ */ new WeakSet();
|
|
5102
5369
|
function assertAtomicKeyValueCommandSharesSlot(args) {
|
|
5103
5370
|
const value = args[0];
|
|
5104
|
-
const command = (typeof value === "string" ? value :
|
|
5371
|
+
const command = (typeof value === "string" ? value : Buffer19.isBuffer(value) ? value.toString("utf8") : "").toUpperCase();
|
|
5105
5372
|
if (command === "MSET" || command === "MSETNX") {
|
|
5106
5373
|
assertKeyValueCommandSharesSlot(args, command);
|
|
5107
5374
|
}
|
|
@@ -5111,7 +5378,7 @@ function assertKeyValueCommandSharesSlot(args, command) {
|
|
|
5111
5378
|
let expectedSlot;
|
|
5112
5379
|
for (let index = 1; index < args.length; index += 2) {
|
|
5113
5380
|
const key = args[index];
|
|
5114
|
-
if (typeof key !== "string" && !
|
|
5381
|
+
if (typeof key !== "string" && !Buffer19.isBuffer(key)) return;
|
|
5115
5382
|
const slot = routingSlotForKey(key);
|
|
5116
5383
|
expectedSlot ??= slot;
|
|
5117
5384
|
if (slot !== expectedSlot) {
|
|
@@ -5122,62 +5389,202 @@ function assertKeyValueCommandSharesSlot(args, command) {
|
|
|
5122
5389
|
}
|
|
5123
5390
|
|
|
5124
5391
|
// src/protocol-response.ts
|
|
5125
|
-
import { Buffer as
|
|
5392
|
+
import { Buffer as Buffer26 } from "buffer";
|
|
5126
5393
|
|
|
5127
5394
|
// src/protocol-compact-response.ts
|
|
5128
|
-
import { Buffer as
|
|
5395
|
+
import { Buffer as Buffer25 } from "buffer";
|
|
5129
5396
|
|
|
5130
5397
|
// src/native-negotiation.ts
|
|
5131
|
-
import { Buffer as
|
|
5398
|
+
import { Buffer as Buffer20 } from "buffer";
|
|
5132
5399
|
var EMPTY_COMPACT_RESPONSE_OPCODES = /* @__PURE__ */ new Map();
|
|
5133
5400
|
function nativeNegotiation(value) {
|
|
5134
5401
|
const capabilities = field(value, "capabilities") ?? value;
|
|
5135
5402
|
const limits = field(capabilities, "limits");
|
|
5136
|
-
const
|
|
5403
|
+
const rawResponseCodecs = field(capabilities, "response_codecs");
|
|
5404
|
+
const responseCodecs = rawResponseCodecs == null ? void 0 : requiredMap(rawResponseCodecs, "HELLO response_codecs");
|
|
5405
|
+
const schemas = requiredMap(field(capabilities, "schemas"), "HELLO schemas");
|
|
5137
5406
|
const maxResponseBytes = positiveSafeInteger3(field(limits, "max_response_bytes"));
|
|
5138
5407
|
return {
|
|
5139
5408
|
compactResponseOpcodes: parseCompactResponseOpcodes(
|
|
5140
5409
|
field(responseCodecs, "compact_response_opcodes")
|
|
5141
5410
|
),
|
|
5411
|
+
flowQuery: parseFlowQueryNegotiation(capabilities, schemas),
|
|
5142
5412
|
...maxResponseBytes == null ? {} : { maxResponseBytes }
|
|
5143
5413
|
};
|
|
5144
5414
|
}
|
|
5415
|
+
var REQUIRED_FLOW_QUERY_CAPABILITIES = /* @__PURE__ */ new Set([
|
|
5416
|
+
"flow_query_v1",
|
|
5417
|
+
"flow_query_result_projection_v1",
|
|
5418
|
+
"flow_explain_v1",
|
|
5419
|
+
"flow_explain_analyze_v1",
|
|
5420
|
+
"flow_composite_index_v1",
|
|
5421
|
+
"flow_query_index_status_v1"
|
|
5422
|
+
]);
|
|
5423
|
+
var REQUIRED_FLOW_QUERY_SHAPES = /* @__PURE__ */ new Set([
|
|
5424
|
+
"runs_by_run_id_record",
|
|
5425
|
+
"runs_by_partition_and_run_id_record",
|
|
5426
|
+
"runs_by_partition_predicates_ordered_records",
|
|
5427
|
+
"runs_by_partition_type_state_ordered_records",
|
|
5428
|
+
"runs_by_partition_type_terminals_ordered_records",
|
|
5429
|
+
"runs_by_partition_metadata_ordered_records",
|
|
5430
|
+
"runs_by_partition_type_running_lease_deadline_ordered_records",
|
|
5431
|
+
"runs_by_partition_parent_ordered_records",
|
|
5432
|
+
"runs_by_partition_root_ordered_records",
|
|
5433
|
+
"runs_by_partition_correlation_ordered_records",
|
|
5434
|
+
"runs_by_partition_predicates_count",
|
|
5435
|
+
"events_by_run_id_ordered_records"
|
|
5436
|
+
]);
|
|
5437
|
+
function parseFlowQueryNegotiation(capabilities, schemas) {
|
|
5438
|
+
const manifest = requiredMap(field(capabilities, "flow_query"), "HELLO flow_query");
|
|
5439
|
+
const requestContract = requiredBoundedText(manifest, "request_contract");
|
|
5440
|
+
const resultContract = requiredBoundedText(manifest, "result_contract");
|
|
5441
|
+
const explainContract = requiredBoundedText(manifest, "explain_contract");
|
|
5442
|
+
const indexStatusContract = requiredBoundedText(manifest, "index_status_contract");
|
|
5443
|
+
requireEqual(requestContract, "ferric.flow.query.request/v1", "flow_query request_contract");
|
|
5444
|
+
requireEqual(resultContract, "ferric.flow.query.result/v1", "flow_query result_contract");
|
|
5445
|
+
requireEqual(explainContract, "ferric.flow.explain/v1", "flow_query explain_contract");
|
|
5446
|
+
requireEqual(
|
|
5447
|
+
indexStatusContract,
|
|
5448
|
+
"ferric.flow.query.indexes/v1",
|
|
5449
|
+
"flow_query index_status_contract"
|
|
5450
|
+
);
|
|
5451
|
+
const queryCapabilities = boundedTextSet(manifest, "capabilities", 64);
|
|
5452
|
+
const languageVersions = boundedTextSet(manifest, "language_versions", 16);
|
|
5453
|
+
const shapes = boundedTextSet(manifest, "shapes", 128);
|
|
5454
|
+
requireMembers(queryCapabilities, REQUIRED_FLOW_QUERY_CAPABILITIES, "flow_query capability");
|
|
5455
|
+
requireMembers(languageVersions, /* @__PURE__ */ new Set(["FQL1"]), "flow_query language");
|
|
5456
|
+
requireMembers(shapes, REQUIRED_FLOW_QUERY_SHAPES, "flow_query shape");
|
|
5457
|
+
const schema = requiredMap(field(schemas, "FLOW.QUERY"), "HELLO FLOW.QUERY schema");
|
|
5458
|
+
const fields = boundedTextSet(schema, "fields", 64);
|
|
5459
|
+
requireMembers(
|
|
5460
|
+
fields,
|
|
5461
|
+
/* @__PURE__ */ new Set(["version", "query", "params", "deadline_ms"]),
|
|
5462
|
+
"FLOW.QUERY schema field"
|
|
5463
|
+
);
|
|
5464
|
+
const required = boundedTextSet(schema, "required", 16);
|
|
5465
|
+
if (required.size !== 2 || !required.has("version") || !required.has("query")) {
|
|
5466
|
+
throw incompatibleServer("FLOW.QUERY schema must require exactly version and query");
|
|
5467
|
+
}
|
|
5468
|
+
return {
|
|
5469
|
+
requestContract: "ferric.flow.query.request/v1",
|
|
5470
|
+
resultContract: "ferric.flow.query.result/v1",
|
|
5471
|
+
explainContract: "ferric.flow.explain/v1",
|
|
5472
|
+
indexStatusContract: "ferric.flow.query.indexes/v1",
|
|
5473
|
+
capabilities: queryCapabilities,
|
|
5474
|
+
languageVersions,
|
|
5475
|
+
shapes
|
|
5476
|
+
};
|
|
5477
|
+
}
|
|
5478
|
+
function requiredMap(value, context) {
|
|
5479
|
+
if (value instanceof Map) return value;
|
|
5480
|
+
if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer20.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
5481
|
+
return value;
|
|
5482
|
+
}
|
|
5483
|
+
throw incompatibleServer(`${context} is missing or invalid`);
|
|
5484
|
+
}
|
|
5485
|
+
function requiredBoundedText(mapping, name) {
|
|
5486
|
+
const value = strictText(field(mapping, name));
|
|
5487
|
+
if (value == null || value.length === 0 || Buffer20.byteLength(value) > 256) {
|
|
5488
|
+
throw incompatibleServer(`HELLO flow_query ${name} must be bounded non-empty text`);
|
|
5489
|
+
}
|
|
5490
|
+
return value;
|
|
5491
|
+
}
|
|
5492
|
+
function boundedTextSet(mapping, name, maximum) {
|
|
5493
|
+
const raw = field(mapping, name);
|
|
5494
|
+
if (!Array.isArray(raw) || raw.length < 1 || raw.length > maximum) {
|
|
5495
|
+
throw incompatibleServer(`HELLO ${name} must contain 1..${maximum} entries`);
|
|
5496
|
+
}
|
|
5497
|
+
const result = /* @__PURE__ */ new Set();
|
|
5498
|
+
for (let index = 0; index < raw.length; index += 1) {
|
|
5499
|
+
if (!Object.hasOwn(raw, index)) throw incompatibleServer(`HELLO ${name} must be dense`);
|
|
5500
|
+
const item = strictText(raw[index]);
|
|
5501
|
+
if (item == null || item.length === 0 || Buffer20.byteLength(item) > 256) {
|
|
5502
|
+
throw incompatibleServer(`HELLO ${name} contains invalid text`);
|
|
5503
|
+
}
|
|
5504
|
+
if (result.has(item)) throw incompatibleServer(`HELLO ${name} contains duplicate ${item}`);
|
|
5505
|
+
result.add(item);
|
|
5506
|
+
}
|
|
5507
|
+
return result;
|
|
5508
|
+
}
|
|
5509
|
+
function requireMembers(actual, required, context) {
|
|
5510
|
+
for (const item of required) {
|
|
5511
|
+
if (!actual.has(item)) throw incompatibleServer(`missing ${context} ${JSON.stringify(item)}`);
|
|
5512
|
+
}
|
|
5513
|
+
}
|
|
5514
|
+
function requireEqual(actual, expected, context) {
|
|
5515
|
+
if (actual !== expected) throw incompatibleServer(`${context} must be ${JSON.stringify(expected)}`);
|
|
5516
|
+
}
|
|
5517
|
+
function strictText(value) {
|
|
5518
|
+
if (typeof value === "string") return value;
|
|
5519
|
+
if (Buffer20.isBuffer(value) || value instanceof Uint8Array) {
|
|
5520
|
+
try {
|
|
5521
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
5522
|
+
} catch {
|
|
5523
|
+
return void 0;
|
|
5524
|
+
}
|
|
5525
|
+
}
|
|
5526
|
+
return void 0;
|
|
5527
|
+
}
|
|
5528
|
+
function incompatibleServer(message) {
|
|
5529
|
+
return new FerricStoreError(`incompatible FerricStore server: ${message}`);
|
|
5530
|
+
}
|
|
5145
5531
|
function compactResponseOpcodeSupports(capabilities, codec, opcode) {
|
|
5146
5532
|
return capabilities?.get(codec)?.has(opcode) === true;
|
|
5147
5533
|
}
|
|
5148
5534
|
function parseCompactResponseOpcodes(value) {
|
|
5535
|
+
if (value == null) return EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
5149
5536
|
const entries = mapEntries(value);
|
|
5150
|
-
if (entries == null)
|
|
5537
|
+
if (entries == null) {
|
|
5538
|
+
throw incompatibleServer("HELLO compact_response_opcodes must be a map");
|
|
5539
|
+
}
|
|
5540
|
+
if (entries.length > 32) {
|
|
5541
|
+
throw incompatibleServer("HELLO compact_response_opcodes supports at most 32 codecs");
|
|
5542
|
+
}
|
|
5151
5543
|
const result = /* @__PURE__ */ new Map();
|
|
5544
|
+
let totalOpcodes = 0;
|
|
5152
5545
|
for (const [rawName, rawOpcodes] of entries) {
|
|
5153
|
-
const name =
|
|
5154
|
-
if (name == null || name.length === 0 ||
|
|
5546
|
+
const name = strictText(rawName);
|
|
5547
|
+
if (name == null || name.length === 0 || Buffer20.byteLength(name) > 128) {
|
|
5548
|
+
throw incompatibleServer("HELLO compact_response_opcodes contains an invalid codec name");
|
|
5549
|
+
}
|
|
5550
|
+
if (result.has(name)) {
|
|
5551
|
+
throw incompatibleServer(`HELLO compact_response_opcodes contains duplicate codec ${name}`);
|
|
5552
|
+
}
|
|
5553
|
+
if (!Array.isArray(rawOpcodes)) {
|
|
5554
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} must be an array`);
|
|
5555
|
+
}
|
|
5556
|
+
totalOpcodes += rawOpcodes.length;
|
|
5557
|
+
if (totalOpcodes > 1024) {
|
|
5558
|
+
throw incompatibleServer("HELLO compact_response_opcodes supports at most 1024 opcodes");
|
|
5559
|
+
}
|
|
5155
5560
|
const opcodes = /* @__PURE__ */ new Set();
|
|
5156
|
-
let valid = true;
|
|
5157
5561
|
for (let index = 0; index < rawOpcodes.length; index += 1) {
|
|
5158
5562
|
if (!Object.hasOwn(rawOpcodes, index)) {
|
|
5159
|
-
|
|
5160
|
-
break;
|
|
5563
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} must be dense`);
|
|
5161
5564
|
}
|
|
5162
|
-
const opcode =
|
|
5565
|
+
const opcode = strictUnsigned16(rawOpcodes[index]);
|
|
5163
5566
|
if (opcode == null) {
|
|
5164
|
-
|
|
5165
|
-
|
|
5567
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} has invalid opcode`);
|
|
5568
|
+
}
|
|
5569
|
+
if (opcodes.has(opcode)) {
|
|
5570
|
+
throw incompatibleServer(`HELLO compact_response_opcodes codec ${name} has duplicate opcode`);
|
|
5166
5571
|
}
|
|
5167
5572
|
opcodes.add(opcode);
|
|
5168
5573
|
}
|
|
5169
|
-
|
|
5574
|
+
result.set(name, opcodes);
|
|
5170
5575
|
}
|
|
5171
5576
|
return result;
|
|
5172
5577
|
}
|
|
5173
5578
|
function mapEntries(value) {
|
|
5174
5579
|
if (value instanceof Map) return [...value.entries()];
|
|
5175
|
-
if (typeof value !== "object" || value == null || Array.isArray(value)) return void 0;
|
|
5580
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer20.isBuffer(value) || value instanceof Uint8Array) return void 0;
|
|
5176
5581
|
return Object.entries(value);
|
|
5177
5582
|
}
|
|
5178
|
-
function
|
|
5179
|
-
|
|
5180
|
-
|
|
5583
|
+
function strictUnsigned16(value) {
|
|
5584
|
+
if (typeof value === "bigint") {
|
|
5585
|
+
return value >= 0n && value <= 0xffffn ? Number(value) : void 0;
|
|
5586
|
+
}
|
|
5587
|
+
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 65535 ? value : void 0;
|
|
5181
5588
|
}
|
|
5182
5589
|
function positiveSafeInteger3(value) {
|
|
5183
5590
|
const parsed = nonNegativeSafeInteger2(value);
|
|
@@ -5196,8 +5603,8 @@ function nonNegativeSafeInteger2(value) {
|
|
|
5196
5603
|
}
|
|
5197
5604
|
function text2(value) {
|
|
5198
5605
|
if (typeof value === "string") return value;
|
|
5199
|
-
if (
|
|
5200
|
-
return
|
|
5606
|
+
if (Buffer20.isBuffer(value) || value instanceof Uint8Array) {
|
|
5607
|
+
return Buffer20.from(value).toString("utf8");
|
|
5201
5608
|
}
|
|
5202
5609
|
return void 0;
|
|
5203
5610
|
}
|
|
@@ -5268,7 +5675,7 @@ function readCompactBinaryMap(data, offset, budget) {
|
|
|
5268
5675
|
for (let index = 0; index < count; index += 1) {
|
|
5269
5676
|
const key = readBinary(data, offset);
|
|
5270
5677
|
const value = readBinary(data, key.offset);
|
|
5271
|
-
|
|
5678
|
+
setProtocolMapEntry(values, key.value, value.value);
|
|
5272
5679
|
offset = value.offset;
|
|
5273
5680
|
}
|
|
5274
5681
|
return { value: values, offset };
|
|
@@ -5284,11 +5691,246 @@ function requireCompactContainer(count, budget) {
|
|
|
5284
5691
|
consumeDecodeItems(count, budget);
|
|
5285
5692
|
}
|
|
5286
5693
|
|
|
5287
|
-
// src/protocol-
|
|
5288
|
-
|
|
5694
|
+
// src/protocol-error-message.ts
|
|
5695
|
+
import { Buffer as Buffer22 } from "buffer";
|
|
5696
|
+
var MAX_ERROR_MESSAGE_CHARS = 4096;
|
|
5697
|
+
var MAX_ERROR_TEXT_BYTES = MAX_ERROR_MESSAGE_CHARS * 4;
|
|
5698
|
+
function protocolErrorMessage(status, value) {
|
|
5699
|
+
const direct = errorText(value);
|
|
5700
|
+
if (direct != null) return truncate(direct);
|
|
5701
|
+
return truncate(`ERR native request failed status=${status}: ${errorDescription(value)}`);
|
|
5702
|
+
}
|
|
5703
|
+
function errorText(value) {
|
|
5704
|
+
if (typeof value === "string") return value;
|
|
5705
|
+
if (Buffer22.isBuffer(value) || value instanceof Uint8Array) {
|
|
5706
|
+
return boundedBinaryText(value);
|
|
5707
|
+
}
|
|
5708
|
+
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5709
|
+
const message = value.message;
|
|
5710
|
+
if (typeof message === "string") return message;
|
|
5711
|
+
if (Buffer22.isBuffer(message) || message instanceof Uint8Array) {
|
|
5712
|
+
return boundedBinaryText(message);
|
|
5713
|
+
}
|
|
5714
|
+
if (message == null || typeof message !== "object") return String(message);
|
|
5715
|
+
}
|
|
5716
|
+
return void 0;
|
|
5717
|
+
}
|
|
5718
|
+
function boundedBinaryText(value) {
|
|
5719
|
+
const bytes2 = Buffer22.isBuffer(value) ? value : Buffer22.from(value.buffer, value.byteOffset, value.byteLength);
|
|
5720
|
+
return bytes2.subarray(0, MAX_ERROR_TEXT_BYTES).toString("utf8");
|
|
5721
|
+
}
|
|
5722
|
+
function errorDescription(value) {
|
|
5723
|
+
if (Array.isArray(value)) return `[array length=${value.length}]`;
|
|
5724
|
+
if (value instanceof Map) return `[map size=${value.size}]`;
|
|
5725
|
+
if (typeof value === "object" && value != null) return "[object]";
|
|
5726
|
+
return String(value);
|
|
5727
|
+
}
|
|
5728
|
+
function truncate(value) {
|
|
5729
|
+
return value.length <= MAX_ERROR_MESSAGE_CHARS ? value : `${value.slice(0, MAX_ERROR_MESSAGE_CHARS - 1)}\u2026`;
|
|
5730
|
+
}
|
|
5731
|
+
|
|
5732
|
+
// src/protocol-flow-query-result.ts
|
|
5733
|
+
import { Buffer as Buffer24 } from "buffer";
|
|
5734
|
+
|
|
5735
|
+
// src/protocol-binary-detacher.ts
|
|
5736
|
+
import { Buffer as Buffer23 } from "buffer";
|
|
5737
|
+
var MIN_PINNED_BACKING_BYTES = 64;
|
|
5738
|
+
function detachDecodedBinary(value, backingBytes) {
|
|
5739
|
+
if (Buffer23.isBuffer(value)) return detachBuffer(value, backingBytes);
|
|
5740
|
+
if (Array.isArray(value)) {
|
|
5741
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
5742
|
+
value[index] = detachDecodedBinary(value[index], backingBytes);
|
|
5743
|
+
}
|
|
5744
|
+
return value;
|
|
5745
|
+
}
|
|
5746
|
+
if (!isDecodedRecord(value)) return value;
|
|
5747
|
+
for (const key of Object.keys(value)) {
|
|
5748
|
+
setOwnValue2(value, key, detachDecodedBinary(value[key], backingBytes));
|
|
5749
|
+
}
|
|
5750
|
+
return value;
|
|
5751
|
+
}
|
|
5752
|
+
function detachBuffer(value, backingBytes) {
|
|
5753
|
+
if (backingBytes <= Math.max(MIN_PINNED_BACKING_BYTES, value.byteLength * 2)) {
|
|
5754
|
+
return value;
|
|
5755
|
+
}
|
|
5756
|
+
if (value.byteLength === 0) return Buffer23.alloc(0);
|
|
5757
|
+
const detached = Buffer23.allocUnsafeSlow(value.byteLength);
|
|
5758
|
+
value.copy(detached);
|
|
5759
|
+
return detached;
|
|
5760
|
+
}
|
|
5761
|
+
function isDecodedRecord(value) {
|
|
5762
|
+
if (typeof value !== "object" || value == null) return false;
|
|
5763
|
+
const prototype = Object.getPrototypeOf(value);
|
|
5764
|
+
return prototype === Object.prototype || prototype === null;
|
|
5765
|
+
}
|
|
5766
|
+
|
|
5767
|
+
// src/protocol-flow-query-result.ts
|
|
5768
|
+
var CONTRACT = "ferric.flow.query.result/v1";
|
|
5769
|
+
var MAX_RECORDS = 100;
|
|
5770
|
+
var MAX_CURSOR_BYTES = 4096;
|
|
5771
|
+
var RECORD_FIELDS = [
|
|
5772
|
+
"id",
|
|
5773
|
+
"type",
|
|
5774
|
+
"state",
|
|
5775
|
+
"version",
|
|
5776
|
+
"priority",
|
|
5777
|
+
"partition_key",
|
|
5778
|
+
"created_at_ms",
|
|
5779
|
+
"updated_at_ms",
|
|
5780
|
+
"next_run_at_ms",
|
|
5781
|
+
"lease_deadline_ms",
|
|
5782
|
+
"attempts",
|
|
5783
|
+
"run_state",
|
|
5784
|
+
"max_active_ms",
|
|
5785
|
+
"parent_flow_id",
|
|
5786
|
+
"root_flow_id",
|
|
5787
|
+
"correlation_id",
|
|
5788
|
+
"attributes",
|
|
5789
|
+
"state_meta",
|
|
5790
|
+
"event_id",
|
|
5791
|
+
"fields"
|
|
5792
|
+
];
|
|
5793
|
+
var RECORD_FIELD_MASK = (1 << RECORD_FIELDS.length) - 1;
|
|
5794
|
+
var QUALITY_VALUES = [
|
|
5795
|
+
["authoritative", "projected_exact", "exact", "not_applicable"],
|
|
5796
|
+
["current", "projection_watermark", "not_applicable"],
|
|
5797
|
+
["complete", "unavailable"],
|
|
5798
|
+
["none", "complete", "authenticated_seek", "live_seek"]
|
|
5799
|
+
];
|
|
5800
|
+
var QUALITY_FIELDS = ["exactness", "freshness", "coverage", "pagination"];
|
|
5801
|
+
var USAGE_FIELDS = [
|
|
5802
|
+
"range_seeks",
|
|
5803
|
+
"range_pages",
|
|
5804
|
+
"scanned_entries",
|
|
5805
|
+
"scanned_bytes",
|
|
5806
|
+
"hydrated_records",
|
|
5807
|
+
"residual_checks",
|
|
5808
|
+
"duplicate_entries",
|
|
5809
|
+
"result_records",
|
|
5810
|
+
"response_bytes",
|
|
5811
|
+
"memory_high_water_bytes",
|
|
5812
|
+
"wall_time_us"
|
|
5813
|
+
];
|
|
5814
|
+
function decodeCompactFlowQueryResult(data, budget) {
|
|
5815
|
+
requireAvailable(data, 0, 2 + QUALITY_FIELDS.length + USAGE_FIELDS.length * 8);
|
|
5816
|
+
if (data.readUInt8(0) !== COMPACT_FLOW_QUERY_RESULT) {
|
|
5817
|
+
throw new FerricStoreError("expected compact FLOW.QUERY result");
|
|
5818
|
+
}
|
|
5819
|
+
const kind = data.readUInt8(1);
|
|
5820
|
+
let offset = 2;
|
|
5821
|
+
const quality = {};
|
|
5822
|
+
for (let index = 0; index < QUALITY_FIELDS.length; index += 1) {
|
|
5823
|
+
const field3 = QUALITY_FIELDS[index];
|
|
5824
|
+
const values = QUALITY_VALUES[index];
|
|
5825
|
+
if (field3 == null || values == null) throw new FerricStoreError("invalid compact FLOW.QUERY quality schema");
|
|
5826
|
+
const value = values[data.readUInt8(offset)];
|
|
5827
|
+
if (value == null) throw new FerricStoreError("invalid compact FLOW.QUERY quality code");
|
|
5828
|
+
quality[field3] = Buffer24.from(value);
|
|
5829
|
+
offset += 1;
|
|
5830
|
+
}
|
|
5831
|
+
const usage = {};
|
|
5832
|
+
for (const field3 of USAGE_FIELDS) {
|
|
5833
|
+
const read = readU64(data, offset);
|
|
5834
|
+
usage[field3] = read.value;
|
|
5835
|
+
offset = read.offset;
|
|
5836
|
+
}
|
|
5837
|
+
let result;
|
|
5838
|
+
if (kind === 0) {
|
|
5839
|
+
const page = readPage(data, offset);
|
|
5840
|
+
offset = page.offset;
|
|
5841
|
+
requireAvailable(data, offset, 4);
|
|
5842
|
+
const count = data.readUInt32BE(offset);
|
|
5843
|
+
offset += 4;
|
|
5844
|
+
if (count > MAX_RECORDS) throw new FerricStoreError("compact FLOW.QUERY page exceeds 100 records");
|
|
5845
|
+
consumeDecodeItems(count, budget);
|
|
5846
|
+
const records = new Array(count);
|
|
5847
|
+
for (let index = 0; index < count; index += 1) {
|
|
5848
|
+
const read = readRecord(data, offset, budget);
|
|
5849
|
+
records[index] = read.value;
|
|
5850
|
+
offset = read.offset;
|
|
5851
|
+
}
|
|
5852
|
+
result = { version: Buffer24.from(CONTRACT), records, page: page.value, quality, usage };
|
|
5853
|
+
} else if (kind === 1) {
|
|
5854
|
+
const count = readU64(data, offset);
|
|
5855
|
+
offset = count.offset;
|
|
5856
|
+
result = {
|
|
5857
|
+
version: Buffer24.from(CONTRACT),
|
|
5858
|
+
result: { kind: Buffer24.from("count"), value: count.value },
|
|
5859
|
+
quality,
|
|
5860
|
+
usage
|
|
5861
|
+
};
|
|
5862
|
+
} else {
|
|
5863
|
+
throw new FerricStoreError(`unsupported compact FLOW.QUERY result kind ${kind}`);
|
|
5864
|
+
}
|
|
5865
|
+
if (offset !== data.byteLength) throw new FerricStoreError("trailing compact FLOW.QUERY result bytes");
|
|
5866
|
+
if (BigInt(usage.response_bytes) !== BigInt(data.byteLength)) {
|
|
5867
|
+
throw new FerricStoreError("compact FLOW.QUERY response_bytes does not match its payload");
|
|
5868
|
+
}
|
|
5869
|
+
return result;
|
|
5870
|
+
}
|
|
5871
|
+
function readPage(data, offset) {
|
|
5872
|
+
requireAvailable(data, offset, 5);
|
|
5873
|
+
const hasMoreCode = data.readUInt8(offset);
|
|
5874
|
+
const size = data.readUInt32BE(offset + 1);
|
|
5875
|
+
offset += 5;
|
|
5876
|
+
if (hasMoreCode === 0 && size === NULL_U32) {
|
|
5877
|
+
return { value: { has_more: false, cursor: null }, offset };
|
|
5878
|
+
}
|
|
5879
|
+
if (hasMoreCode !== 1 || size === 0 || size === NULL_U32 || size > MAX_CURSOR_BYTES) {
|
|
5880
|
+
throw new FerricStoreError("invalid compact FLOW.QUERY page cursor");
|
|
5881
|
+
}
|
|
5882
|
+
requireAvailable(data, offset, size);
|
|
5883
|
+
return {
|
|
5884
|
+
value: {
|
|
5885
|
+
has_more: true,
|
|
5886
|
+
cursor: detachDecodedBinary(data.subarray(offset, offset + size), data.byteLength)
|
|
5887
|
+
},
|
|
5888
|
+
offset: offset + size
|
|
5889
|
+
};
|
|
5890
|
+
}
|
|
5891
|
+
function readRecord(data, offset, budget) {
|
|
5892
|
+
requireAvailable(data, offset, 4);
|
|
5893
|
+
const bitmap = data.readUInt32BE(offset);
|
|
5894
|
+
offset += 4;
|
|
5895
|
+
if ((bitmap & ~RECORD_FIELD_MASK) !== 0) {
|
|
5896
|
+
throw new FerricStoreError("compact FLOW.QUERY record contains reserved fields");
|
|
5897
|
+
}
|
|
5898
|
+
consumeDecodeItems(populationCount(bitmap), budget);
|
|
5899
|
+
const record = {};
|
|
5900
|
+
for (let index = 0; index < RECORD_FIELDS.length; index += 1) {
|
|
5901
|
+
if ((bitmap & 1 << index) === 0) continue;
|
|
5902
|
+
const field3 = RECORD_FIELDS[index];
|
|
5903
|
+
if (field3 == null) throw new FerricStoreError("invalid compact FLOW.QUERY record schema");
|
|
5904
|
+
const read = decodeValueWithBudget(data, offset, budget);
|
|
5905
|
+
setOwnValue2(record, field3, detachDecodedBinary(read.value, data.byteLength));
|
|
5906
|
+
offset = read.offset;
|
|
5907
|
+
}
|
|
5908
|
+
return { value: record, offset };
|
|
5909
|
+
}
|
|
5910
|
+
function readU64(data, offset) {
|
|
5911
|
+
requireAvailable(data, offset, 8);
|
|
5912
|
+
const value = data.readBigUInt64BE(offset);
|
|
5913
|
+
return {
|
|
5914
|
+
value: value <= MAX_SAFE_INTEGER_BIGINT ? Number(value) : value,
|
|
5915
|
+
offset: offset + 8
|
|
5916
|
+
};
|
|
5917
|
+
}
|
|
5918
|
+
function populationCount(value) {
|
|
5919
|
+
let remaining = value >>> 0;
|
|
5920
|
+
let count = 0;
|
|
5921
|
+
while (remaining !== 0) {
|
|
5922
|
+
remaining &= remaining - 1;
|
|
5923
|
+
count += 1;
|
|
5924
|
+
}
|
|
5925
|
+
return count;
|
|
5926
|
+
}
|
|
5927
|
+
|
|
5928
|
+
// src/protocol-compact-response.ts
|
|
5929
|
+
function tryDecodeCompactResponse(opcode, body, hints) {
|
|
5289
5930
|
if (body.byteLength === 0) return { found: false, value: void 0 };
|
|
5290
5931
|
const budget = { remainingItems: DEFAULT_MAX_VALUE_ITEMS };
|
|
5291
5932
|
const tag = body.readUInt8(0);
|
|
5933
|
+
validateCompactResponseItems(tag, opcode, body, hints);
|
|
5292
5934
|
const pipelineValues = opcode === OPCODES.pipeline && supports(hints, "pipeline_v1", opcode);
|
|
5293
5935
|
if (tag === COMPACT_OK_LIST && (supports(hints, "ok_list_v1", opcode) || pipelineValues)) {
|
|
5294
5936
|
const values = decodeCompactOkList(body, budget);
|
|
@@ -5339,6 +5981,9 @@ function tryDecodeCompactResponse(opcode, body, hints) {
|
|
|
5339
5981
|
value: opcode === OPCODES.pipeline ? markCompactPipelineDecoded(read.value) : read.value
|
|
5340
5982
|
};
|
|
5341
5983
|
}
|
|
5984
|
+
if (tag === COMPACT_FLOW_QUERY_RESULT && supports(hints, "flow_query_result_v1", opcode)) {
|
|
5985
|
+
return { found: true, value: decodeCompactFlowQueryResult(body, budget) };
|
|
5986
|
+
}
|
|
5342
5987
|
return { found: false, value: void 0 };
|
|
5343
5988
|
}
|
|
5344
5989
|
function supports(hints, codec, opcode) {
|
|
@@ -5349,7 +5994,7 @@ function decodeCompactOkList(data, budget) {
|
|
|
5349
5994
|
const count = data.readUInt32BE(1);
|
|
5350
5995
|
requireCompactContainer2(count, budget);
|
|
5351
5996
|
if (data.byteLength !== 5) throw new FerricStoreError("invalid compact OK list response");
|
|
5352
|
-
return Array.from({ length: count }, () =>
|
|
5997
|
+
return Array.from({ length: count }, () => Buffer25.from("OK"));
|
|
5353
5998
|
}
|
|
5354
5999
|
function decodeCompactKvGet(data) {
|
|
5355
6000
|
requireAvailable(data, 0, 2);
|
|
@@ -5395,7 +6040,7 @@ function decodeCompactMgetFixed(data, budget) {
|
|
|
5395
6040
|
if (size === NULL_U32 || data.byteLength !== expected) {
|
|
5396
6041
|
throw new FerricStoreError("invalid compact fixed MGET response");
|
|
5397
6042
|
}
|
|
5398
|
-
if (size === 0) return new Array(count).fill(
|
|
6043
|
+
if (size === 0) return new Array(count).fill(Buffer25.alloc(0));
|
|
5399
6044
|
const values = new Array(count);
|
|
5400
6045
|
for (let index = 0, offset = 9; index < count; index += 1, offset += size) {
|
|
5401
6046
|
values[index] = data.subarray(offset, offset + size);
|
|
@@ -5456,7 +6101,7 @@ function decodeCompactPipeline(data, budget, claimModes) {
|
|
|
5456
6101
|
const read = readBinary(data, offset);
|
|
5457
6102
|
const errorStatus = status === 1 ? "busy" : "error";
|
|
5458
6103
|
values[index] = classifyServerError(
|
|
5459
|
-
|
|
6104
|
+
protocolErrorMessage(status === 1 ? 4 : 1, read.value),
|
|
5460
6105
|
read.value,
|
|
5461
6106
|
void 0,
|
|
5462
6107
|
errorStatus
|
|
@@ -5566,13 +6211,13 @@ function readCompactFlowRecord(data, offset, budget = { remainingItems: DEFAULT_
|
|
|
5566
6211
|
let key;
|
|
5567
6212
|
if (keyId === 0) {
|
|
5568
6213
|
const read2 = readBinary(data, offset);
|
|
5569
|
-
key = read2.value
|
|
6214
|
+
key = read2.value;
|
|
5570
6215
|
offset = read2.offset;
|
|
5571
6216
|
} else {
|
|
5572
6217
|
key = FLOW_RECORD_FIELD_KEYS[keyId] ?? `field_${keyId}`;
|
|
5573
6218
|
}
|
|
5574
6219
|
const read = decodeValueWithBudget(data, offset, budget);
|
|
5575
|
-
|
|
6220
|
+
setProtocolMapEntry(record, key, read.value);
|
|
5576
6221
|
offset = read.offset;
|
|
5577
6222
|
}
|
|
5578
6223
|
return { value: record, offset };
|
|
@@ -5608,15 +6253,29 @@ function requireCompactContainer2(count, budget) {
|
|
|
5608
6253
|
}
|
|
5609
6254
|
consumeDecodeItems(count, budget);
|
|
5610
6255
|
}
|
|
5611
|
-
function
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
if (
|
|
5615
|
-
|
|
5616
|
-
|
|
6256
|
+
function validateCompactResponseItems(tag, opcode, data, hints) {
|
|
6257
|
+
const scalarItems = opcode === OPCODES.set || opcode === OPCODES.mset ? 1 : void 0;
|
|
6258
|
+
const expected = scalarItems ?? hints.compactResponseItems;
|
|
6259
|
+
if (expected == null || !COUNTED_COMPACT_TAGS.has(tag)) return;
|
|
6260
|
+
requireAvailable(data, 0, 5);
|
|
6261
|
+
const actual = data.readUInt32BE(1);
|
|
6262
|
+
if (actual !== expected) {
|
|
6263
|
+
throw new FerricStoreError(
|
|
6264
|
+
`compact response returned ${actual} items; expected ${expected} items`
|
|
6265
|
+
);
|
|
5617
6266
|
}
|
|
5618
|
-
return `ERR native request failed status=${status}: ${String(value)}`;
|
|
5619
6267
|
}
|
|
6268
|
+
var COUNTED_COMPACT_TAGS = /* @__PURE__ */ new Set([
|
|
6269
|
+
COMPACT_FLOW_CLAIM_JOBS,
|
|
6270
|
+
COMPACT_OK_LIST,
|
|
6271
|
+
COMPACT_KV_MGET,
|
|
6272
|
+
COMPACT_FLOW_RECORD_LIST,
|
|
6273
|
+
COMPACT_BINARY_LIST_LIST,
|
|
6274
|
+
COMPACT_BINARY_MAP_LIST,
|
|
6275
|
+
COMPACT_INTEGER_LIST,
|
|
6276
|
+
COMPACT_KV_MGET_FIXED,
|
|
6277
|
+
COMPACT_PIPELINE_RESPONSE
|
|
6278
|
+
]);
|
|
5620
6279
|
|
|
5621
6280
|
// src/protocol-response.ts
|
|
5622
6281
|
function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
@@ -5634,9 +6293,16 @@ function decodeResponse(frame, expectedOpcode, hints = {}) {
|
|
|
5634
6293
|
}
|
|
5635
6294
|
const status = frame.body.readUInt16BE(0);
|
|
5636
6295
|
const body = frame.body.subarray(2);
|
|
5637
|
-
const
|
|
6296
|
+
const customPayload = (frame.flags & FLAG_CUSTOM_PAYLOAD) !== 0;
|
|
6297
|
+
const value = decodeResponseValue(
|
|
6298
|
+
frame.opcode,
|
|
6299
|
+
body,
|
|
6300
|
+
hints,
|
|
6301
|
+
status === STATUS_OK,
|
|
6302
|
+
customPayload
|
|
6303
|
+
);
|
|
5638
6304
|
if (status === STATUS_OK) return value;
|
|
5639
|
-
const message =
|
|
6305
|
+
const message = protocolErrorMessage(status, value);
|
|
5640
6306
|
throw classifyServerError(message, value, void 0, status);
|
|
5641
6307
|
}
|
|
5642
6308
|
function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
@@ -5675,7 +6341,7 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5675
6341
|
continue;
|
|
5676
6342
|
}
|
|
5677
6343
|
const error = classifyServerError(
|
|
5678
|
-
|
|
6344
|
+
protocolErrorMessage(status === "busy" ? 4 : 1, payload),
|
|
5679
6345
|
payload,
|
|
5680
6346
|
void 0,
|
|
5681
6347
|
status
|
|
@@ -5690,28 +6356,24 @@ function unwrapPipelineResponse(value, options = {}, expectedItems) {
|
|
|
5690
6356
|
return out;
|
|
5691
6357
|
}
|
|
5692
6358
|
function pipelineStatus(value) {
|
|
5693
|
-
if (typeof value !== "string" && !
|
|
6359
|
+
if (typeof value !== "string" && !Buffer26.isBuffer(value) && !(value instanceof Uint8Array)) return null;
|
|
5694
6360
|
const status = asText(value).toLowerCase();
|
|
5695
6361
|
return status === "ok" || status === "busy" || status === "error" ? status : null;
|
|
5696
6362
|
}
|
|
5697
|
-
function decodeResponseValue(opcode, body, hints) {
|
|
5698
|
-
|
|
5699
|
-
|
|
6363
|
+
function decodeResponseValue(opcode, body, hints, allowCompact, customPayload) {
|
|
6364
|
+
if (customPayload && allowCompact) {
|
|
6365
|
+
const compact = tryDecodeCompactResponse(opcode, body, hints);
|
|
6366
|
+
if (compact.found) return compact.value;
|
|
6367
|
+
}
|
|
6368
|
+
if (customPayload) {
|
|
6369
|
+
throw new FerricStoreError("unsupported or malformed custom protocol response", { raw: body });
|
|
6370
|
+
}
|
|
5700
6371
|
const decoded = decodeValue(body);
|
|
5701
6372
|
if (decoded.offset !== body.byteLength) {
|
|
5702
6373
|
throw new FerricStoreError("native protocol response has trailing bytes", { raw: body });
|
|
5703
6374
|
}
|
|
5704
6375
|
return decoded.value;
|
|
5705
6376
|
}
|
|
5706
|
-
function errorMessage2(status, value) {
|
|
5707
|
-
if (typeof value === "string") return value;
|
|
5708
|
-
if (Buffer21.isBuffer(value)) return value.toString("utf8");
|
|
5709
|
-
if (typeof value === "object" && value != null && Object.hasOwn(value, "message")) {
|
|
5710
|
-
const message = value.message;
|
|
5711
|
-
return typeof message === "string" ? message : String(message);
|
|
5712
|
-
}
|
|
5713
|
-
return `ERR native request failed status=${status}: ${String(value)}`;
|
|
5714
|
-
}
|
|
5715
6377
|
|
|
5716
6378
|
// src/protocol.ts
|
|
5717
6379
|
function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
@@ -5721,7 +6383,7 @@ function encodeRequest(command, requestId, maxBodyBytes = Number.MAX_SAFE_INTEGE
|
|
|
5721
6383
|
const bodyLength = customPayload ? binaryValueByteLength(command.payload) : plan?.byteLength ?? 0;
|
|
5722
6384
|
if (bodyLength > bodyLimit) throw requestFrameTooLarge(bodyLimit);
|
|
5723
6385
|
const flags = command.flags ?? 0;
|
|
5724
|
-
const frame =
|
|
6386
|
+
const frame = Buffer27.allocUnsafe(HEADER_SIZE + bodyLength);
|
|
5725
6387
|
frame.write(MAGIC, 0, "ascii");
|
|
5726
6388
|
frame.writeUInt8(REQUEST_VERSION, 4);
|
|
5727
6389
|
frame.writeUInt8(flags, 5);
|
|
@@ -5822,18 +6484,18 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5822
6484
|
}
|
|
5823
6485
|
if (command === "SET" && commandArgs2.length >= 2) {
|
|
5824
6486
|
const payload = stringSetPayload(commandArgs2);
|
|
5825
|
-
return payload == null ? commandExec(args) : { opcode: OPCODES.set, payload };
|
|
6487
|
+
return payload == null ? commandExec(args) : { compactResponseItems: 1, opcode: OPCODES.set, payload };
|
|
5826
6488
|
}
|
|
5827
6489
|
if (command === "MGET" && commandArgs2.length > 0) {
|
|
5828
6490
|
const compact = allowCustomPayload ? compactKeyPipelinePayload(OPCODES.mget, commandArgs2, 2, maxBodyBytes) : void 0;
|
|
5829
|
-
if (compact != null) return compact;
|
|
5830
|
-
return commandArgs2.every(isBinaryCommandArgument) ? { opcode: OPCODES.mget, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
6491
|
+
if (compact != null) return { ...compact, compactResponseItems: commandArgs2.length };
|
|
6492
|
+
return commandArgs2.every(isBinaryCommandArgument) ? { compactResponseItems: commandArgs2.length, opcode: OPCODES.mget, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
5831
6493
|
}
|
|
5832
6494
|
if (command === "MSET" && commandArgs2.length >= 2 && commandArgs2.length % 2 === 0) {
|
|
5833
6495
|
const compact = allowCustomPayload ? compactMsetPayload(commandArgs2, maxBodyBytes) : void 0;
|
|
5834
|
-
if (compact != null) return compact;
|
|
6496
|
+
if (compact != null) return { ...compact, compactResponseItems: 1 };
|
|
5835
6497
|
const pairs = typedKeyValuePairs(commandArgs2);
|
|
5836
|
-
return pairs == null ? commandExec(args) : { opcode: OPCODES.mset, payload: { pairs } };
|
|
6498
|
+
return pairs == null ? commandExec(args) : { compactResponseItems: 1, opcode: OPCODES.mset, payload: { pairs } };
|
|
5837
6499
|
}
|
|
5838
6500
|
if (command === "DEL" && commandArgs2.length > 0) {
|
|
5839
6501
|
return commandArgs2.every(isBinaryCommandArgument) ? { opcode: OPCODES.del, payload: { keys: commandArgs2 } } : commandExec(args);
|
|
@@ -5843,8 +6505,14 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5843
6505
|
if (command === "FLOW.HISTORY") {
|
|
5844
6506
|
return flowHistoryPayload(commandArgs2) ?? commandExec(args);
|
|
5845
6507
|
}
|
|
5846
|
-
if (command === "FLOW.
|
|
5847
|
-
return
|
|
6508
|
+
if (command === "FLOW.QUERY") {
|
|
6509
|
+
return { opcode: OPCODES.flowQuery, payload: flowQueryPayload(commandArgs2) };
|
|
6510
|
+
}
|
|
6511
|
+
if (command === "FLOW.POLICY.SET") {
|
|
6512
|
+
return flowPolicySetPayload(commandArgs2) ?? commandExec(args);
|
|
6513
|
+
}
|
|
6514
|
+
if (command === "FLOW.POLICY.GET") {
|
|
6515
|
+
return flowPolicyGetPayload(commandArgs2) ?? commandExec(args);
|
|
5848
6516
|
}
|
|
5849
6517
|
const flowAdmin = FLOW_ADMIN_COMMANDS[command];
|
|
5850
6518
|
if (flowAdmin != null) {
|
|
@@ -5997,24 +6665,17 @@ function buildProtocolCommand(args, maxBodyBytes = Number.MAX_SAFE_INTEGER, allo
|
|
|
5997
6665
|
if (command === "FLOW.RUN_STEPS_MANY") {
|
|
5998
6666
|
return flowAdminPayload(OPCODES.flowRunStepsMany, commandArgs2) ?? commandExec(args);
|
|
5999
6667
|
}
|
|
6000
|
-
if (command === "FLOW.SEARCH") {
|
|
6001
|
-
if (hasFlowCommandOnlyOption(command, commandArgs2)) {
|
|
6002
|
-
const fallback = commandExec(args);
|
|
6003
|
-
try {
|
|
6004
|
-
const parsed = flowSearchPayload(commandArgs2);
|
|
6005
|
-
return parsed == null ? fallback : withFlowPartitionRouting(fallback, parsed.payload);
|
|
6006
|
-
} catch {
|
|
6007
|
-
return fallback;
|
|
6008
|
-
}
|
|
6009
|
-
}
|
|
6010
|
-
return flowSearchPayload(commandArgs2) ?? commandExec(args);
|
|
6011
|
-
}
|
|
6012
6668
|
return commandExec(args);
|
|
6013
6669
|
}
|
|
6014
6670
|
function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
6015
6671
|
const compact = compactPipelinePayload(commands, maxBodyBytes);
|
|
6016
6672
|
if (compact != null) {
|
|
6017
|
-
return {
|
|
6673
|
+
return {
|
|
6674
|
+
compactResponseItems: commands.length,
|
|
6675
|
+
flags: FLAG_CUSTOM_PAYLOAD,
|
|
6676
|
+
opcode: OPCODES.pipeline,
|
|
6677
|
+
payload: compact
|
|
6678
|
+
};
|
|
6018
6679
|
}
|
|
6019
6680
|
const protocols = new Array(commands.length);
|
|
6020
6681
|
for (let index = 0; index < commands.length; index += 1) {
|
|
@@ -6053,6 +6714,7 @@ function tryPipelineCommand(commands, maxBodyBytes = Number.MAX_SAFE_INTEGER) {
|
|
|
6053
6714
|
const pipelineClaimModes = pipelineProtocols.map((protocol) => protocol.compactClaimMode);
|
|
6054
6715
|
const hasPipelineClaimMode = pipelineClaimModes.some((mode) => mode != null);
|
|
6055
6716
|
return {
|
|
6717
|
+
compactResponseItems: commands.length,
|
|
6056
6718
|
opcode: OPCODES.pipeline,
|
|
6057
6719
|
payload: {
|
|
6058
6720
|
atomicity: "none",
|
|
@@ -6101,7 +6763,7 @@ import "net";
|
|
|
6101
6763
|
import "tls";
|
|
6102
6764
|
|
|
6103
6765
|
// src/client-native-options.ts
|
|
6104
|
-
import { Buffer as
|
|
6766
|
+
import { Buffer as Buffer28 } from "buffer";
|
|
6105
6767
|
|
|
6106
6768
|
// src/string-array-snapshot.ts
|
|
6107
6769
|
function snapshotOwnStringArray(values, name) {
|
|
@@ -6184,7 +6846,7 @@ function snapshotTlsOptions(options) {
|
|
|
6184
6846
|
return Object.freeze(snapshot);
|
|
6185
6847
|
}
|
|
6186
6848
|
function snapshotTlsValue(value, name) {
|
|
6187
|
-
if (
|
|
6849
|
+
if (Buffer28.isBuffer(value)) return Buffer28.from(value);
|
|
6188
6850
|
if (value instanceof Uint8Array) return value.slice();
|
|
6189
6851
|
if (Array.isArray(value)) {
|
|
6190
6852
|
const snapshot = new Array(value.length);
|
|
@@ -7039,7 +7701,7 @@ var NativeResponseHandler = class {
|
|
|
7039
7701
|
compactResponseOpcodes: this.options.compactResponseOpcodes?.() ?? EMPTY_COMPACT_RESPONSE_OPCODES
|
|
7040
7702
|
});
|
|
7041
7703
|
if (frame.opcode === OPCODES.windowUpdate) this.options.applyFlowControlLimits(value);
|
|
7042
|
-
const
|
|
7704
|
+
const event2 = {
|
|
7043
7705
|
flags: frame.flags,
|
|
7044
7706
|
laneId: frame.laneId,
|
|
7045
7707
|
opcode: frame.opcode,
|
|
@@ -7047,7 +7709,7 @@ var NativeResponseHandler = class {
|
|
|
7047
7709
|
};
|
|
7048
7710
|
if (frame.opcode === OPCODES.goaway) this.options.beginDraining();
|
|
7049
7711
|
try {
|
|
7050
|
-
const callback = this.options.onEvent?.(
|
|
7712
|
+
const callback = this.options.onEvent?.(event2);
|
|
7051
7713
|
if (callback != null) void Promise.resolve(callback).catch(() => void 0);
|
|
7052
7714
|
} catch {
|
|
7053
7715
|
}
|
|
@@ -7211,12 +7873,14 @@ var NativeConnectionCapabilities = class {
|
|
|
7211
7873
|
}
|
|
7212
7874
|
configuredRequestFrameBytes;
|
|
7213
7875
|
compactResponseOpcodes = EMPTY_COMPACT_RESPONSE_OPCODES;
|
|
7876
|
+
flowQuery;
|
|
7214
7877
|
requestFrameBytes;
|
|
7215
7878
|
negotiatedRequestFrameBytes;
|
|
7216
7879
|
apply(value) {
|
|
7217
7880
|
const limits = startupLimits(value);
|
|
7218
7881
|
const negotiation = nativeNegotiation(value);
|
|
7219
7882
|
this.compactResponseOpcodes = negotiation.compactResponseOpcodes;
|
|
7883
|
+
this.flowQuery = negotiation.flowQuery;
|
|
7220
7884
|
if (limits.frameBytes != null) {
|
|
7221
7885
|
this.negotiatedRequestFrameBytes = Math.min(
|
|
7222
7886
|
this.configuredRequestFrameBytes,
|
|
@@ -7236,6 +7900,19 @@ var NativeConnectionCapabilities = class {
|
|
|
7236
7900
|
}
|
|
7237
7901
|
};
|
|
7238
7902
|
|
|
7903
|
+
// src/native-startup-payload.ts
|
|
7904
|
+
function nativeStartupPayload(clientName, events) {
|
|
7905
|
+
const name = clientName ?? "ferricstore-typescript";
|
|
7906
|
+
return {
|
|
7907
|
+
client_name: name,
|
|
7908
|
+
compact_flow_responses: true,
|
|
7909
|
+
compact_response_codecs: ["flow_query_result_v1"],
|
|
7910
|
+
compression: "none",
|
|
7911
|
+
driver_name: name,
|
|
7912
|
+
...events == null || events.length === 0 ? {} : { events: [...events] }
|
|
7913
|
+
};
|
|
7914
|
+
}
|
|
7915
|
+
|
|
7239
7916
|
// src/native-adapter.ts
|
|
7240
7917
|
var NativeAdapter = class _NativeAdapter {
|
|
7241
7918
|
socket;
|
|
@@ -7394,13 +8071,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7394
8071
|
const response = await this.request({
|
|
7395
8072
|
laneId: 0,
|
|
7396
8073
|
opcode: OPCODES.startup,
|
|
7397
|
-
payload:
|
|
7398
|
-
client_name: clientName ?? "ferricstore-typescript",
|
|
7399
|
-
compact_flow_responses: true,
|
|
7400
|
-
compression: "none",
|
|
7401
|
-
driver_name: clientName ?? "ferricstore-typescript",
|
|
7402
|
-
...events == null || events.length === 0 ? {} : { events: [...events] }
|
|
7403
|
-
}
|
|
8074
|
+
payload: nativeStartupPayload(clientName, events)
|
|
7404
8075
|
});
|
|
7405
8076
|
this.applyStartupLimits(response);
|
|
7406
8077
|
const authRequired = field(response, "auth_required");
|
|
@@ -7460,6 +8131,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
7460
8131
|
if (!hasFlowControlCredit) this.pendingControlRequests += 1;
|
|
7461
8132
|
this.pending.set(requestId, {
|
|
7462
8133
|
...command.compactClaimMode == null ? {} : { compactClaimMode: command.compactClaimMode },
|
|
8134
|
+
...command.compactResponseItems == null ? {} : { compactResponseItems: command.compactResponseItems },
|
|
7463
8135
|
hasFlowControlCredit,
|
|
7464
8136
|
indefinite: timeoutMs == null,
|
|
7465
8137
|
laneId,
|
|
@@ -7592,6 +8264,29 @@ function executeCommandArgs(executor, args) {
|
|
|
7592
8264
|
|
|
7593
8265
|
// src/reconnecting-executor.ts
|
|
7594
8266
|
import "buffer";
|
|
8267
|
+
|
|
8268
|
+
// src/command-retry-policy.ts
|
|
8269
|
+
import { Buffer as Buffer32 } from "buffer";
|
|
8270
|
+
function isCasMutation(args) {
|
|
8271
|
+
const offset = commandName2(args[0]) === "COMMAND_EXEC" ? 1 : 0;
|
|
8272
|
+
const name = commandName2(args[offset]);
|
|
8273
|
+
if (name === "CAS") return true;
|
|
8274
|
+
if (name !== "FLOW.POLICY.SET") return false;
|
|
8275
|
+
for (let index = offset + 2; index < args.length; index += 2) {
|
|
8276
|
+
if (!Object.hasOwn(args, index)) return false;
|
|
8277
|
+
if (commandName2(args[index]) === "EXPECTED_GENERATION") return true;
|
|
8278
|
+
}
|
|
8279
|
+
return false;
|
|
8280
|
+
}
|
|
8281
|
+
function commandName2(value) {
|
|
8282
|
+
if (typeof value === "string") return value.toUpperCase();
|
|
8283
|
+
if (Buffer32.isBuffer(value) || value instanceof Uint8Array) {
|
|
8284
|
+
return Buffer32.from(value).toString("utf8").toUpperCase();
|
|
8285
|
+
}
|
|
8286
|
+
return void 0;
|
|
8287
|
+
}
|
|
8288
|
+
|
|
8289
|
+
// src/reconnecting-executor.ts
|
|
7595
8290
|
var ReconnectingExecutor = class {
|
|
7596
8291
|
constructor(createExecutor, options = {}) {
|
|
7597
8292
|
this.createExecutor = createExecutor;
|
|
@@ -7622,7 +8317,12 @@ var ReconnectingExecutor = class {
|
|
|
7622
8317
|
async executeCommandArgs(args) {
|
|
7623
8318
|
const snapshot = snapshotCommandArguments(args);
|
|
7624
8319
|
assertCommandHasStableConnectionState(snapshot);
|
|
7625
|
-
|
|
8320
|
+
const casMutation = isCasMutation(snapshot);
|
|
8321
|
+
return await this.withReconnect(
|
|
8322
|
+
(executor) => executeCommandArgs(executor, snapshot),
|
|
8323
|
+
casMutation ? isClosedConnectionError : isReconnectableClosedConnectionError,
|
|
8324
|
+
!casMutation
|
|
8325
|
+
);
|
|
7626
8326
|
}
|
|
7627
8327
|
async ready() {
|
|
7628
8328
|
await this.executorPromise;
|
|
@@ -7707,7 +8407,7 @@ var ReconnectingExecutor = class {
|
|
|
7707
8407
|
})();
|
|
7708
8408
|
await this.closePromise;
|
|
7709
8409
|
}
|
|
7710
|
-
async withReconnect(operation, reconnectable = isReconnectableClosedConnectionError) {
|
|
8410
|
+
async withReconnect(operation, reconnectable = isReconnectableClosedConnectionError, replayAllowed = true) {
|
|
7711
8411
|
let executor = await this.executorPromise;
|
|
7712
8412
|
let retries = 0;
|
|
7713
8413
|
for (; ; ) {
|
|
@@ -7716,6 +8416,10 @@ var ReconnectingExecutor = class {
|
|
|
7716
8416
|
return await operation(executor);
|
|
7717
8417
|
} catch (error) {
|
|
7718
8418
|
if (this.closed || retries >= this.maxRetries || !reconnectable(error)) throw error;
|
|
8419
|
+
if (!replayAllowed) {
|
|
8420
|
+
await this.reconnect(executor).catch(() => void 0);
|
|
8421
|
+
throw error;
|
|
8422
|
+
}
|
|
7719
8423
|
for (; ; ) {
|
|
7720
8424
|
retries += 1;
|
|
7721
8425
|
try {
|
|
@@ -7768,6 +8472,9 @@ var ReconnectingExecutor = class {
|
|
|
7768
8472
|
function isReconnectableClosedConnectionError(error) {
|
|
7769
8473
|
return error instanceof ConnectionClosedError && error.requestDisposition === "unsent";
|
|
7770
8474
|
}
|
|
8475
|
+
function isClosedConnectionError(error) {
|
|
8476
|
+
return error instanceof ConnectionClosedError;
|
|
8477
|
+
}
|
|
7771
8478
|
function isReadOnlyReconnectableClosedConnectionError(error) {
|
|
7772
8479
|
const pending = [error];
|
|
7773
8480
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -7789,16 +8496,88 @@ function normalizeNonNegativeInteger2(value, fallback) {
|
|
|
7789
8496
|
import "buffer";
|
|
7790
8497
|
|
|
7791
8498
|
// src/topology-routing.ts
|
|
7792
|
-
import { Buffer as
|
|
8499
|
+
import { Buffer as Buffer35 } from "buffer";
|
|
8500
|
+
|
|
8501
|
+
// src/flow-partition-route-cache.ts
|
|
8502
|
+
import { Buffer as Buffer34 } from "buffer";
|
|
7793
8503
|
import { createHash } from "crypto";
|
|
7794
|
-
var
|
|
7795
|
-
var
|
|
8504
|
+
var AUTO_PREFIX = Buffer34.from("__flow_auto__:", "ascii");
|
|
8505
|
+
var MAX_CACHEABLE_PARTITION_BYTES = 4 * 1024;
|
|
8506
|
+
var MAX_CACHE_BYTES = 1 * 1024 * 1024;
|
|
8507
|
+
var MAX_CACHE_ENTRIES = 1024;
|
|
8508
|
+
var CACHE_ENTRY_OVERHEAD_BYTES = 96;
|
|
8509
|
+
var routeCache = /* @__PURE__ */ new Map();
|
|
8510
|
+
var cacheBytes = 0;
|
|
8511
|
+
var cacheHits = 0;
|
|
8512
|
+
var cacheMisses = 0;
|
|
8513
|
+
function flowLogicalPartitionRoutingKey(value) {
|
|
8514
|
+
if (typeof value !== "string" && !Buffer34.isBuffer(value)) return void 0;
|
|
8515
|
+
const autoBucket = flowAutoBucket(value);
|
|
8516
|
+
if (autoBucket != null) return `{fa:${autoBucket}}`;
|
|
8517
|
+
const bytes2 = Buffer34.isBuffer(value) ? value : Buffer34.from(value);
|
|
8518
|
+
if (bytes2.byteLength > MAX_CACHEABLE_PARTITION_BYTES) return hashRoute(bytes2);
|
|
8519
|
+
const cacheKey = bytes2.toString("base64");
|
|
8520
|
+
const cached = routeCache.get(cacheKey);
|
|
8521
|
+
if (cached != null) {
|
|
8522
|
+
cacheHits += 1;
|
|
8523
|
+
routeCache.delete(cacheKey);
|
|
8524
|
+
routeCache.set(cacheKey, cached);
|
|
8525
|
+
return cached.routeKey;
|
|
8526
|
+
}
|
|
8527
|
+
cacheMisses += 1;
|
|
8528
|
+
const routeKey = hashRoute(bytes2);
|
|
8529
|
+
const entryBytes = estimatedEntryBytes(cacheKey, routeKey);
|
|
8530
|
+
while (routeCache.size >= MAX_CACHE_ENTRIES || routeCache.size > 0 && cacheBytes + entryBytes > MAX_CACHE_BYTES) {
|
|
8531
|
+
evictOldest();
|
|
8532
|
+
}
|
|
8533
|
+
if (entryBytes <= MAX_CACHE_BYTES) {
|
|
8534
|
+
routeCache.set(cacheKey, { bytes: entryBytes, routeKey });
|
|
8535
|
+
cacheBytes += entryBytes;
|
|
8536
|
+
}
|
|
8537
|
+
return routeKey;
|
|
8538
|
+
}
|
|
8539
|
+
function flowAutoBucket(value) {
|
|
8540
|
+
if (typeof value === "string") {
|
|
8541
|
+
const match = /^__flow_auto__:(0|[1-9]\d{0,2})$/u.exec(value);
|
|
8542
|
+
if (match?.[1] == null) return void 0;
|
|
8543
|
+
const bucket2 = Number(match[1]);
|
|
8544
|
+
return bucket2 < 256 ? bucket2 : void 0;
|
|
8545
|
+
}
|
|
8546
|
+
const digitCount = value.byteLength - AUTO_PREFIX.byteLength;
|
|
8547
|
+
if (digitCount < 1 || digitCount > 3) return void 0;
|
|
8548
|
+
for (let index = 0; index < AUTO_PREFIX.byteLength; index += 1) {
|
|
8549
|
+
if (value[index] !== AUTO_PREFIX[index]) return void 0;
|
|
8550
|
+
}
|
|
8551
|
+
if (digitCount > 1 && value[AUTO_PREFIX.byteLength] === 48) return void 0;
|
|
8552
|
+
let bucket = 0;
|
|
8553
|
+
for (let index = AUTO_PREFIX.byteLength; index < value.byteLength; index += 1) {
|
|
8554
|
+
const digit = value[index];
|
|
8555
|
+
if (digit == null || digit < 48 || digit > 57) return void 0;
|
|
8556
|
+
bucket = bucket * 10 + digit - 48;
|
|
8557
|
+
}
|
|
8558
|
+
return bucket < 256 ? bucket : void 0;
|
|
8559
|
+
}
|
|
8560
|
+
function hashRoute(value) {
|
|
8561
|
+
const digest = createHash("sha256").update(value).digest("base64url");
|
|
8562
|
+
return `{f:${digest}}`;
|
|
8563
|
+
}
|
|
8564
|
+
function estimatedEntryBytes(cacheKey, routeKey) {
|
|
8565
|
+
return CACHE_ENTRY_OVERHEAD_BYTES + 2 * (cacheKey.length + routeKey.length);
|
|
8566
|
+
}
|
|
8567
|
+
function evictOldest() {
|
|
8568
|
+
const oldest = routeCache.entries().next().value;
|
|
8569
|
+
if (oldest == null) return;
|
|
8570
|
+
routeCache.delete(oldest[0]);
|
|
8571
|
+
cacheBytes -= oldest[1].bytes;
|
|
8572
|
+
}
|
|
8573
|
+
|
|
8574
|
+
// src/topology-routing.ts
|
|
7796
8575
|
function routingKeyFromProtocolPayload(name, command) {
|
|
7797
8576
|
if (command.opcode < 256 || name === "CLUSTER.KEYSLOT" || name === "SHARDS" || name === "ROUTE") {
|
|
7798
8577
|
return void 0;
|
|
7799
8578
|
}
|
|
7800
8579
|
if (isPlainObject3(command.payload)) {
|
|
7801
|
-
for (const
|
|
8580
|
+
for (const field3 of [
|
|
7802
8581
|
"key",
|
|
7803
8582
|
"partition_key",
|
|
7804
8583
|
"id",
|
|
@@ -7808,8 +8587,8 @@ function routingKeyFromProtocolPayload(name, command) {
|
|
|
7808
8587
|
"correlation_id",
|
|
7809
8588
|
"scope"
|
|
7810
8589
|
]) {
|
|
7811
|
-
const value = getField(command.payload,
|
|
7812
|
-
if (typeof value === "string" ||
|
|
8590
|
+
const value = getField(command.payload, field3);
|
|
8591
|
+
if (typeof value === "string" || Buffer35.isBuffer(value)) {
|
|
7813
8592
|
return value;
|
|
7814
8593
|
}
|
|
7815
8594
|
}
|
|
@@ -7843,6 +8622,7 @@ function flowRoutingData(name, args) {
|
|
|
7843
8622
|
if (flowScheduleCommands.has(name)) {
|
|
7844
8623
|
return void 0;
|
|
7845
8624
|
}
|
|
8625
|
+
if (name === "FLOW.QUERY") return void 0;
|
|
7846
8626
|
if (flowApprovalIdCommands.has(name)) {
|
|
7847
8627
|
const id = flowArgs[0];
|
|
7848
8628
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(id));
|
|
@@ -7856,7 +8636,7 @@ function flowRoutingData(name, args) {
|
|
|
7856
8636
|
if (typeof partition === "string" && partition.toUpperCase() !== "AUTO" && partition.toUpperCase() !== "MIXED") {
|
|
7857
8637
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
7858
8638
|
}
|
|
7859
|
-
if (
|
|
8639
|
+
if (Buffer35.isBuffer(partition)) {
|
|
7860
8640
|
const text3 = partition.toString("utf8").toUpperCase();
|
|
7861
8641
|
if (text3 !== "AUTO" && text3 !== "MIXED") {
|
|
7862
8642
|
return flowRoutingResult(flowLogicalPartitionRoutingKey(partition));
|
|
@@ -7947,46 +8727,17 @@ function flowPartitionRoutingKeyFromCommand(command, claim) {
|
|
|
7947
8727
|
return { handled: false };
|
|
7948
8728
|
}
|
|
7949
8729
|
function isRoutingKey(value) {
|
|
7950
|
-
return typeof value === "string" ||
|
|
7951
|
-
}
|
|
7952
|
-
function flowLogicalPartitionRoutingKey(value) {
|
|
7953
|
-
if (typeof value !== "string" && !Buffer28.isBuffer(value)) {
|
|
7954
|
-
return void 0;
|
|
7955
|
-
}
|
|
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);
|
|
7959
|
-
if (autoMatch != null) {
|
|
7960
|
-
const bucket = Number(autoMatch[1]);
|
|
7961
|
-
if (bucket < 256) {
|
|
7962
|
-
return `{fa:${bucket}}`;
|
|
7963
|
-
}
|
|
7964
|
-
}
|
|
7965
|
-
const cacheKey = `${Buffer28.isBuffer(value) ? "b" : "s"}:${bytes2.toString("base64")}`;
|
|
7966
|
-
const cached = flowPartitionRouteCache.get(cacheKey);
|
|
7967
|
-
if (cached != null) {
|
|
7968
|
-
flowPartitionRouteCache.delete(cacheKey);
|
|
7969
|
-
flowPartitionRouteCache.set(cacheKey, cached);
|
|
7970
|
-
return cached;
|
|
7971
|
-
}
|
|
7972
|
-
const digest = createHash("sha256").update(bytes2).digest("base64url");
|
|
7973
|
-
const routeKey = `{f:${digest}}`;
|
|
7974
|
-
if (flowPartitionRouteCache.size >= FLOW_PARTITION_ROUTE_CACHE_MAX) {
|
|
7975
|
-
const oldest = flowPartitionRouteCache.keys().next().value;
|
|
7976
|
-
if (oldest != null) flowPartitionRouteCache.delete(oldest);
|
|
7977
|
-
}
|
|
7978
|
-
flowPartitionRouteCache.set(cacheKey, routeKey);
|
|
7979
|
-
return routeKey;
|
|
8730
|
+
return typeof value === "string" || Buffer35.isBuffer(value);
|
|
7980
8731
|
}
|
|
7981
8732
|
function flowAutoIdRoutingKey(value) {
|
|
7982
|
-
if (typeof value !== "string" && !
|
|
8733
|
+
if (typeof value !== "string" && !Buffer35.isBuffer(value)) {
|
|
7983
8734
|
return void 0;
|
|
7984
8735
|
}
|
|
7985
|
-
const bucket = (
|
|
8736
|
+
const bucket = (Buffer35.isBuffer(value) ? crc32(value) : crc32Utf8(value)) & 255;
|
|
7986
8737
|
return `{fa:${bucket}}`;
|
|
7987
8738
|
}
|
|
7988
8739
|
function flowClaimLogicalPartitionRoutingKey(value) {
|
|
7989
|
-
if (typeof value !== "string" && !
|
|
8740
|
+
if (typeof value !== "string" && !Buffer35.isBuffer(value)) return void 0;
|
|
7990
8741
|
const selector = commandPart(value);
|
|
7991
8742
|
if (selector === "AUTO" || selector === "ANY") return void 0;
|
|
7992
8743
|
if (selector === "GLOBAL") return "{f}";
|
|
@@ -8001,7 +8752,7 @@ function singleShardFlowClaimPartitionKey(values) {
|
|
|
8001
8752
|
return keys.some((key) => key == null) ? void 0 : singleShardKey(keys);
|
|
8002
8753
|
}
|
|
8003
8754
|
function singleShardKey(keys) {
|
|
8004
|
-
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !
|
|
8755
|
+
if (keys.length === 0 || keys.some((key) => typeof key !== "string" && !Buffer35.isBuffer(key))) {
|
|
8005
8756
|
return void 0;
|
|
8006
8757
|
}
|
|
8007
8758
|
const usable = keys;
|
|
@@ -8012,7 +8763,7 @@ function singleShardKey(keys) {
|
|
|
8012
8763
|
const firstSlot = routingSlotForKey(first);
|
|
8013
8764
|
return usable.every((key) => routingSlotForKey(key) === firstSlot) ? first : void 0;
|
|
8014
8765
|
}
|
|
8015
|
-
function
|
|
8766
|
+
function commandName3(args) {
|
|
8016
8767
|
return commandView(args).name;
|
|
8017
8768
|
}
|
|
8018
8769
|
var commandPart = commandToken;
|
|
@@ -8034,7 +8785,7 @@ function routedKeyGroups(keys, routeKey) {
|
|
|
8034
8785
|
const groups = /* @__PURE__ */ new Map();
|
|
8035
8786
|
for (let index = 0; index < keys.length; index += 1) {
|
|
8036
8787
|
const key = keys[index];
|
|
8037
|
-
if (typeof key !== "string" && !
|
|
8788
|
+
if (typeof key !== "string" && !Buffer35.isBuffer(key)) return void 0;
|
|
8038
8789
|
const route = routeKey(key);
|
|
8039
8790
|
const groupKey = `${route.endpointKey}\0${route.laneId}`;
|
|
8040
8791
|
const group = groups.get(groupKey);
|
|
@@ -8426,7 +9177,7 @@ var TopologyPipelineExecutor = class {
|
|
|
8426
9177
|
commands.forEach((command, index) => {
|
|
8427
9178
|
const routed = this.context.routeData(command);
|
|
8428
9179
|
if (routed == null) {
|
|
8429
|
-
if (decomposableCommandNames.has(
|
|
9180
|
+
if (decomposableCommandNames.has(commandName3(command) ?? "")) standalone.push({ command, index });
|
|
8430
9181
|
else {
|
|
8431
9182
|
controlCommands.push(command);
|
|
8432
9183
|
controlIndices.push(index);
|
|
@@ -8642,7 +9393,7 @@ function topologyRouteIsCurrent(topology, route) {
|
|
|
8642
9393
|
// src/topology-route-planner.ts
|
|
8643
9394
|
function topologyRouteData(args, route) {
|
|
8644
9395
|
if (args.length === 0) return void 0;
|
|
8645
|
-
const name =
|
|
9396
|
+
const name = commandName3(args);
|
|
8646
9397
|
if (name?.startsWith("FLOW.") === true) {
|
|
8647
9398
|
const routed = flowRoutingData(name, args);
|
|
8648
9399
|
return routed == null ? void 0 : {
|
|
@@ -8671,7 +9422,7 @@ var TopologyScatterExecutor = class {
|
|
|
8671
9422
|
}
|
|
8672
9423
|
dependencies;
|
|
8673
9424
|
async execute(args) {
|
|
8674
|
-
const name =
|
|
9425
|
+
const name = commandName3(args);
|
|
8675
9426
|
if (name === "MGET") {
|
|
8676
9427
|
const value = await this.scatterArray(name, args.slice(1));
|
|
8677
9428
|
return value == null ? { handled: false } : { handled: true, value };
|
|
@@ -8753,6 +9504,18 @@ var TopologyScatterExecutor = class {
|
|
|
8753
9504
|
}
|
|
8754
9505
|
};
|
|
8755
9506
|
|
|
9507
|
+
// src/topology-reroute-retry.ts
|
|
9508
|
+
async function canRetrySafeReroute(error, attempt, retryAllowed, refresh, assertOpen) {
|
|
9509
|
+
if (attempt !== 0 || !isRetryableRouteError(error)) return false;
|
|
9510
|
+
const refreshed = await refresh().then(
|
|
9511
|
+
() => true,
|
|
9512
|
+
() => false
|
|
9513
|
+
);
|
|
9514
|
+
if (!refreshed || !retryAllowed || !await waitForExplicitlySafeReroute(error)) return false;
|
|
9515
|
+
assertOpen();
|
|
9516
|
+
return true;
|
|
9517
|
+
}
|
|
9518
|
+
|
|
8756
9519
|
// src/topology.ts
|
|
8757
9520
|
var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
8758
9521
|
adapterOptions;
|
|
@@ -8794,15 +9557,15 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8794
9557
|
this.adapterOptions = {
|
|
8795
9558
|
...adapterOptions,
|
|
8796
9559
|
events: [.../* @__PURE__ */ new Set([...adapterOptions.events ?? [], "TOPOLOGY_CHANGED"])],
|
|
8797
|
-
onEvent: (
|
|
9560
|
+
onEvent: (event2) => {
|
|
8798
9561
|
try {
|
|
8799
|
-
const callback = userOnEvent?.(
|
|
9562
|
+
const callback = userOnEvent?.(event2);
|
|
8800
9563
|
if (callback != null) {
|
|
8801
9564
|
void Promise.resolve(callback).catch(() => void 0);
|
|
8802
9565
|
}
|
|
8803
9566
|
} catch {
|
|
8804
9567
|
}
|
|
8805
|
-
if (!this.closed && nativeEventName(
|
|
9568
|
+
if (!this.closed && nativeEventName(event2) === "TOPOLOGY_CHANGED") {
|
|
8806
9569
|
this.requestTopologyRefresh();
|
|
8807
9570
|
}
|
|
8808
9571
|
}
|
|
@@ -8938,6 +9701,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8938
9701
|
this.assertOpen();
|
|
8939
9702
|
const snapshot = snapshotCommandArguments(args);
|
|
8940
9703
|
assertCommandHasStableConnectionState(snapshot);
|
|
9704
|
+
const casMutation = isCasMutation(snapshot);
|
|
8941
9705
|
let rerouteAttempt = 0;
|
|
8942
9706
|
for (let planningAttempt = 0; planningAttempt < MAX_TOPOLOGY_PLANNING_ATTEMPTS; planningAttempt += 1) {
|
|
8943
9707
|
const routed = this.routeData(snapshot);
|
|
@@ -8953,7 +9717,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8953
9717
|
try {
|
|
8954
9718
|
return routed.command == null ? await adapter.executeCommandOnLane(snapshot, routed.route.laneId) : await adapter.executeProtocolCommand(routed.command, routed.route.laneId);
|
|
8955
9719
|
} catch (error) {
|
|
8956
|
-
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt)) {
|
|
9720
|
+
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt, !casMutation)) {
|
|
8957
9721
|
rerouteAttempt += 1;
|
|
8958
9722
|
continue;
|
|
8959
9723
|
}
|
|
@@ -8995,6 +9759,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
8995
9759
|
assertCommandHasStableConnectionState(command);
|
|
8996
9760
|
}
|
|
8997
9761
|
let rerouteAttempt = 0;
|
|
9762
|
+
const containsCasMutation = snapshot.some(isCasMutation);
|
|
8998
9763
|
for (let planningAttempt = 0; planningAttempt < MAX_TOPOLOGY_PLANNING_ATTEMPTS; planningAttempt += 1) {
|
|
8999
9764
|
const route = singleRouteForCommands(snapshot, (command) => this.routeData(command));
|
|
9000
9765
|
if (route == null) return void 0;
|
|
@@ -9003,7 +9768,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
9003
9768
|
try {
|
|
9004
9769
|
return await adapter.executeFusedPipelineOnLane(snapshot, route.laneId, snapshotOptions);
|
|
9005
9770
|
} catch (error) {
|
|
9006
|
-
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt)) {
|
|
9771
|
+
if (await this.refreshAndCanRetrySafeReroute(error, rerouteAttempt, !containsCasMutation)) {
|
|
9007
9772
|
rerouteAttempt += 1;
|
|
9008
9773
|
continue;
|
|
9009
9774
|
}
|
|
@@ -9012,15 +9777,14 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
9012
9777
|
}
|
|
9013
9778
|
throw new StaleTopologyRouteError();
|
|
9014
9779
|
}
|
|
9015
|
-
async refreshAndCanRetrySafeReroute(error, attempt) {
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9780
|
+
async refreshAndCanRetrySafeReroute(error, attempt, retryAllowed = true) {
|
|
9781
|
+
return await canRetrySafeReroute(
|
|
9782
|
+
error,
|
|
9783
|
+
attempt,
|
|
9784
|
+
retryAllowed,
|
|
9785
|
+
async () => await this.refreshTopology(),
|
|
9786
|
+
() => this.assertOpen()
|
|
9020
9787
|
);
|
|
9021
|
-
if (!refreshed || !await waitForExplicitlySafeReroute(error)) return false;
|
|
9022
|
-
this.assertOpen();
|
|
9023
|
-
return true;
|
|
9024
9788
|
}
|
|
9025
9789
|
async executePipelineOnRoute(commands, route, options) {
|
|
9026
9790
|
const adapter = await this.adapterForCurrentRoute(route);
|
|
@@ -9110,7 +9874,7 @@ var TopologyNativeAdapterPool = class _TopologyNativeAdapterPool {
|
|
|
9110
9874
|
};
|
|
9111
9875
|
|
|
9112
9876
|
// src/response-map-preservation.ts
|
|
9113
|
-
import { Buffer as
|
|
9877
|
+
import { Buffer as Buffer37 } from "buffer";
|
|
9114
9878
|
function toStringKeyMapPreservingValues(value) {
|
|
9115
9879
|
if (value == null) return void 0;
|
|
9116
9880
|
const result = {};
|
|
@@ -9120,7 +9884,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
9120
9884
|
}
|
|
9121
9885
|
return result;
|
|
9122
9886
|
}
|
|
9123
|
-
if (typeof value === "object" && !Array.isArray(value) && !
|
|
9887
|
+
if (typeof value === "object" && !Array.isArray(value) && !Buffer37.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9124
9888
|
for (const [key, item] of Object.entries(value)) {
|
|
9125
9889
|
setOwnValue(result, text(key), normalizeMapStructurePreservingBytes(item));
|
|
9126
9890
|
}
|
|
@@ -9129,7 +9893,7 @@ function toStringKeyMapPreservingValues(value) {
|
|
|
9129
9893
|
return void 0;
|
|
9130
9894
|
}
|
|
9131
9895
|
function normalizeMapStructurePreservingBytes(value) {
|
|
9132
|
-
if (
|
|
9896
|
+
if (Buffer37.isBuffer(value) || value instanceof Uint8Array) return value;
|
|
9133
9897
|
if (value instanceof Map) {
|
|
9134
9898
|
const result = {};
|
|
9135
9899
|
for (const [key, item] of value.entries()) {
|
|
@@ -9151,7 +9915,7 @@ function normalizeMapStructurePreservingBytes(value) {
|
|
|
9151
9915
|
}
|
|
9152
9916
|
|
|
9153
9917
|
// src/native-kv-responses.ts
|
|
9154
|
-
import { Buffer as
|
|
9918
|
+
import { Buffer as Buffer38 } from "buffer";
|
|
9155
9919
|
function rateLimitResultFromResp(value) {
|
|
9156
9920
|
if (!Array.isArray(value) || value.length !== 4) {
|
|
9157
9921
|
throw new TypeError("RATELIMIT.ADD returned an unexpected response");
|
|
@@ -9208,13 +9972,13 @@ function fetchOrComputeResultFromResp(value, codec) {
|
|
|
9208
9972
|
}
|
|
9209
9973
|
function decodePayload(codec, value) {
|
|
9210
9974
|
if (value == null) return null;
|
|
9211
|
-
if (
|
|
9212
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
9213
|
-
if (typeof value === "string") return codec.decode(
|
|
9975
|
+
if (Buffer38.isBuffer(value)) return codec.decode(value);
|
|
9976
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer38.from(value));
|
|
9977
|
+
if (typeof value === "string") return codec.decode(Buffer38.from(value));
|
|
9214
9978
|
return normalizeRefMeta(value);
|
|
9215
9979
|
}
|
|
9216
9980
|
function requiredResponseString(value, context) {
|
|
9217
|
-
if (typeof value !== "string" && !
|
|
9981
|
+
if (typeof value !== "string" && !Buffer38.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9218
9982
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9219
9983
|
}
|
|
9220
9984
|
const result = text(value);
|
|
@@ -9231,7 +9995,7 @@ function requiredNonNegativeInteger(value, context) {
|
|
|
9231
9995
|
return result;
|
|
9232
9996
|
}
|
|
9233
9997
|
function responseBytes(value, context) {
|
|
9234
|
-
if (typeof value !== "string" && !
|
|
9998
|
+
if (typeof value !== "string" && !Buffer38.isBuffer(value) && !(value instanceof Uint8Array)) {
|
|
9235
9999
|
throw new TypeError(`${context} returned an unexpected response`);
|
|
9236
10000
|
}
|
|
9237
10001
|
return bytes(value);
|
|
@@ -9554,17 +10318,6 @@ function finiteNonNegativeInteger(value, fallback) {
|
|
|
9554
10318
|
function finiteNonNegativeNumber(value, fallback) {
|
|
9555
10319
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(0, value);
|
|
9556
10320
|
}
|
|
9557
|
-
function appendReadOptions(args, options) {
|
|
9558
|
-
append(args, "COUNT", options.count);
|
|
9559
|
-
append(args, "PARTITION", options.partitionKey);
|
|
9560
|
-
append(args, "FROM_MS", options.fromMs);
|
|
9561
|
-
append(args, "TO_MS", options.toMs);
|
|
9562
|
-
appendBool(args, "REV", options.rev);
|
|
9563
|
-
append(args, "STATE", options.state);
|
|
9564
|
-
appendBool(args, "TERMINAL_ONLY", options.terminalOnly);
|
|
9565
|
-
appendBool(args, "INCLUDE_COLD", options.includeCold);
|
|
9566
|
-
appendBool(args, "CONSISTENT_PROJECTION", options.consistentProjection);
|
|
9567
|
-
}
|
|
9568
10321
|
function appendAttributeQueryOptions(args, options) {
|
|
9569
10322
|
append(args, "STATE", options.state);
|
|
9570
10323
|
append(args, "PARTITION", options.partitionKey);
|
|
@@ -9618,22 +10371,6 @@ function appendAttributes(args, attributes) {
|
|
|
9618
10371
|
args.push("ATTRIBUTE", name, value);
|
|
9619
10372
|
}
|
|
9620
10373
|
}
|
|
9621
|
-
function appendSearchStateMeta(args, state, stateMeta) {
|
|
9622
|
-
const entries = Object.entries(stateMeta ?? {});
|
|
9623
|
-
if (entries.length === 0) {
|
|
9624
|
-
return;
|
|
9625
|
-
}
|
|
9626
|
-
if (entries.every(([, value]) => isPlainObject5(value))) {
|
|
9627
|
-
for (const [metaState, values] of entries) {
|
|
9628
|
-
args.push("STATE_META", metaState, values);
|
|
9629
|
-
}
|
|
9630
|
-
return;
|
|
9631
|
-
}
|
|
9632
|
-
if (state == null) {
|
|
9633
|
-
throw new Error("search stateMeta filters require state or nested state metadata");
|
|
9634
|
-
}
|
|
9635
|
-
args.push("STATE_META", state, stateMeta);
|
|
9636
|
-
}
|
|
9637
10374
|
function normalizeAdminResponse(value) {
|
|
9638
10375
|
return normalizeRefMeta(value);
|
|
9639
10376
|
}
|
|
@@ -9941,7 +10678,7 @@ function groupAutoPartitionItems(items) {
|
|
|
9941
10678
|
}
|
|
9942
10679
|
|
|
9943
10680
|
// src/client-values.ts
|
|
9944
|
-
import { Buffer as
|
|
10681
|
+
import { Buffer as Buffer39 } from "buffer";
|
|
9945
10682
|
async function valueMGetEntries(client, refs, options = {}) {
|
|
9946
10683
|
const refCount = refs.length;
|
|
9947
10684
|
if (refCount === 0) {
|
|
@@ -9976,12 +10713,12 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9976
10713
|
const item = response[index];
|
|
9977
10714
|
if (item == null) {
|
|
9978
10715
|
entries[index] = { found: false };
|
|
9979
|
-
} else if (
|
|
10716
|
+
} else if (Buffer39.isBuffer(item)) {
|
|
9980
10717
|
entries[index] = { found: true, value: client.codec.decode(item) };
|
|
9981
10718
|
} else if (item instanceof Uint8Array) {
|
|
9982
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10719
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer39.from(item)) };
|
|
9983
10720
|
} else if (typeof item === "string") {
|
|
9984
|
-
entries[index] = { found: true, value: client.codec.decode(
|
|
10721
|
+
entries[index] = { found: true, value: client.codec.decode(Buffer39.from(item)) };
|
|
9985
10722
|
} else {
|
|
9986
10723
|
entries[index] = { found: true, value: item };
|
|
9987
10724
|
}
|
|
@@ -9993,7 +10730,7 @@ async function valueMGetEntries(client, refs, options = {}) {
|
|
|
9993
10730
|
import "buffer";
|
|
9994
10731
|
|
|
9995
10732
|
// src/auto-batch-ordering.ts
|
|
9996
|
-
import { Buffer as
|
|
10733
|
+
import { Buffer as Buffer40 } from "buffer";
|
|
9997
10734
|
function autoBatchOrderingPlan(batch) {
|
|
9998
10735
|
const accesses = /* @__PURE__ */ new Map();
|
|
9999
10736
|
const fallbackDependencies = [];
|
|
@@ -10108,13 +10845,13 @@ function flowManyAutoBatchIds(command, name) {
|
|
|
10108
10845
|
return fixedFlowItemIds(
|
|
10109
10846
|
command,
|
|
10110
10847
|
mixed ? 4 : 3,
|
|
10111
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) &&
|
|
10848
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && isFencingToken(command[itemIndex + (mixed ? 2 : 1)]) && Buffer40.isBuffer(command[itemIndex + (mixed ? 3 : 2)])
|
|
10112
10849
|
);
|
|
10113
10850
|
}
|
|
10114
10851
|
return fixedFlowItemIds(
|
|
10115
10852
|
command,
|
|
10116
10853
|
mixed ? 4 : 3,
|
|
10117
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10854
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer40.isBuffer(command[itemIndex + (mixed ? 2 : 1)]) && isFencingToken(command[itemIndex + (mixed ? 3 : 2)])
|
|
10118
10855
|
);
|
|
10119
10856
|
}
|
|
10120
10857
|
function createManyAutoBatchIds(command) {
|
|
@@ -10127,7 +10864,7 @@ function createManyAutoBatchIds(command) {
|
|
|
10127
10864
|
const ids = fixedFlowItemIds(
|
|
10128
10865
|
command,
|
|
10129
10866
|
width,
|
|
10130
|
-
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) &&
|
|
10867
|
+
(itemIndex) => isAutoBatchResourceValue(command[itemIndex]) && (!mixed || isAutoBatchResourceValue(command[itemIndex + 1])) && Buffer40.isBuffer(command[itemIndex + width - 1]),
|
|
10131
10868
|
markerIndex
|
|
10132
10869
|
);
|
|
10133
10870
|
if (ids != null) return ids;
|
|
@@ -10145,7 +10882,7 @@ function extendedCreateManyAutoBatchIds(command, markerIndex) {
|
|
|
10145
10882
|
let cursor = markerIndex + 2;
|
|
10146
10883
|
for (let itemIndex = 0; itemIndex < itemCount; itemIndex += 1) {
|
|
10147
10884
|
const id = command[cursor];
|
|
10148
|
-
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !
|
|
10885
|
+
if (!isAutoBatchResourceValue(id) || !isAutoBatchResourceValue(command[cursor + 1]) || !Buffer40.isBuffer(command[cursor + 2])) return void 0;
|
|
10149
10886
|
ids.push(id);
|
|
10150
10887
|
cursor += 3;
|
|
10151
10888
|
const afterValues = skipExtendedNamedItems(command, cursor, true);
|
|
@@ -10164,7 +10901,7 @@ function skipExtendedNamedItems(command, countIndex, encodedValues) {
|
|
|
10164
10901
|
for (let index = 0; index < count; index += 1) {
|
|
10165
10902
|
const name = command[firstItem + index * 2];
|
|
10166
10903
|
const value = command[firstItem + index * 2 + 1];
|
|
10167
|
-
if (!isAutoBatchResourceValue(name) || (encodedValues ? !
|
|
10904
|
+
if (!isAutoBatchResourceValue(name) || (encodedValues ? !Buffer40.isBuffer(value) : !isAutoBatchResourceValue(value))) return void 0;
|
|
10168
10905
|
}
|
|
10169
10906
|
return firstItem + count * 2;
|
|
10170
10907
|
}
|
|
@@ -10179,7 +10916,7 @@ function runStepsManyAutoBatchIds(command) {
|
|
|
10179
10916
|
ids.push(item);
|
|
10180
10917
|
continue;
|
|
10181
10918
|
}
|
|
10182
|
-
if (typeof item !== "object" || item == null || Array.isArray(item) ||
|
|
10919
|
+
if (typeof item !== "object" || item == null || Array.isArray(item) || Buffer40.isBuffer(item)) return void 0;
|
|
10183
10920
|
const id = item.id;
|
|
10184
10921
|
if (!isAutoBatchResourceValue(id)) return void 0;
|
|
10185
10922
|
ids.push(id);
|
|
@@ -10220,7 +10957,7 @@ function flowValuePutOwner(command, start) {
|
|
|
10220
10957
|
}
|
|
10221
10958
|
var flowValuePutOptionTokens = /* @__PURE__ */ new Set(["NAME", "NOW", "OVERRIDE", "OWNER_FLOW_ID", "PARTITION", "TTL", "TTL_MS"]);
|
|
10222
10959
|
function isAutoBatchResourceValue(value) {
|
|
10223
|
-
return typeof value === "string" ||
|
|
10960
|
+
return typeof value === "string" || Buffer40.isBuffer(value);
|
|
10224
10961
|
}
|
|
10225
10962
|
function isFencingToken(value) {
|
|
10226
10963
|
return typeof value === "number" && Number.isSafeInteger(value) || typeof value === "bigint";
|
|
@@ -10229,7 +10966,7 @@ function nonNegativeItemCount(value) {
|
|
|
10229
10966
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : void 0;
|
|
10230
10967
|
}
|
|
10231
10968
|
function autoBatchResourceKey(namespace, value) {
|
|
10232
|
-
return `${namespace}:${
|
|
10969
|
+
return `${namespace}:${Buffer40.from(value).toString("base64")}`;
|
|
10233
10970
|
}
|
|
10234
10971
|
function autoBatchCommandName(command) {
|
|
10235
10972
|
return commandView(command).name ?? null;
|
|
@@ -10605,7 +11342,7 @@ async function hydrateClaimedRecords(claimed, concurrency, hydrate) {
|
|
|
10605
11342
|
const results = new Array(claimed.length);
|
|
10606
11343
|
let cursor = 0;
|
|
10607
11344
|
let failure;
|
|
10608
|
-
const
|
|
11345
|
+
const run2 = async () => {
|
|
10609
11346
|
while (failure == null) {
|
|
10610
11347
|
const index = cursor;
|
|
10611
11348
|
cursor += 1;
|
|
@@ -10618,7 +11355,7 @@ async function hydrateClaimedRecords(claimed, concurrency, hydrate) {
|
|
|
10618
11355
|
}
|
|
10619
11356
|
}
|
|
10620
11357
|
};
|
|
10621
|
-
await Promise.all(Array.from({ length: Math.min(concurrency, claimed.length) },
|
|
11358
|
+
await Promise.all(Array.from({ length: Math.min(concurrency, claimed.length) }, run2));
|
|
10622
11359
|
if (failure != null) {
|
|
10623
11360
|
const hydratedItems = [];
|
|
10624
11361
|
for (let index = 0; index < results.length; index += 1) {
|
|
@@ -10640,70 +11377,1038 @@ function claimFailure(error) {
|
|
|
10640
11377
|
// src/client-flow-support.ts
|
|
10641
11378
|
import "buffer";
|
|
10642
11379
|
|
|
10643
|
-
// src/
|
|
10644
|
-
import "buffer";
|
|
11380
|
+
// src/flow-query-builder.ts
|
|
11381
|
+
import { Buffer as Buffer43 } from "buffer";
|
|
10645
11382
|
|
|
10646
|
-
// src/
|
|
10647
|
-
import { Buffer as
|
|
10648
|
-
|
|
10649
|
-
|
|
10650
|
-
|
|
11383
|
+
// src/flow-query-metadata.ts
|
|
11384
|
+
import { Buffer as Buffer42 } from "buffer";
|
|
11385
|
+
var MAX_FLOW_QUERY_METADATA_KEY_BYTES = 64;
|
|
11386
|
+
function normalizeStateMeta(value, state) {
|
|
11387
|
+
if (value == null) return {};
|
|
11388
|
+
const entries = objectEntries(value, "stateMeta");
|
|
11389
|
+
if (entries.length === 0) return {};
|
|
11390
|
+
const nested = entries.map(([, item]) => isPlainRecord(item));
|
|
11391
|
+
if (nested.every(Boolean)) {
|
|
11392
|
+
return value;
|
|
10651
11393
|
}
|
|
10652
|
-
|
|
10653
|
-
}
|
|
10654
|
-
function clientNameResponse(response) {
|
|
10655
|
-
return response == null ? null : textResponse(response, "CLIENT GETNAME");
|
|
10656
|
-
}
|
|
10657
|
-
function fetchOrComputeCompletionToken(options) {
|
|
10658
|
-
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
11394
|
+
if (nested.some(Boolean)) {
|
|
10659
11395
|
throw new TypeError(
|
|
10660
|
-
"
|
|
11396
|
+
"stateMeta must be entirely flat or entirely nested by state"
|
|
10661
11397
|
);
|
|
10662
11398
|
}
|
|
10663
|
-
if (
|
|
10664
|
-
throw new TypeError(
|
|
11399
|
+
if (state == null || state === "" || state === "any") {
|
|
11400
|
+
throw new TypeError(
|
|
11401
|
+
"FLOW.QUERY stateMeta filters require state; a concrete state is required"
|
|
11402
|
+
);
|
|
10665
11403
|
}
|
|
10666
|
-
return
|
|
11404
|
+
return { [state]: value };
|
|
10667
11405
|
}
|
|
10668
|
-
function
|
|
10669
|
-
const
|
|
10670
|
-
|
|
10671
|
-
|
|
10672
|
-
|
|
11406
|
+
function metadataEntries(value, context) {
|
|
11407
|
+
const entries = objectEntries(value ?? {}, context).map(([rawName, item]) => {
|
|
11408
|
+
const name = rawName.trim();
|
|
11409
|
+
const size = Buffer42.byteLength(name, "utf8");
|
|
11410
|
+
if (size === 0 || size > MAX_FLOW_QUERY_METADATA_KEY_BYTES || name.startsWith("__")) {
|
|
11411
|
+
throw new TypeError(`${context} key is invalid or reserved`);
|
|
11412
|
+
}
|
|
11413
|
+
return [name, item];
|
|
11414
|
+
});
|
|
11415
|
+
entries.sort(([left], [right]) => compareUnicodeScalars(left, right));
|
|
11416
|
+
for (let index = 1; index < entries.length; index += 1) {
|
|
11417
|
+
if (entries[index - 1]?.[0] === entries[index]?.[0]) {
|
|
11418
|
+
throw new TypeError(`${context} key is duplicated after normalization`);
|
|
11419
|
+
}
|
|
10673
11420
|
}
|
|
10674
|
-
return
|
|
11421
|
+
return entries;
|
|
10675
11422
|
}
|
|
10676
|
-
function
|
|
10677
|
-
|
|
10678
|
-
|
|
10679
|
-
);
|
|
11423
|
+
function objectEntries(value, context) {
|
|
11424
|
+
if (!isPlainRecord(value))
|
|
11425
|
+
throw new TypeError(`${context} must be a plain object`);
|
|
11426
|
+
const keys = Reflect.ownKeys(value);
|
|
11427
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
11428
|
+
throw new TypeError(`${context} keys must be strings`);
|
|
11429
|
+
}
|
|
11430
|
+
return keys.map((key) => [key, value[key]]);
|
|
10680
11431
|
}
|
|
10681
|
-
function
|
|
10682
|
-
|
|
11432
|
+
function isPlainRecord(value) {
|
|
11433
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer42.isBuffer(value)) {
|
|
11434
|
+
return false;
|
|
11435
|
+
}
|
|
11436
|
+
const prototype = Object.getPrototypeOf(value);
|
|
11437
|
+
return prototype === null || prototype === Object.prototype;
|
|
10683
11438
|
}
|
|
10684
|
-
|
|
10685
|
-
|
|
10686
|
-
|
|
10687
|
-
|
|
10688
|
-
|
|
10689
|
-
|
|
10690
|
-
|
|
10691
|
-
|
|
10692
|
-
|
|
11439
|
+
function metadataSelector(root, ...names) {
|
|
11440
|
+
return root + names.map((name) => `['${name.replaceAll("'", "''")}']`).join("");
|
|
11441
|
+
}
|
|
11442
|
+
function compareUnicodeScalars(left, right) {
|
|
11443
|
+
let leftOffset = 0;
|
|
11444
|
+
let rightOffset = 0;
|
|
11445
|
+
while (leftOffset < left.length && rightOffset < right.length) {
|
|
11446
|
+
const leftCodePoint = left.codePointAt(leftOffset);
|
|
11447
|
+
const rightCodePoint = right.codePointAt(rightOffset);
|
|
11448
|
+
if (leftCodePoint == null || rightCodePoint == null) break;
|
|
11449
|
+
if (leftCodePoint !== rightCodePoint)
|
|
11450
|
+
return leftCodePoint < rightCodePoint ? -1 : 1;
|
|
11451
|
+
leftOffset += leftCodePoint > 65535 ? 2 : 1;
|
|
11452
|
+
rightOffset += rightCodePoint > 65535 ? 2 : 1;
|
|
10693
11453
|
}
|
|
10694
|
-
|
|
10695
|
-
|
|
10696
|
-
|
|
11454
|
+
return left.length === right.length ? 0 : leftOffset === left.length ? -1 : 1;
|
|
11455
|
+
}
|
|
11456
|
+
|
|
11457
|
+
// src/flow-query-builder.ts
|
|
11458
|
+
var MAX_FLOW_QUERY_RESULTS = 100;
|
|
11459
|
+
var MAX_FLOW_QUERY_PARTITION_BYTES = 65535;
|
|
11460
|
+
var MAX_FLOW_QUERY_TIME = Number.MAX_SAFE_INTEGER;
|
|
11461
|
+
var MAX_FLOW_QUERY_STATE_BYTES = 64;
|
|
11462
|
+
var FlowCollectionQuery = class {
|
|
11463
|
+
constructor(partitionKey, limit, reverse) {
|
|
11464
|
+
this.limit = limit;
|
|
11465
|
+
this.reverse = reverse;
|
|
11466
|
+
this.params.partition_key = partitionKey;
|
|
10697
11467
|
}
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
|
|
10701
|
-
|
|
10702
|
-
|
|
11468
|
+
limit;
|
|
11469
|
+
reverse;
|
|
11470
|
+
params = /* @__PURE__ */ Object.create(null);
|
|
11471
|
+
predicates = ["partition_key = @partition_key"];
|
|
11472
|
+
orderField = "updated_at_ms";
|
|
11473
|
+
equality(selector, parameter, value) {
|
|
11474
|
+
this.params[parameter] = queryParameter(value, parameter);
|
|
11475
|
+
this.predicates.push(`${selector} = @${parameter}`);
|
|
11476
|
+
}
|
|
11477
|
+
window(fromMs, toMs) {
|
|
11478
|
+
if (fromMs == null && toMs == null) return;
|
|
11479
|
+
const lower = fromMs == null ? 0 : boundedTime(fromMs, "fromMs");
|
|
11480
|
+
const upper = toMs == null ? MAX_FLOW_QUERY_TIME : boundedTime(toMs, "toMs");
|
|
11481
|
+
if (lower > upper) throw new TypeError("fromMs must not exceed toMs");
|
|
11482
|
+
this.predicates.push("updated_at_ms BETWEEN @from_ms AND @to_ms");
|
|
11483
|
+
this.params.from_ms = lower;
|
|
11484
|
+
this.params.to_ms = upper;
|
|
11485
|
+
}
|
|
11486
|
+
metadata(root, values) {
|
|
11487
|
+
const entries = metadataEntries(values, root);
|
|
11488
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
11489
|
+
const entry = entries[index];
|
|
11490
|
+
if (entry == null) throw new TypeError("metadata entries must be dense");
|
|
11491
|
+
this.equality(
|
|
11492
|
+
metadataSelector(root, entry[0]),
|
|
11493
|
+
`${root}_${index}`,
|
|
11494
|
+
entry[1]
|
|
11495
|
+
);
|
|
10703
11496
|
}
|
|
10704
11497
|
}
|
|
10705
|
-
|
|
10706
|
-
|
|
11498
|
+
stateMetadata(values) {
|
|
11499
|
+
const entries = [];
|
|
11500
|
+
const states = /* @__PURE__ */ new Set();
|
|
11501
|
+
for (const [rawState, metadata] of objectEntries(values, "stateMeta")) {
|
|
11502
|
+
const state = requiredText(rawState, "stateMeta state").trim();
|
|
11503
|
+
const stateBytes = Buffer43.byteLength(state, "utf8");
|
|
11504
|
+
if (stateBytes === 0 || stateBytes > MAX_FLOW_QUERY_STATE_BYTES) {
|
|
11505
|
+
throw new TypeError(
|
|
11506
|
+
`stateMeta state names must be 1..${MAX_FLOW_QUERY_STATE_BYTES} bytes`
|
|
11507
|
+
);
|
|
11508
|
+
}
|
|
11509
|
+
if (states.has(state)) {
|
|
11510
|
+
throw new TypeError(
|
|
11511
|
+
"stateMeta state is duplicated after normalization"
|
|
11512
|
+
);
|
|
11513
|
+
}
|
|
11514
|
+
states.add(state);
|
|
11515
|
+
if (!isPlainRecord(metadata))
|
|
11516
|
+
throw new TypeError("stateMeta values must be metadata maps");
|
|
11517
|
+
for (const [name, value] of metadataEntries(metadata, "stateMeta")) {
|
|
11518
|
+
entries.push([state, name, value]);
|
|
11519
|
+
}
|
|
11520
|
+
}
|
|
11521
|
+
entries.sort(
|
|
11522
|
+
([leftState, leftName], [rightState, rightName]) => compareUnicodeScalars(leftState, rightState) || compareUnicodeScalars(leftName, rightName)
|
|
11523
|
+
);
|
|
11524
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
11525
|
+
const entry = entries[index];
|
|
11526
|
+
if (entry == null) throw new TypeError("stateMeta entries must be dense");
|
|
11527
|
+
this.equality(
|
|
11528
|
+
metadataSelector("state_meta", entry[0], entry[1]),
|
|
11529
|
+
`state_meta_${index}`,
|
|
11530
|
+
entry[2]
|
|
11531
|
+
);
|
|
11532
|
+
}
|
|
11533
|
+
}
|
|
11534
|
+
build() {
|
|
11535
|
+
if (this.predicates.length > 12) {
|
|
11536
|
+
throw new TypeError("FLOW.QUERY accepts at most 12 predicates");
|
|
11537
|
+
}
|
|
11538
|
+
const direction = this.reverse ? "DESC" : "ASC";
|
|
11539
|
+
const query = `FROM runs WHERE ${this.predicates.join(" AND ")} ORDER BY ${this.orderField} ${direction} LIMIT ${this.limit} RETURN RECORDS`;
|
|
11540
|
+
validateFlowQueryText(query);
|
|
11541
|
+
return { query, params: this.params };
|
|
11542
|
+
}
|
|
11543
|
+
};
|
|
11544
|
+
function buildFlowListQuery(type, options) {
|
|
11545
|
+
const attributeCount = Object.keys(options.attributes ?? {}).length;
|
|
11546
|
+
if (type === "any" && attributeCount === 0) {
|
|
11547
|
+
throw new TypeError(
|
|
11548
|
+
"FLOW.QUERY list requires a concrete flow type or an attribute predicate"
|
|
11549
|
+
);
|
|
11550
|
+
}
|
|
11551
|
+
if (options.terminalOnly !== true && options.state === "any" && attributeCount === 0) {
|
|
11552
|
+
throw new TypeError(
|
|
11553
|
+
"FLOW.QUERY list state any requires an attribute predicate"
|
|
11554
|
+
);
|
|
11555
|
+
}
|
|
11556
|
+
const builder = queryBuilder(options);
|
|
11557
|
+
addType(builder, type);
|
|
11558
|
+
if (options.terminalOnly === true) {
|
|
11559
|
+
addTerminalState(builder, options.state);
|
|
11560
|
+
} else if (options.state == null || options.state === "") {
|
|
11561
|
+
builder.equality("state", "state", "queued");
|
|
11562
|
+
} else if (options.state !== "any") {
|
|
11563
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11564
|
+
}
|
|
11565
|
+
builder.metadata("attribute", options.attributes);
|
|
11566
|
+
builder.window(options.fromMs, options.toMs);
|
|
11567
|
+
return builder.build();
|
|
11568
|
+
}
|
|
11569
|
+
function buildFlowSearchQuery(type, options) {
|
|
11570
|
+
const stateMeta = normalizeStateMeta(options.stateMeta, options.state);
|
|
11571
|
+
if (Object.keys(options.attributes ?? {}).length === 0 && Object.keys(stateMeta).length === 0) {
|
|
11572
|
+
throw new TypeError(
|
|
11573
|
+
"FLOW.QUERY search requires an attribute or stateMeta predicate"
|
|
11574
|
+
);
|
|
11575
|
+
}
|
|
11576
|
+
if ((type === "" || type === "any") && Object.keys(stateMeta).length > 0) {
|
|
11577
|
+
throw new TypeError(
|
|
11578
|
+
"FLOW.QUERY stateMeta predicates require a concrete flow type"
|
|
11579
|
+
);
|
|
11580
|
+
}
|
|
11581
|
+
const builder = queryBuilder(options);
|
|
11582
|
+
if (type !== "" && type !== "any")
|
|
11583
|
+
builder.equality("type", "type", requiredText(type, "type"));
|
|
11584
|
+
if (options.terminalOnly === true) {
|
|
11585
|
+
addTerminalState(builder, options.state);
|
|
11586
|
+
} else if (options.state != null && options.state !== "" && options.state !== "any") {
|
|
11587
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11588
|
+
}
|
|
11589
|
+
builder.metadata("attribute", options.attributes);
|
|
11590
|
+
builder.stateMetadata(stateMeta);
|
|
11591
|
+
builder.window(options.fromMs, options.toMs);
|
|
11592
|
+
return builder.build();
|
|
11593
|
+
}
|
|
11594
|
+
function buildFlowTerminalQuery(type, options) {
|
|
11595
|
+
if (requiredText(type, "type") === "any") {
|
|
11596
|
+
throw new TypeError("FLOW.QUERY terminals require a concrete flow type");
|
|
11597
|
+
}
|
|
11598
|
+
if (metadataEntries(options.attributes, "attribute").length > 0) {
|
|
11599
|
+
throw new TypeError(
|
|
11600
|
+
"FLOW.QUERY terminals do not support attribute predicates"
|
|
11601
|
+
);
|
|
11602
|
+
}
|
|
11603
|
+
const builder = queryBuilder(options);
|
|
11604
|
+
addType(builder, type);
|
|
11605
|
+
addTerminalState(builder, options.state);
|
|
11606
|
+
builder.window(options.fromMs, options.toMs);
|
|
11607
|
+
return builder.build();
|
|
11608
|
+
}
|
|
11609
|
+
function buildFlowFailureQuery(type, options) {
|
|
11610
|
+
if (options.state != null && options.state !== "" && options.state !== "any" && options.state !== "failed") {
|
|
11611
|
+
throw new TypeError("FLOW failures state must be failed or any");
|
|
11612
|
+
}
|
|
11613
|
+
return buildFlowListQuery(type, {
|
|
11614
|
+
...options,
|
|
11615
|
+
state: "failed",
|
|
11616
|
+
terminalOnly: false
|
|
11617
|
+
});
|
|
11618
|
+
}
|
|
11619
|
+
function buildFlowLineageQuery(selector, id, options) {
|
|
11620
|
+
if (options.terminalOnly === true) {
|
|
11621
|
+
throw new TypeError("terminalOnly cannot be combined with a lineage query");
|
|
11622
|
+
}
|
|
11623
|
+
if (metadataEntries(options.attributes, "attribute").length > 0) {
|
|
11624
|
+
throw new TypeError(
|
|
11625
|
+
"FLOW.QUERY lineage does not support attribute predicates"
|
|
11626
|
+
);
|
|
11627
|
+
}
|
|
11628
|
+
const builder = queryBuilder(options);
|
|
11629
|
+
builder.equality(selector, "lineage_id", requiredText(id, "lineage id"));
|
|
11630
|
+
if (options.state != null && options.state !== "" && options.state !== "any") {
|
|
11631
|
+
builder.equality("state", "state", requiredText(options.state, "state"));
|
|
11632
|
+
}
|
|
11633
|
+
builder.metadata("attribute", options.attributes);
|
|
11634
|
+
builder.window(options.fromMs, options.toMs);
|
|
11635
|
+
return builder.build();
|
|
11636
|
+
}
|
|
11637
|
+
function buildFlowStuckQuery(type, options) {
|
|
11638
|
+
const concreteType = requiredText(type, "type");
|
|
11639
|
+
if (concreteType === "any") {
|
|
11640
|
+
throw new TypeError("FLOW.QUERY stuck requires a concrete flow type");
|
|
11641
|
+
}
|
|
11642
|
+
const now = options.nowMs == null ? Date.now() : boundedTime(options.nowMs, "nowMs");
|
|
11643
|
+
const older = options.olderThanMs == null ? 0 : boundedTime(options.olderThanMs, "olderThanMs");
|
|
11644
|
+
const cutoff = now - older;
|
|
11645
|
+
if (cutoff < 0) throw new TypeError("olderThanMs must not exceed nowMs");
|
|
11646
|
+
const builder = new FlowCollectionQuery(
|
|
11647
|
+
requiredPartition(options.partitionKey),
|
|
11648
|
+
boundedCount(options.count),
|
|
11649
|
+
false
|
|
11650
|
+
);
|
|
11651
|
+
builder.orderField = "lease_deadline_ms";
|
|
11652
|
+
builder.equality("type", "type", concreteType);
|
|
11653
|
+
builder.equality("state", "state", "running");
|
|
11654
|
+
builder.predicates.push(
|
|
11655
|
+
"lease_deadline_ms BETWEEN @lease_from_ms AND @lease_to_ms"
|
|
11656
|
+
);
|
|
11657
|
+
builder.params.lease_from_ms = 0;
|
|
11658
|
+
builder.params.lease_to_ms = cutoff;
|
|
11659
|
+
return builder.build();
|
|
11660
|
+
}
|
|
11661
|
+
function queryBuilder(options) {
|
|
11662
|
+
if (options.includeCold === true)
|
|
11663
|
+
throw new TypeError("FLOW.QUERY does not expose includeCold");
|
|
11664
|
+
if (options.consistentProjection === true) {
|
|
11665
|
+
throw new TypeError("FLOW.QUERY does not expose consistentProjection");
|
|
11666
|
+
}
|
|
11667
|
+
if (options.rev != null && typeof options.rev !== "boolean") {
|
|
11668
|
+
throw new TypeError("rev must be boolean");
|
|
11669
|
+
}
|
|
11670
|
+
return new FlowCollectionQuery(
|
|
11671
|
+
requiredPartition(options.partitionKey),
|
|
11672
|
+
boundedCount(options.count),
|
|
11673
|
+
options.rev !== false
|
|
11674
|
+
);
|
|
11675
|
+
}
|
|
11676
|
+
function requiredPartition(value) {
|
|
11677
|
+
if (typeof value !== "string") {
|
|
11678
|
+
throw new TypeError(
|
|
11679
|
+
"FLOW.QUERY convenience methods require a partition key"
|
|
11680
|
+
);
|
|
11681
|
+
}
|
|
11682
|
+
const size = Buffer43.byteLength(value, "utf8");
|
|
11683
|
+
if (size === 0 || size > MAX_FLOW_QUERY_PARTITION_BYTES) {
|
|
11684
|
+
throw new TypeError(
|
|
11685
|
+
`FLOW.QUERY partition key must be 1..${MAX_FLOW_QUERY_PARTITION_BYTES} bytes`
|
|
11686
|
+
);
|
|
11687
|
+
}
|
|
11688
|
+
return value;
|
|
11689
|
+
}
|
|
11690
|
+
function boundedCount(value) {
|
|
11691
|
+
if (value == null) return MAX_FLOW_QUERY_RESULTS;
|
|
11692
|
+
if (!Number.isSafeInteger(value) || value < 1 || value > MAX_FLOW_QUERY_RESULTS) {
|
|
11693
|
+
throw new TypeError(
|
|
11694
|
+
`FLOW.QUERY limit must be between 1 and ${MAX_FLOW_QUERY_RESULTS}`
|
|
11695
|
+
);
|
|
11696
|
+
}
|
|
11697
|
+
return value;
|
|
11698
|
+
}
|
|
11699
|
+
function boundedTime(value, name) {
|
|
11700
|
+
if (!Number.isSafeInteger(value) || value < 0 || value > MAX_FLOW_QUERY_TIME) {
|
|
11701
|
+
throw new TypeError(`${name} must be a non-negative safe integer`);
|
|
11702
|
+
}
|
|
11703
|
+
return value;
|
|
11704
|
+
}
|
|
11705
|
+
function addType(builder, type) {
|
|
11706
|
+
const normalized = requiredText(type, "type");
|
|
11707
|
+
if (normalized !== "any") builder.equality("type", "type", normalized);
|
|
11708
|
+
}
|
|
11709
|
+
function addTerminalState(builder, state) {
|
|
11710
|
+
if (state == null || state === "" || state === "any") {
|
|
11711
|
+
builder.predicates.push("state IN (@terminal_0, @terminal_1, @terminal_2)");
|
|
11712
|
+
builder.params.terminal_0 = "completed";
|
|
11713
|
+
builder.params.terminal_1 = "failed";
|
|
11714
|
+
builder.params.terminal_2 = "cancelled";
|
|
11715
|
+
} else if (state === "completed" || state === "failed" || state === "cancelled") {
|
|
11716
|
+
builder.equality("state", "state", state);
|
|
11717
|
+
} else {
|
|
11718
|
+
throw new TypeError(
|
|
11719
|
+
"terminal state must be completed, failed, cancelled, or any"
|
|
11720
|
+
);
|
|
11721
|
+
}
|
|
11722
|
+
}
|
|
11723
|
+
function requiredText(value, context) {
|
|
11724
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
11725
|
+
throw new TypeError(`${context} must be non-empty text`);
|
|
11726
|
+
}
|
|
11727
|
+
return value;
|
|
11728
|
+
}
|
|
11729
|
+
function queryParameter(value, context) {
|
|
11730
|
+
if (typeof value === "string" || typeof value === "boolean" || typeof value === "bigint" || typeof value === "number" || Buffer43.isBuffer(value)) {
|
|
11731
|
+
return value;
|
|
11732
|
+
}
|
|
11733
|
+
throw new TypeError(`${context} must be a scalar FLOW.QUERY parameter`);
|
|
11734
|
+
}
|
|
11735
|
+
|
|
11736
|
+
// src/flow-query-response.ts
|
|
11737
|
+
import { Buffer as Buffer45 } from "buffer";
|
|
11738
|
+
|
|
11739
|
+
// src/flow-query-response-validation.ts
|
|
11740
|
+
import { Buffer as Buffer44 } from "buffer";
|
|
11741
|
+
function requiredMap2(value, context) {
|
|
11742
|
+
if (value instanceof Map) return value;
|
|
11743
|
+
if (typeof value !== "object" || value == null || Array.isArray(value) || Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11744
|
+
throw decodeError(`${context} must be a map`, value);
|
|
11745
|
+
}
|
|
11746
|
+
return value;
|
|
11747
|
+
}
|
|
11748
|
+
function freezeMap(value) {
|
|
11749
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
11750
|
+
const entries = value instanceof Map ? value.entries() : Object.entries(value);
|
|
11751
|
+
for (const [rawKey, item] of entries) {
|
|
11752
|
+
const key = strictText2(rawKey);
|
|
11753
|
+
if (key == null || Object.hasOwn(output, key)) {
|
|
11754
|
+
throw decodeError(
|
|
11755
|
+
"server response map contains an invalid or duplicate key",
|
|
11756
|
+
value
|
|
11757
|
+
);
|
|
11758
|
+
}
|
|
11759
|
+
output[key] = item;
|
|
11760
|
+
}
|
|
11761
|
+
return Object.freeze(output);
|
|
11762
|
+
}
|
|
11763
|
+
function freezeMetadataMap(value, context) {
|
|
11764
|
+
return normalizeMetadataMap(
|
|
11765
|
+
value,
|
|
11766
|
+
context,
|
|
11767
|
+
{ remaining: DEFAULT_MAX_VALUE_ITEMS },
|
|
11768
|
+
/* @__PURE__ */ new Set(),
|
|
11769
|
+
0
|
|
11770
|
+
);
|
|
11771
|
+
}
|
|
11772
|
+
function normalizeMetadataMap(value, context, budget, ancestors, depth) {
|
|
11773
|
+
enterMetadataContainer(value, context, budget, ancestors, depth);
|
|
11774
|
+
try {
|
|
11775
|
+
const output = /* @__PURE__ */ Object.create(null);
|
|
11776
|
+
const entries = value instanceof Map ? value.entries() : Object.entries(value);
|
|
11777
|
+
for (const [rawKey, item] of entries) {
|
|
11778
|
+
const key = strictText2(rawKey);
|
|
11779
|
+
if (key == null || Object.hasOwn(output, key)) {
|
|
11780
|
+
throw decodeError(`${context} contains an invalid or duplicate key`, value);
|
|
11781
|
+
}
|
|
11782
|
+
output[key] = normalizeMetadataValue(
|
|
11783
|
+
item,
|
|
11784
|
+
`${context}.${key}`,
|
|
11785
|
+
budget,
|
|
11786
|
+
ancestors,
|
|
11787
|
+
depth + 1
|
|
11788
|
+
);
|
|
11789
|
+
}
|
|
11790
|
+
return Object.freeze(output);
|
|
11791
|
+
} finally {
|
|
11792
|
+
ancestors.delete(value);
|
|
11793
|
+
}
|
|
11794
|
+
}
|
|
11795
|
+
function normalizeMetadataValue(value, context, budget, ancestors, depth) {
|
|
11796
|
+
if (typeof value === "string") {
|
|
11797
|
+
if (!value.isWellFormed()) throw decodeError(`${context} contains invalid text`, value);
|
|
11798
|
+
return value;
|
|
11799
|
+
}
|
|
11800
|
+
if (Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11801
|
+
const decoded = strictText2(value);
|
|
11802
|
+
if (decoded == null) throw decodeError(`${context} contains invalid UTF-8`, value);
|
|
11803
|
+
return decoded;
|
|
11804
|
+
}
|
|
11805
|
+
if (value == null || typeof value === "boolean" || typeof value === "number" || typeof value === "bigint") {
|
|
11806
|
+
return value;
|
|
11807
|
+
}
|
|
11808
|
+
if (Array.isArray(value)) {
|
|
11809
|
+
enterMetadataContainer(value, context, budget, ancestors, depth);
|
|
11810
|
+
try {
|
|
11811
|
+
const output = new Array(value.length);
|
|
11812
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
11813
|
+
if (!Object.hasOwn(value, index)) {
|
|
11814
|
+
throw decodeError(`${context} must be a dense array`, value);
|
|
11815
|
+
}
|
|
11816
|
+
output[index] = normalizeMetadataValue(
|
|
11817
|
+
value[index],
|
|
11818
|
+
`${context}[${index}]`,
|
|
11819
|
+
budget,
|
|
11820
|
+
ancestors,
|
|
11821
|
+
depth + 1
|
|
11822
|
+
);
|
|
11823
|
+
}
|
|
11824
|
+
return Object.freeze(output);
|
|
11825
|
+
} finally {
|
|
11826
|
+
ancestors.delete(value);
|
|
11827
|
+
}
|
|
11828
|
+
}
|
|
11829
|
+
if (value instanceof Map) {
|
|
11830
|
+
return normalizeMetadataMap(value, context, budget, ancestors, depth);
|
|
11831
|
+
}
|
|
11832
|
+
if (isPlainObject6(value)) {
|
|
11833
|
+
return normalizeMetadataMap(value, context, budget, ancestors, depth);
|
|
11834
|
+
}
|
|
11835
|
+
throw decodeError(`${context} contains an unsupported value`, value);
|
|
11836
|
+
}
|
|
11837
|
+
function enterMetadataContainer(value, context, budget, ancestors, depth) {
|
|
11838
|
+
if (depth >= DEFAULT_MAX_VALUE_DEPTH) {
|
|
11839
|
+
throw decodeError(`${context} exceeds the maximum metadata depth`, value);
|
|
11840
|
+
}
|
|
11841
|
+
if (ancestors.has(value)) throw decodeError(`${context} contains a cycle`, value);
|
|
11842
|
+
const size = Array.isArray(value) ? value.length : value instanceof Map ? value.size : Object.keys(value).length;
|
|
11843
|
+
if (size > budget.remaining) {
|
|
11844
|
+
throw decodeError(`${context} exceeds the maximum metadata items`, value);
|
|
11845
|
+
}
|
|
11846
|
+
budget.remaining -= size;
|
|
11847
|
+
ancestors.add(value);
|
|
11848
|
+
}
|
|
11849
|
+
function isPlainObject6(value) {
|
|
11850
|
+
const prototype = Object.getPrototypeOf(value);
|
|
11851
|
+
return prototype === Object.prototype || prototype === null;
|
|
11852
|
+
}
|
|
11853
|
+
function requireContract(mapping, name, expected, context) {
|
|
11854
|
+
const actual = requiredText2(mapping, name, context);
|
|
11855
|
+
if (actual !== expected) {
|
|
11856
|
+
throw decodeError(
|
|
11857
|
+
`${context} has unsupported contract ${JSON.stringify(actual)}`,
|
|
11858
|
+
mapping
|
|
11859
|
+
);
|
|
11860
|
+
}
|
|
11861
|
+
}
|
|
11862
|
+
function requiredText2(mapping, name, context) {
|
|
11863
|
+
const value = strictText2(field(mapping, name));
|
|
11864
|
+
if (value == null || value.length === 0) {
|
|
11865
|
+
throw decodeError(`${context} ${name} must be non-empty text`, mapping);
|
|
11866
|
+
}
|
|
11867
|
+
return value;
|
|
11868
|
+
}
|
|
11869
|
+
function optionalText2(mapping, name, context) {
|
|
11870
|
+
const raw = field(mapping, name);
|
|
11871
|
+
if (raw == null) return void 0;
|
|
11872
|
+
const value = strictText2(raw);
|
|
11873
|
+
if (value == null)
|
|
11874
|
+
throw decodeError(`${context} ${name} must be text`, mapping);
|
|
11875
|
+
return value;
|
|
11876
|
+
}
|
|
11877
|
+
function requiredBoundedText2(mapping, name, context, maximumBytes) {
|
|
11878
|
+
const value = requiredText2(mapping, name, context);
|
|
11879
|
+
if (Buffer44.byteLength(value, "utf8") > maximumBytes) {
|
|
11880
|
+
throw decodeError(
|
|
11881
|
+
`${context} ${name} exceeds ${maximumBytes} bytes`,
|
|
11882
|
+
mapping
|
|
11883
|
+
);
|
|
11884
|
+
}
|
|
11885
|
+
return value;
|
|
11886
|
+
}
|
|
11887
|
+
function boundedText(value, context, maximumBytes) {
|
|
11888
|
+
const decoded = strictText2(value);
|
|
11889
|
+
if (decoded == null || decoded.length === 0) {
|
|
11890
|
+
throw decodeError(`${context} must be non-empty text`, value);
|
|
11891
|
+
}
|
|
11892
|
+
if (Buffer44.byteLength(decoded, "utf8") > maximumBytes) {
|
|
11893
|
+
throw decodeError(`${context} exceeds ${maximumBytes} bytes`, value);
|
|
11894
|
+
}
|
|
11895
|
+
return decoded;
|
|
11896
|
+
}
|
|
11897
|
+
function requiredBoolean(mapping, name, context) {
|
|
11898
|
+
const value = field(mapping, name);
|
|
11899
|
+
if (typeof value !== "boolean") {
|
|
11900
|
+
throw decodeError(`${context} ${name} must be boolean`, mapping);
|
|
11901
|
+
}
|
|
11902
|
+
return value;
|
|
11903
|
+
}
|
|
11904
|
+
function nonNegativeInteger(value, context) {
|
|
11905
|
+
if (typeof value === "bigint") {
|
|
11906
|
+
if (value >= 0n && value <= BigInt(Number.MAX_SAFE_INTEGER))
|
|
11907
|
+
return Number(value);
|
|
11908
|
+
} else if (typeof value === "number" && Number.isSafeInteger(value) && value >= 0) {
|
|
11909
|
+
return value;
|
|
11910
|
+
}
|
|
11911
|
+
throw decodeError(`${context} must be a non-negative safe integer`, value);
|
|
11912
|
+
}
|
|
11913
|
+
function positiveInteger(value, context) {
|
|
11914
|
+
const parsed = nonNegativeInteger(value, context);
|
|
11915
|
+
if (parsed === 0) throw decodeError(`${context} must be positive`, value);
|
|
11916
|
+
return parsed;
|
|
11917
|
+
}
|
|
11918
|
+
function boundedInteger(value, maximum, context) {
|
|
11919
|
+
let parsed;
|
|
11920
|
+
if (typeof value === "bigint") {
|
|
11921
|
+
parsed = value;
|
|
11922
|
+
} else if (typeof value === "number" && Number.isSafeInteger(value)) {
|
|
11923
|
+
parsed = BigInt(value);
|
|
11924
|
+
} else {
|
|
11925
|
+
throw decodeError(
|
|
11926
|
+
`${context} must be a lossless non-negative integer`,
|
|
11927
|
+
value
|
|
11928
|
+
);
|
|
11929
|
+
}
|
|
11930
|
+
if (parsed < 0n || parsed > maximum) {
|
|
11931
|
+
throw decodeError(
|
|
11932
|
+
`${context} is outside its supported integer range`,
|
|
11933
|
+
value
|
|
11934
|
+
);
|
|
11935
|
+
}
|
|
11936
|
+
return parsed <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(parsed) : parsed;
|
|
11937
|
+
}
|
|
11938
|
+
function positiveBoundedInteger(value, maximum, context) {
|
|
11939
|
+
const parsed = boundedInteger(value, maximum, context);
|
|
11940
|
+
if (parsed === 0) throw decodeError(`${context} must be positive`, value);
|
|
11941
|
+
return parsed;
|
|
11942
|
+
}
|
|
11943
|
+
function hasKey(mapping, name) {
|
|
11944
|
+
if (!(mapping instanceof Map)) return Object.hasOwn(mapping, name);
|
|
11945
|
+
if (mapping.has(name)) return true;
|
|
11946
|
+
const binaryName = Buffer44.from(name);
|
|
11947
|
+
for (const key of mapping.keys()) {
|
|
11948
|
+
if (Buffer44.isBuffer(key) && key.equals(binaryName)) return true;
|
|
11949
|
+
if (key instanceof Uint8Array && Buffer44.from(key).equals(binaryName))
|
|
11950
|
+
return true;
|
|
11951
|
+
}
|
|
11952
|
+
return false;
|
|
11953
|
+
}
|
|
11954
|
+
function decodeError(message, raw) {
|
|
11955
|
+
return new FerricStoreError(`invalid server response: ${message}`, { raw });
|
|
11956
|
+
}
|
|
11957
|
+
function strictText2(value) {
|
|
11958
|
+
if (typeof value === "string")
|
|
11959
|
+
return value.isWellFormed() ? value : void 0;
|
|
11960
|
+
if (Buffer44.isBuffer(value) || value instanceof Uint8Array) {
|
|
11961
|
+
try {
|
|
11962
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(value);
|
|
11963
|
+
} catch {
|
|
11964
|
+
return void 0;
|
|
11965
|
+
}
|
|
11966
|
+
}
|
|
11967
|
+
return void 0;
|
|
11968
|
+
}
|
|
11969
|
+
|
|
11970
|
+
// src/flow-query-types.ts
|
|
11971
|
+
var FlowQueryError = class extends FerricStoreError {
|
|
11972
|
+
code;
|
|
11973
|
+
detail;
|
|
11974
|
+
hint;
|
|
11975
|
+
position;
|
|
11976
|
+
context;
|
|
11977
|
+
constructor(options) {
|
|
11978
|
+
super(options.message, {
|
|
11979
|
+
cause: options.cause,
|
|
11980
|
+
raw: options.raw,
|
|
11981
|
+
retryable: options.retryable,
|
|
11982
|
+
safeToRetry: options.safeToRetry,
|
|
11983
|
+
retryAfterMs: options.retryAfterMs
|
|
11984
|
+
});
|
|
11985
|
+
this.code = options.code;
|
|
11986
|
+
this.detail = options.detail;
|
|
11987
|
+
this.hint = options.hint;
|
|
11988
|
+
this.position = options.position;
|
|
11989
|
+
this.context = options.context;
|
|
11990
|
+
}
|
|
11991
|
+
};
|
|
11992
|
+
|
|
11993
|
+
// src/flow-query-response.ts
|
|
11994
|
+
var FLOW_QUERY_RESULT_CONTRACT = "ferric.flow.query.result/v1";
|
|
11995
|
+
var FLOW_EXPLAIN_CONTRACT = "ferric.flow.explain/v1";
|
|
11996
|
+
var FLOW_QUERY_INDEXES_CONTRACT = "ferric.flow.query.indexes/v1";
|
|
11997
|
+
var USAGE_FIELDS2 = [
|
|
11998
|
+
["range_seeks", "rangeSeeks"],
|
|
11999
|
+
["range_pages", "rangePages"],
|
|
12000
|
+
["scanned_entries", "scannedEntries"],
|
|
12001
|
+
["scanned_bytes", "scannedBytes"],
|
|
12002
|
+
["hydrated_records", "hydratedRecords"],
|
|
12003
|
+
["residual_checks", "residualChecks"],
|
|
12004
|
+
["duplicate_entries", "duplicateEntries"],
|
|
12005
|
+
["result_records", "resultRecords"],
|
|
12006
|
+
["response_bytes", "responseBytes"],
|
|
12007
|
+
["memory_high_water_bytes", "memoryHighWaterBytes"],
|
|
12008
|
+
["wall_time_us", "wallTimeUs"]
|
|
12009
|
+
];
|
|
12010
|
+
var MAX_SIGNED_64 = (1n << 63n) - 1n;
|
|
12011
|
+
var MAX_UNSIGNED_64 = (1n << 64n) - 1n;
|
|
12012
|
+
function decodeFlowQueryResult(value) {
|
|
12013
|
+
const result = decodeFlowQueryResponse(value, (mapping) => freezeMap(mapping));
|
|
12014
|
+
if (result.kind === "records") {
|
|
12015
|
+
return Object.freeze({
|
|
12016
|
+
kind: "records",
|
|
12017
|
+
version: FLOW_QUERY_RESULT_CONTRACT,
|
|
12018
|
+
records: Object.freeze(result.records),
|
|
12019
|
+
page: result.page,
|
|
12020
|
+
quality: result.quality,
|
|
12021
|
+
usage: result.usage,
|
|
12022
|
+
raw: result.raw
|
|
12023
|
+
});
|
|
12024
|
+
}
|
|
12025
|
+
return Object.freeze({
|
|
12026
|
+
kind: "count",
|
|
12027
|
+
version: FLOW_QUERY_RESULT_CONTRACT,
|
|
12028
|
+
count: result.count,
|
|
12029
|
+
quality: result.quality,
|
|
12030
|
+
usage: result.usage,
|
|
12031
|
+
raw: result.raw
|
|
12032
|
+
});
|
|
12033
|
+
}
|
|
12034
|
+
function decodeFlowQueryRecords(value, decodeRecord) {
|
|
12035
|
+
const result = decodeFlowQueryResponse(
|
|
12036
|
+
value,
|
|
12037
|
+
(mapping, index) => decodeRecord(mapping instanceof Map ? freezeMap(mapping) : mapping, index)
|
|
12038
|
+
);
|
|
12039
|
+
if (result.kind === "count") {
|
|
12040
|
+
throw new FerricStoreError("Flow record convenience query returned a count result", {
|
|
12041
|
+
raw: result.raw
|
|
12042
|
+
});
|
|
12043
|
+
}
|
|
12044
|
+
return result.records;
|
|
12045
|
+
}
|
|
12046
|
+
function decodeFlowQueryResponse(value, decodeRecord) {
|
|
12047
|
+
const mapping = requiredMap2(value, "FLOW.QUERY result");
|
|
12048
|
+
requireContract(mapping, "version", FLOW_QUERY_RESULT_CONTRACT, "FLOW.QUERY result");
|
|
12049
|
+
const quality = decodeQuality(field(mapping, "quality"));
|
|
12050
|
+
const usage = decodeUsage(field(mapping, "usage"));
|
|
12051
|
+
const hasRecords = hasKey(mapping, "records");
|
|
12052
|
+
const hasCount = hasKey(mapping, "result");
|
|
12053
|
+
if (hasRecords === hasCount) {
|
|
12054
|
+
throw decodeError("FLOW.QUERY result must contain exactly one records or count shape", value);
|
|
12055
|
+
}
|
|
12056
|
+
const raw = freezeMap(mapping);
|
|
12057
|
+
if (hasRecords) {
|
|
12058
|
+
const rawRecords = field(mapping, "records");
|
|
12059
|
+
if (!Array.isArray(rawRecords) || rawRecords.length > 100) {
|
|
12060
|
+
throw decodeError("FLOW.QUERY records must be an array of at most 100 maps", value);
|
|
12061
|
+
}
|
|
12062
|
+
const records = new Array(rawRecords.length);
|
|
12063
|
+
for (let index = 0; index < rawRecords.length; index += 1) {
|
|
12064
|
+
if (!Object.hasOwn(rawRecords, index)) {
|
|
12065
|
+
throw decodeError("FLOW.QUERY records must be a dense array", value);
|
|
12066
|
+
}
|
|
12067
|
+
records[index] = decodeRecord(
|
|
12068
|
+
requiredMap2(rawRecords[index], `FLOW.QUERY record ${index}`),
|
|
12069
|
+
index
|
|
12070
|
+
);
|
|
12071
|
+
}
|
|
12072
|
+
if (usage.resultRecords !== records.length) {
|
|
12073
|
+
throw decodeError("FLOW.QUERY usage result_records does not match records", value);
|
|
12074
|
+
}
|
|
12075
|
+
return {
|
|
12076
|
+
kind: "records",
|
|
12077
|
+
records,
|
|
12078
|
+
page: decodePage(field(mapping, "page")),
|
|
12079
|
+
quality,
|
|
12080
|
+
usage,
|
|
12081
|
+
raw
|
|
12082
|
+
};
|
|
12083
|
+
}
|
|
12084
|
+
if (hasKey(mapping, "page")) {
|
|
12085
|
+
throw decodeError("FLOW.QUERY count result contains an unexpected page", value);
|
|
12086
|
+
}
|
|
12087
|
+
const countResult = requiredMap2(field(mapping, "result"), "FLOW.QUERY count result");
|
|
12088
|
+
if (requiredText2(countResult, "kind", "FLOW.QUERY count result") !== "count") {
|
|
12089
|
+
throw decodeError("FLOW.QUERY count result kind must be count", value);
|
|
12090
|
+
}
|
|
12091
|
+
const count = boundedInteger(
|
|
12092
|
+
field(countResult, "value"),
|
|
12093
|
+
MAX_SIGNED_64,
|
|
12094
|
+
"FLOW.QUERY count value"
|
|
12095
|
+
);
|
|
12096
|
+
if (usage.resultRecords !== 1) {
|
|
12097
|
+
throw decodeError("FLOW.QUERY count usage result_records must be 1", value);
|
|
12098
|
+
}
|
|
12099
|
+
return {
|
|
12100
|
+
kind: "count",
|
|
12101
|
+
count,
|
|
12102
|
+
quality,
|
|
12103
|
+
usage,
|
|
12104
|
+
raw
|
|
12105
|
+
};
|
|
12106
|
+
}
|
|
12107
|
+
function decodeFlowExplainResult(value) {
|
|
12108
|
+
const mapping = requiredMap2(value, "FLOW.QUERY explain");
|
|
12109
|
+
requireContract(mapping, "version", FLOW_EXPLAIN_CONTRACT, "FLOW.QUERY explain");
|
|
12110
|
+
const queryFingerprint = requiredText2(mapping, "query_fingerprint", "FLOW.QUERY explain");
|
|
12111
|
+
if (!/^[0-9a-f]{64}$/iu.test(queryFingerprint)) {
|
|
12112
|
+
throw decodeError("FLOW.QUERY explain query_fingerprint is invalid", value);
|
|
12113
|
+
}
|
|
12114
|
+
const status = requiredText2(mapping, "status", "FLOW.QUERY explain");
|
|
12115
|
+
if (status !== "planned" && status !== "rejected" && status !== "executed") {
|
|
12116
|
+
throw decodeError(`FLOW.QUERY explain status ${JSON.stringify(status)} is unsupported`, value);
|
|
12117
|
+
}
|
|
12118
|
+
const plan = freezeMetadataMap(
|
|
12119
|
+
requiredMap2(field(mapping, "plan"), "FLOW.QUERY explain plan"),
|
|
12120
|
+
"FLOW.QUERY explain plan"
|
|
12121
|
+
);
|
|
12122
|
+
const estimate = freezeMetadataMap(
|
|
12123
|
+
requiredMap2(field(mapping, "estimate"), "FLOW.QUERY explain estimate"),
|
|
12124
|
+
"FLOW.QUERY explain estimate"
|
|
12125
|
+
);
|
|
12126
|
+
const bounds = freezeMetadataMap(
|
|
12127
|
+
requiredMap2(field(mapping, "bounds"), "FLOW.QUERY explain bounds"),
|
|
12128
|
+
"FLOW.QUERY explain bounds"
|
|
12129
|
+
);
|
|
12130
|
+
const actualValue = field(mapping, "actual");
|
|
12131
|
+
let actual;
|
|
12132
|
+
if (status === "executed") {
|
|
12133
|
+
if (actualValue == null) {
|
|
12134
|
+
throw decodeError("FLOW.QUERY executed explain is missing actual usage", value);
|
|
12135
|
+
}
|
|
12136
|
+
actual = decodeUsage(actualValue);
|
|
12137
|
+
} else if (actualValue != null) {
|
|
12138
|
+
throw decodeError("FLOW.QUERY non-executed explain contains actual usage", value);
|
|
12139
|
+
}
|
|
12140
|
+
const diagnosticValue = field(mapping, "diagnostic");
|
|
12141
|
+
let diagnostic;
|
|
12142
|
+
if (status === "rejected") {
|
|
12143
|
+
diagnostic = tryDecodeFlowQueryError(diagnosticValue);
|
|
12144
|
+
if (diagnostic == null) {
|
|
12145
|
+
throw decodeError("FLOW.QUERY rejected explain has an invalid diagnostic", value);
|
|
12146
|
+
}
|
|
12147
|
+
} else if (diagnosticValue != null) {
|
|
12148
|
+
throw decodeError("FLOW.QUERY non-rejected explain contains a diagnostic", value);
|
|
12149
|
+
}
|
|
12150
|
+
return Object.freeze({
|
|
12151
|
+
version: FLOW_EXPLAIN_CONTRACT,
|
|
12152
|
+
queryFingerprint,
|
|
12153
|
+
status,
|
|
12154
|
+
plan,
|
|
12155
|
+
estimate,
|
|
12156
|
+
bounds,
|
|
12157
|
+
actual,
|
|
12158
|
+
diagnostic,
|
|
12159
|
+
raw: freezeMap(mapping)
|
|
12160
|
+
});
|
|
12161
|
+
}
|
|
12162
|
+
function tryDecodeFlowQueryError(value, cause) {
|
|
12163
|
+
try {
|
|
12164
|
+
const mapping = requiredMap2(value, "FLOW.QUERY diagnostic");
|
|
12165
|
+
const contextValue = field(mapping, "context");
|
|
12166
|
+
const context = contextValue == null ? void 0 : freezeMetadataMap(
|
|
12167
|
+
requiredMap2(contextValue, "FLOW.QUERY diagnostic context"),
|
|
12168
|
+
"FLOW.QUERY diagnostic context"
|
|
12169
|
+
);
|
|
12170
|
+
const position = decodePosition(field(mapping, "position"));
|
|
12171
|
+
return new FlowQueryError({
|
|
12172
|
+
code: requiredText2(mapping, "code", "FLOW.QUERY diagnostic"),
|
|
12173
|
+
message: requiredText2(mapping, "message", "FLOW.QUERY diagnostic"),
|
|
12174
|
+
detail: optionalText2(mapping, "detail", "FLOW.QUERY diagnostic"),
|
|
12175
|
+
hint: optionalText2(mapping, "hint", "FLOW.QUERY diagnostic"),
|
|
12176
|
+
retryable: requiredBoolean(mapping, "retryable", "FLOW.QUERY diagnostic"),
|
|
12177
|
+
safeToRetry: requiredBoolean(mapping, "safe_to_retry", "FLOW.QUERY diagnostic"),
|
|
12178
|
+
retryAfterMs: nonNegativeInteger(
|
|
12179
|
+
field(mapping, "retry_after_ms"),
|
|
12180
|
+
"FLOW.QUERY diagnostic retry_after_ms"
|
|
12181
|
+
),
|
|
12182
|
+
position,
|
|
12183
|
+
context,
|
|
12184
|
+
raw: value,
|
|
12185
|
+
cause
|
|
12186
|
+
});
|
|
12187
|
+
} catch (error) {
|
|
12188
|
+
if (error instanceof FerricStoreError) return void 0;
|
|
12189
|
+
throw error;
|
|
12190
|
+
}
|
|
12191
|
+
}
|
|
12192
|
+
function decodeFlowQueryIndexStatus(value) {
|
|
12193
|
+
const mapping = requiredMap2(value, "FLOW.QUERY.INDEXES");
|
|
12194
|
+
requireContract(
|
|
12195
|
+
mapping,
|
|
12196
|
+
"contract_version",
|
|
12197
|
+
FLOW_QUERY_INDEXES_CONTRACT,
|
|
12198
|
+
"FLOW.QUERY.INDEXES"
|
|
12199
|
+
);
|
|
12200
|
+
const registry = requiredMap2(field(mapping, "registry"), "FLOW.QUERY.INDEXES registry");
|
|
12201
|
+
const services = freezeMetadataMap(
|
|
12202
|
+
requiredMap2(field(mapping, "services"), "FLOW.QUERY.INDEXES services"),
|
|
12203
|
+
"FLOW.QUERY.INDEXES services"
|
|
12204
|
+
);
|
|
12205
|
+
const rawIndexes = field(mapping, "indexes");
|
|
12206
|
+
if (!Array.isArray(rawIndexes) || rawIndexes.length > 32) {
|
|
12207
|
+
throw decodeError("FLOW.QUERY.INDEXES indexes must contain at most 32 entries", value);
|
|
12208
|
+
}
|
|
12209
|
+
const indexes = new Array(rawIndexes.length);
|
|
12210
|
+
for (let index = 0; index < rawIndexes.length; index += 1) {
|
|
12211
|
+
if (!Object.hasOwn(rawIndexes, index)) {
|
|
12212
|
+
throw decodeError("FLOW.QUERY.INDEXES indexes must be a dense array", value);
|
|
12213
|
+
}
|
|
12214
|
+
indexes[index] = decodeIndex(rawIndexes[index], index);
|
|
12215
|
+
}
|
|
12216
|
+
return Object.freeze({
|
|
12217
|
+
contractVersion: FLOW_QUERY_INDEXES_CONTRACT,
|
|
12218
|
+
observedAtMs: nonNegativeInteger(
|
|
12219
|
+
field(mapping, "observed_at_ms"),
|
|
12220
|
+
"FLOW.QUERY.INDEXES observed_at_ms"
|
|
12221
|
+
),
|
|
12222
|
+
statisticsMaxAgeMs: nonNegativeInteger(
|
|
12223
|
+
field(mapping, "statistics_max_age_ms"),
|
|
12224
|
+
"FLOW.QUERY.INDEXES statistics_max_age_ms"
|
|
12225
|
+
),
|
|
12226
|
+
registry: Object.freeze({
|
|
12227
|
+
epoch: boundedInteger(
|
|
12228
|
+
field(registry, "epoch"),
|
|
12229
|
+
MAX_UNSIGNED_64,
|
|
12230
|
+
"FLOW.QUERY.INDEXES epoch"
|
|
12231
|
+
),
|
|
12232
|
+
catalogVersion: positiveBoundedInteger(
|
|
12233
|
+
field(registry, "catalog_version"),
|
|
12234
|
+
MAX_UNSIGNED_64,
|
|
12235
|
+
"FLOW.QUERY.INDEXES catalog_version"
|
|
12236
|
+
)
|
|
12237
|
+
}),
|
|
12238
|
+
services,
|
|
12239
|
+
indexes: Object.freeze(indexes),
|
|
12240
|
+
raw: freezeMap(mapping)
|
|
12241
|
+
});
|
|
12242
|
+
}
|
|
12243
|
+
function decodeIndex(value, index) {
|
|
12244
|
+
const mapping = requiredMap2(value, `FLOW.QUERY.INDEXES index ${index}`);
|
|
12245
|
+
return Object.freeze({
|
|
12246
|
+
id: requiredText2(mapping, "id", "FLOW.QUERY.INDEXES index"),
|
|
12247
|
+
version: positiveBoundedInteger(
|
|
12248
|
+
field(mapping, "version"),
|
|
12249
|
+
MAX_UNSIGNED_64,
|
|
12250
|
+
"FLOW.QUERY.INDEXES index version"
|
|
12251
|
+
),
|
|
12252
|
+
buildId: requiredText2(mapping, "build_id", "FLOW.QUERY.INDEXES index"),
|
|
12253
|
+
state: requiredText2(mapping, "state", "FLOW.QUERY.INDEXES index"),
|
|
12254
|
+
queryable: requiredBoolean(mapping, "queryable", "FLOW.QUERY.INDEXES index"),
|
|
12255
|
+
coveringFields: decodeCoveringFields(mapping),
|
|
12256
|
+
format: decodeIndexFormat(mapping),
|
|
12257
|
+
raw: freezeMap(mapping)
|
|
12258
|
+
});
|
|
12259
|
+
}
|
|
12260
|
+
function decodeCoveringFields(mapping) {
|
|
12261
|
+
const raw = field(mapping, "covering_fields");
|
|
12262
|
+
if (!Array.isArray(raw) || raw.length > 32) {
|
|
12263
|
+
throw decodeError(
|
|
12264
|
+
"FLOW.QUERY.INDEXES index covering_fields must contain at most 32 entries",
|
|
12265
|
+
raw
|
|
12266
|
+
);
|
|
12267
|
+
}
|
|
12268
|
+
const fields = new Array(raw.length);
|
|
12269
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12270
|
+
for (let index = 0; index < raw.length; index += 1) {
|
|
12271
|
+
if (!Object.hasOwn(raw, index)) {
|
|
12272
|
+
throw decodeError("FLOW.QUERY.INDEXES index covering_fields must be dense", raw);
|
|
12273
|
+
}
|
|
12274
|
+
const value = boundedText(
|
|
12275
|
+
raw[index],
|
|
12276
|
+
`FLOW.QUERY.INDEXES index covering_fields entry ${index}`,
|
|
12277
|
+
512
|
|
12278
|
+
);
|
|
12279
|
+
if (seen.has(value)) {
|
|
12280
|
+
throw decodeError("FLOW.QUERY.INDEXES index covering_fields contains duplicates", raw);
|
|
12281
|
+
}
|
|
12282
|
+
seen.add(value);
|
|
12283
|
+
fields[index] = value;
|
|
12284
|
+
}
|
|
12285
|
+
return Object.freeze(fields);
|
|
12286
|
+
}
|
|
12287
|
+
function decodeIndexFormat(mapping) {
|
|
12288
|
+
const raw = requiredMap2(field(mapping, "format"), "FLOW.QUERY.INDEXES index format");
|
|
12289
|
+
if (!hasKey(raw, "counter")) {
|
|
12290
|
+
throw decodeError("FLOW.QUERY.INDEXES index format counter is missing", raw);
|
|
12291
|
+
}
|
|
12292
|
+
const counterValue = field(raw, "counter");
|
|
12293
|
+
const counter = counterValue === null ? void 0 : boundedText(counterValue, "FLOW.QUERY.INDEXES index format counter", 128);
|
|
12294
|
+
return Object.freeze({
|
|
12295
|
+
queryRow: requiredBoundedText2(raw, "query_row", "FLOW.QUERY.INDEXES index format", 128),
|
|
12296
|
+
key: requiredBoundedText2(raw, "key", "FLOW.QUERY.INDEXES index format", 128),
|
|
12297
|
+
entry: requiredBoundedText2(raw, "entry", "FLOW.QUERY.INDEXES index format", 128),
|
|
12298
|
+
reverse: requiredBoundedText2(raw, "reverse", "FLOW.QUERY.INDEXES index format", 128),
|
|
12299
|
+
counter,
|
|
12300
|
+
raw: freezeMap(raw)
|
|
12301
|
+
});
|
|
12302
|
+
}
|
|
12303
|
+
function decodeQuality(value) {
|
|
12304
|
+
const mapping = requiredMap2(value, "FLOW.QUERY quality");
|
|
12305
|
+
return Object.freeze({
|
|
12306
|
+
exactness: requiredBoundedText2(mapping, "exactness", "FLOW.QUERY quality", 64),
|
|
12307
|
+
freshness: requiredBoundedText2(mapping, "freshness", "FLOW.QUERY quality", 64),
|
|
12308
|
+
coverage: requiredBoundedText2(mapping, "coverage", "FLOW.QUERY quality", 64),
|
|
12309
|
+
pagination: requiredBoundedText2(mapping, "pagination", "FLOW.QUERY quality", 64)
|
|
12310
|
+
});
|
|
12311
|
+
}
|
|
12312
|
+
function decodeUsage(value) {
|
|
12313
|
+
const mapping = requiredMap2(value, "FLOW.QUERY usage");
|
|
12314
|
+
const usage = /* @__PURE__ */ Object.create(null);
|
|
12315
|
+
for (const [wireName, property] of USAGE_FIELDS2) {
|
|
12316
|
+
usage[property] = nonNegativeInteger(
|
|
12317
|
+
field(mapping, wireName),
|
|
12318
|
+
`FLOW.QUERY usage ${wireName}`
|
|
12319
|
+
);
|
|
12320
|
+
}
|
|
12321
|
+
return Object.freeze(usage);
|
|
12322
|
+
}
|
|
12323
|
+
function decodePage(value) {
|
|
12324
|
+
const mapping = requiredMap2(value, "FLOW.QUERY page");
|
|
12325
|
+
const hasMore = requiredBoolean(mapping, "has_more", "FLOW.QUERY page");
|
|
12326
|
+
const cursor = optionalText2(mapping, "cursor", "FLOW.QUERY page");
|
|
12327
|
+
if (cursor != null && (!cursor.startsWith("fqc1_") || Buffer45.byteLength(cursor) > 4096)) {
|
|
12328
|
+
throw decodeError("FLOW.QUERY page cursor is invalid", value);
|
|
12329
|
+
}
|
|
12330
|
+
if (hasMore !== (cursor != null)) {
|
|
12331
|
+
throw decodeError("FLOW.QUERY page has_more and cursor are inconsistent", value);
|
|
12332
|
+
}
|
|
12333
|
+
return Object.freeze({ hasMore, ...cursor == null ? {} : { cursor } });
|
|
12334
|
+
}
|
|
12335
|
+
function decodePosition(value) {
|
|
12336
|
+
if (value == null) return void 0;
|
|
12337
|
+
const mapping = requiredMap2(value, "FLOW.QUERY diagnostic position");
|
|
12338
|
+
return Object.freeze({
|
|
12339
|
+
byte: positiveInteger(field(mapping, "byte"), "FLOW.QUERY diagnostic position byte"),
|
|
12340
|
+
line: positiveInteger(field(mapping, "line"), "FLOW.QUERY diagnostic position line"),
|
|
12341
|
+
column: positiveInteger(
|
|
12342
|
+
field(mapping, "column"),
|
|
12343
|
+
"FLOW.QUERY diagnostic position column"
|
|
12344
|
+
)
|
|
12345
|
+
});
|
|
12346
|
+
}
|
|
12347
|
+
|
|
12348
|
+
// src/client-core.ts
|
|
12349
|
+
import "buffer";
|
|
12350
|
+
|
|
12351
|
+
// src/client-core-helpers.ts
|
|
12352
|
+
import { Buffer as Buffer46 } from "buffer";
|
|
12353
|
+
function bgsaveResponse(response) {
|
|
12354
|
+
if ((typeof response === "string" || Buffer46.isBuffer(response) || response instanceof Uint8Array) && text(response) === "Background saving started") {
|
|
12355
|
+
return true;
|
|
12356
|
+
}
|
|
12357
|
+
return okResponse(response);
|
|
12358
|
+
}
|
|
12359
|
+
function clientNameResponse(response) {
|
|
12360
|
+
return response == null ? null : textResponse(response, "CLIENT GETNAME");
|
|
12361
|
+
}
|
|
12362
|
+
function fetchOrComputeCompletionToken(options) {
|
|
12363
|
+
if (options == null || !Object.hasOwn(options, "computeToken") || options.computeToken === void 0) {
|
|
12364
|
+
throw new TypeError(
|
|
12365
|
+
"fetch-or-compute completion requires computeToken"
|
|
12366
|
+
);
|
|
12367
|
+
}
|
|
12368
|
+
if (!Buffer46.isBuffer(options.computeToken)) {
|
|
12369
|
+
throw new TypeError("fetch-or-compute computeToken must be a Buffer");
|
|
12370
|
+
}
|
|
12371
|
+
return options.computeToken;
|
|
12372
|
+
}
|
|
12373
|
+
function concatCommandArgs(prefix, suffix) {
|
|
12374
|
+
const args = new Array(prefix.length + suffix.length);
|
|
12375
|
+
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
12376
|
+
for (let index = 0; index < suffix.length; index += 1) {
|
|
12377
|
+
args[prefix.length + index] = suffix[index];
|
|
12378
|
+
}
|
|
12379
|
+
return args;
|
|
12380
|
+
}
|
|
12381
|
+
function unsupportedClientTracking() {
|
|
12382
|
+
throw new InvalidCommandError(
|
|
12383
|
+
"CLIENT TRACKING is not supported by the FerricStore native protocol; use native event subscriptions"
|
|
12384
|
+
);
|
|
12385
|
+
}
|
|
12386
|
+
function unsupportedClientCaching() {
|
|
12387
|
+
throw new InvalidCommandError("CLIENT CACHING is not supported by the FerricStore native protocol");
|
|
12388
|
+
}
|
|
12389
|
+
|
|
12390
|
+
// src/client-base.ts
|
|
12391
|
+
import "buffer";
|
|
12392
|
+
|
|
12393
|
+
// src/client-executor.ts
|
|
12394
|
+
import "buffer";
|
|
12395
|
+
var ErrorMappingExecutor = class {
|
|
12396
|
+
constructor(executor) {
|
|
12397
|
+
this.executor = executor;
|
|
12398
|
+
}
|
|
12399
|
+
executor;
|
|
12400
|
+
async executeCommand(...args) {
|
|
12401
|
+
return await this.executeCommandArgs(args);
|
|
12402
|
+
}
|
|
12403
|
+
async executeCommandArgs(args) {
|
|
12404
|
+
try {
|
|
12405
|
+
return await executeCommandArgs(this.executor, args);
|
|
12406
|
+
} catch (error) {
|
|
12407
|
+
throwMapped(error);
|
|
12408
|
+
}
|
|
12409
|
+
}
|
|
12410
|
+
async executePipeline(commands, options) {
|
|
12411
|
+
let results;
|
|
10707
12412
|
try {
|
|
10708
12413
|
if (this.executor.executePipeline != null) {
|
|
10709
12414
|
results = await this.executor.executePipeline(commands, options);
|
|
@@ -11020,14 +12725,14 @@ var FerricStoreAdministrationClient = class extends FerricStoreClientBase {
|
|
|
11020
12725
|
};
|
|
11021
12726
|
|
|
11022
12727
|
// src/store-utilities.ts
|
|
11023
|
-
import { Buffer as
|
|
12728
|
+
import { Buffer as Buffer49 } from "buffer";
|
|
11024
12729
|
function encode(codec, value) {
|
|
11025
12730
|
return codec.encode(value);
|
|
11026
12731
|
}
|
|
11027
12732
|
function decode(codec, value) {
|
|
11028
12733
|
if (value == null) return null;
|
|
11029
|
-
if (
|
|
11030
|
-
if (value instanceof Uint8Array) return codec.decode(
|
|
12734
|
+
if (Buffer49.isBuffer(value)) return codec.decode(value);
|
|
12735
|
+
if (value instanceof Uint8Array) return codec.decode(Buffer49.from(value));
|
|
11031
12736
|
return value;
|
|
11032
12737
|
}
|
|
11033
12738
|
function number(value) {
|
|
@@ -11088,7 +12793,7 @@ function requireNonEmpty(values, command, noun = "argument") {
|
|
|
11088
12793
|
if (values.length === 0) throw new TypeError(`${command} requires at least one ${noun}`);
|
|
11089
12794
|
return values;
|
|
11090
12795
|
}
|
|
11091
|
-
function
|
|
12796
|
+
function commandName4(args) {
|
|
11092
12797
|
return typeof args[0] === "string" ? args[0] : "command";
|
|
11093
12798
|
}
|
|
11094
12799
|
function commandArgs(client, args) {
|
|
@@ -11103,7 +12808,7 @@ function arrayOrRest(values) {
|
|
|
11103
12808
|
function appendXReadStreams(args, streams) {
|
|
11104
12809
|
const offset = args.length;
|
|
11105
12810
|
const streamCount = streams.length;
|
|
11106
|
-
requireNonEmpty(streams,
|
|
12811
|
+
requireNonEmpty(streams, commandName4(args), "stream");
|
|
11107
12812
|
args.length = offset + 1 + streamCount * 2;
|
|
11108
12813
|
args[offset] = "STREAMS";
|
|
11109
12814
|
for (let index = 0; index < streamCount; index += 1) {
|
|
@@ -11113,7 +12818,7 @@ function appendXReadStreams(args, streams) {
|
|
|
11113
12818
|
const stream = streams[index];
|
|
11114
12819
|
if (stream == null) throw new TypeError("XREAD streams must contain only stream descriptors");
|
|
11115
12820
|
if (!Object.hasOwn(stream, "key") || !Object.hasOwn(stream, "id")) {
|
|
11116
|
-
throw new TypeError(`${
|
|
12821
|
+
throw new TypeError(`${commandName4(args)} streams require own key and id fields`);
|
|
11117
12822
|
}
|
|
11118
12823
|
args[offset + 1 + index] = stream.key;
|
|
11119
12824
|
args[offset + 1 + streamCount + index] = stream.id;
|
|
@@ -11135,7 +12840,7 @@ function concatArgs(...parts) {
|
|
|
11135
12840
|
return args;
|
|
11136
12841
|
}
|
|
11137
12842
|
function encodedArgs(prefix, codec, values, allowEmpty = false) {
|
|
11138
|
-
if (!allowEmpty) requireNonEmpty(values,
|
|
12843
|
+
if (!allowEmpty) requireNonEmpty(values, commandName4(prefix));
|
|
11139
12844
|
const args = new Array(prefix.length + values.length);
|
|
11140
12845
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
11141
12846
|
for (let index = 0; index < values.length; index += 1) {
|
|
@@ -11149,7 +12854,7 @@ function encodedArgs(prefix, codec, values, allowEmpty = false) {
|
|
|
11149
12854
|
function keyValueArgs(prefix, codec, entries) {
|
|
11150
12855
|
const validateTuples = Array.isArray(entries);
|
|
11151
12856
|
const pairs = validateTuples ? entries : Object.entries(entries);
|
|
11152
|
-
requireNonEmpty(pairs,
|
|
12857
|
+
requireNonEmpty(pairs, commandName4(prefix), "entry");
|
|
11153
12858
|
const args = new Array(prefix.length + pairs.length * 2);
|
|
11154
12859
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
11155
12860
|
for (let index = 0; index < pairs.length; index += 1) {
|
|
@@ -11163,7 +12868,7 @@ function keyValueArgs(prefix, codec, entries) {
|
|
|
11163
12868
|
return args;
|
|
11164
12869
|
}
|
|
11165
12870
|
function encodedEntryArgs(prefix, codec, entries) {
|
|
11166
|
-
requireNonEmpty(entries,
|
|
12871
|
+
requireNonEmpty(entries, commandName4(prefix), "entry");
|
|
11167
12872
|
const args = new Array(prefix.length + entries.length * 2);
|
|
11168
12873
|
for (let index = 0; index < prefix.length; index += 1) args[index] = prefix[index];
|
|
11169
12874
|
for (let index = 0; index < entries.length; index += 1) {
|
|
@@ -11617,15 +13322,15 @@ function compressionOptions(options) {
|
|
|
11617
13322
|
// src/store-decoders.ts
|
|
11618
13323
|
function decodeHashRecord(codec, value) {
|
|
11619
13324
|
const result = {};
|
|
11620
|
-
for (const [
|
|
11621
|
-
setOwnValue(result, textToken(
|
|
13325
|
+
for (const [field3, item] of hashPairs(value)) {
|
|
13326
|
+
setOwnValue(result, textToken(field3), decode(codec, item));
|
|
11622
13327
|
}
|
|
11623
13328
|
return result;
|
|
11624
13329
|
}
|
|
11625
13330
|
function decodeHashFlatPairs(codec, value) {
|
|
11626
13331
|
const result = [];
|
|
11627
|
-
for (const [
|
|
11628
|
-
result.push(textToken(
|
|
13332
|
+
for (const [field3, item] of hashPairs(value)) {
|
|
13333
|
+
result.push(textToken(field3), decode(codec, item));
|
|
11629
13334
|
}
|
|
11630
13335
|
return result;
|
|
11631
13336
|
}
|
|
@@ -11745,7 +13450,7 @@ function requiredPair(value, message) {
|
|
|
11745
13450
|
}
|
|
11746
13451
|
function decodeStreamFieldValues(codec, value) {
|
|
11747
13452
|
const result = [];
|
|
11748
|
-
for (const [
|
|
13453
|
+
for (const [field3, item] of hashPairs(value)) result.push(textToken(field3), decode(codec, item));
|
|
11749
13454
|
return result;
|
|
11750
13455
|
}
|
|
11751
13456
|
var geoSearchMetadataTokens = /* @__PURE__ */ new Set(["WITHCOORD", "WITHDIST", "WITHHASH"]);
|
|
@@ -12559,8 +14264,8 @@ var HashStore = class {
|
|
|
12559
14264
|
async hset(key, entries) {
|
|
12560
14265
|
return number(await commandArgs(this.client, keyValueArgs(["HSET", key], this.client.codec, entries)));
|
|
12561
14266
|
}
|
|
12562
|
-
async hget(key,
|
|
12563
|
-
return decode(this.client.codec, await this.client.command("HGET", key,
|
|
14267
|
+
async hget(key, field3) {
|
|
14268
|
+
return decode(this.client.codec, await this.client.command("HGET", key, field3));
|
|
12564
14269
|
}
|
|
12565
14270
|
async hdel(key, ...fieldsOrArray) {
|
|
12566
14271
|
const fields = requireNonEmpty(arrayOrRest(fieldsOrArray), "HDEL", "field");
|
|
@@ -12579,8 +14284,8 @@ var HashStore = class {
|
|
|
12579
14284
|
async hgetall(key) {
|
|
12580
14285
|
return decodeHashRecord(this.client.codec, await this.client.command("HGETALL", key));
|
|
12581
14286
|
}
|
|
12582
|
-
async hexists(key,
|
|
12583
|
-
return binaryBooleanResponse(await this.client.command("HEXISTS", key,
|
|
14287
|
+
async hexists(key, field3) {
|
|
14288
|
+
return binaryBooleanResponse(await this.client.command("HEXISTS", key, field3));
|
|
12584
14289
|
}
|
|
12585
14290
|
async hkeys(key) {
|
|
12586
14291
|
return mapArray(await this.client.command("HKEYS", key), "HKEYS", textToken);
|
|
@@ -12595,17 +14300,17 @@ var HashStore = class {
|
|
|
12595
14300
|
async hlen(key) {
|
|
12596
14301
|
return number(await this.client.command("HLEN", key));
|
|
12597
14302
|
}
|
|
12598
|
-
async hincrby(key,
|
|
12599
|
-
return integerReply(await this.client.command("HINCRBY", key,
|
|
14303
|
+
async hincrby(key, field3, increment) {
|
|
14304
|
+
return integerReply(await this.client.command("HINCRBY", key, field3, increment));
|
|
12600
14305
|
}
|
|
12601
|
-
async hincrbyfloat(key,
|
|
12602
|
-
return string(await this.client.command("HINCRBYFLOAT", key,
|
|
14306
|
+
async hincrbyfloat(key, field3, increment) {
|
|
14307
|
+
return string(await this.client.command("HINCRBYFLOAT", key, field3, increment));
|
|
12603
14308
|
}
|
|
12604
|
-
async hsetnx(key,
|
|
12605
|
-
return binaryBooleanResponse(await this.client.command("HSETNX", key,
|
|
14309
|
+
async hsetnx(key, field3, value) {
|
|
14310
|
+
return binaryBooleanResponse(await this.client.command("HSETNX", key, field3, encode(this.client.codec, value)));
|
|
12606
14311
|
}
|
|
12607
|
-
async hstrlen(key,
|
|
12608
|
-
return number(await this.client.command("HSTRLEN", key,
|
|
14312
|
+
async hstrlen(key, field3) {
|
|
14313
|
+
return number(await this.client.command("HSTRLEN", key, field3));
|
|
12609
14314
|
}
|
|
12610
14315
|
async hrandfield(key, count, withValues = false) {
|
|
12611
14316
|
if (withValues && count == null) {
|
|
@@ -13241,6 +14946,100 @@ var FerricStoreManagementClient = class extends FerricStoreClientCore {
|
|
|
13241
14946
|
}
|
|
13242
14947
|
};
|
|
13243
14948
|
|
|
14949
|
+
// src/client-flow-query.ts
|
|
14950
|
+
var FerricStoreFlowQueryClient = class extends FerricStoreManagementClient {
|
|
14951
|
+
async query(query, params = {}) {
|
|
14952
|
+
if (hasFlowExplainPrefix(query)) {
|
|
14953
|
+
throw new TypeError("query does not accept EXPLAIN; use explain or explainAnalyze");
|
|
14954
|
+
}
|
|
14955
|
+
return decodeFlowQueryResult(await this.executeFlowQuery(query, params));
|
|
14956
|
+
}
|
|
14957
|
+
async explain(query, params = {}) {
|
|
14958
|
+
return await this.executeExplain("EXPLAIN ", query, params);
|
|
14959
|
+
}
|
|
14960
|
+
async explainAnalyze(query, params = {}) {
|
|
14961
|
+
return await this.executeExplain("EXPLAIN ANALYZE ", query, params);
|
|
14962
|
+
}
|
|
14963
|
+
async queryIndexes(indexId) {
|
|
14964
|
+
const args = ["FLOW.QUERY.INDEXES"];
|
|
14965
|
+
if (indexId != null) {
|
|
14966
|
+
validateFlowQueryIndexId(indexId);
|
|
14967
|
+
args.push(indexId);
|
|
14968
|
+
}
|
|
14969
|
+
try {
|
|
14970
|
+
return decodeFlowQueryIndexStatus(await this.commandArgs(args));
|
|
14971
|
+
} catch (error) {
|
|
14972
|
+
this.throwFlowQueryError(error);
|
|
14973
|
+
}
|
|
14974
|
+
}
|
|
14975
|
+
async list(type, options) {
|
|
14976
|
+
return await this.executeFlowRecordQuery(buildFlowListQuery(type, options));
|
|
14977
|
+
}
|
|
14978
|
+
async search(type, options) {
|
|
14979
|
+
return await this.executeFlowRecordQuery(buildFlowSearchQuery(type, options));
|
|
14980
|
+
}
|
|
14981
|
+
async terminals(type, options) {
|
|
14982
|
+
return await this.executeFlowRecordQuery(buildFlowTerminalQuery(type, options));
|
|
14983
|
+
}
|
|
14984
|
+
async failures(type, options) {
|
|
14985
|
+
return await this.executeFlowRecordQuery(buildFlowFailureQuery(type, options));
|
|
14986
|
+
}
|
|
14987
|
+
async byParent(parentFlowId, options) {
|
|
14988
|
+
return await this.executeFlowRecordQuery(
|
|
14989
|
+
buildFlowLineageQuery("parent_flow_id", parentFlowId, options)
|
|
14990
|
+
);
|
|
14991
|
+
}
|
|
14992
|
+
async byRoot(rootFlowId, options) {
|
|
14993
|
+
return await this.executeFlowRecordQuery(
|
|
14994
|
+
buildFlowLineageQuery("root_flow_id", rootFlowId, options)
|
|
14995
|
+
);
|
|
14996
|
+
}
|
|
14997
|
+
async byCorrelation(correlationId, options) {
|
|
14998
|
+
return await this.executeFlowRecordQuery(
|
|
14999
|
+
buildFlowLineageQuery("correlation_id", correlationId, options)
|
|
15000
|
+
);
|
|
15001
|
+
}
|
|
15002
|
+
async stuck(type, options) {
|
|
15003
|
+
return await this.executeFlowRecordQuery(buildFlowStuckQuery(type, options));
|
|
15004
|
+
}
|
|
15005
|
+
records(values) {
|
|
15006
|
+
const records = new Array(values.length);
|
|
15007
|
+
for (let index = 0; index < values.length; index += 1) {
|
|
15008
|
+
if (!Object.hasOwn(values, index)) {
|
|
15009
|
+
throw new TypeError(`Flow record response item ${index} is missing`);
|
|
15010
|
+
}
|
|
15011
|
+
records[index] = flowRecordFromResp(values[index], this.codec);
|
|
15012
|
+
}
|
|
15013
|
+
return records;
|
|
15014
|
+
}
|
|
15015
|
+
async executeFlowQuery(query, params) {
|
|
15016
|
+
const args = flowQueryArgs(query, params);
|
|
15017
|
+
try {
|
|
15018
|
+
return await this.commandArgs(args);
|
|
15019
|
+
} catch (error) {
|
|
15020
|
+
this.throwFlowQueryError(error);
|
|
15021
|
+
}
|
|
15022
|
+
}
|
|
15023
|
+
async executeFlowRecordQuery(request) {
|
|
15024
|
+
const response = await this.executeFlowQuery(request.query, request.params);
|
|
15025
|
+
return decodeFlowQueryRecords(response, (value) => flowRecordFromResp(value, this.codec));
|
|
15026
|
+
}
|
|
15027
|
+
async executeExplain(prefix, query, params) {
|
|
15028
|
+
validateFlowQueryText(query);
|
|
15029
|
+
if (hasFlowExplainPrefix(query)) {
|
|
15030
|
+
throw new TypeError("query already contains an EXPLAIN prefix");
|
|
15031
|
+
}
|
|
15032
|
+
return decodeFlowExplainResult(await this.executeFlowQuery(prefix + query.trim(), params));
|
|
15033
|
+
}
|
|
15034
|
+
throwFlowQueryError(error) {
|
|
15035
|
+
if (error instanceof FerricStoreError) {
|
|
15036
|
+
const diagnostic = tryDecodeFlowQueryError(error.raw, error);
|
|
15037
|
+
if (diagnostic != null) throw diagnostic;
|
|
15038
|
+
}
|
|
15039
|
+
throw error;
|
|
15040
|
+
}
|
|
15041
|
+
};
|
|
15042
|
+
|
|
13244
15043
|
// src/producer-backpressure.ts
|
|
13245
15044
|
async function executeProducerWriteWithBackpressure(execute, policy, signal) {
|
|
13246
15045
|
for (let attempt = 0; ; attempt += 1) {
|
|
@@ -13262,8 +15061,167 @@ function throwIfClosed(signal) {
|
|
|
13262
15061
|
throw new FerricStoreError("FerricStore client is closed", { raw: signal.reason });
|
|
13263
15062
|
}
|
|
13264
15063
|
|
|
15064
|
+
// src/flow-policy.ts
|
|
15065
|
+
import { Buffer as Buffer51 } from "buffer";
|
|
15066
|
+
var MAX_FLOW_POLICY_GENERATION = Number.MAX_SAFE_INTEGER;
|
|
15067
|
+
function assertFlowPolicyGeneration(value) {
|
|
15068
|
+
if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) {
|
|
15069
|
+
throw new TypeError("expectedGeneration must be a nonnegative safe integer");
|
|
15070
|
+
}
|
|
15071
|
+
}
|
|
15072
|
+
function flowPolicySnapshotFromResp(value) {
|
|
15073
|
+
const policy = requiredRecord(value, "FLOW policy snapshot");
|
|
15074
|
+
const maxActiveMs = optionalPositiveInteger(field(policy, "max_active_ms"), "max_active_ms");
|
|
15075
|
+
const state = optionalText3(field(policy, "state"), "state");
|
|
15076
|
+
const mode = optionalMode(field(policy, "mode"), "mode");
|
|
15077
|
+
const version = optionalVersion(field(policy, "version"));
|
|
15078
|
+
const indexedStateMeta = optionalText3(field(policy, "indexed_state_meta"), "indexed_state_meta");
|
|
15079
|
+
const governance = optionalRecord(field(policy, "governance"), "governance");
|
|
15080
|
+
const states = optionalStates(field(policy, "states"));
|
|
15081
|
+
return {
|
|
15082
|
+
type: requiredText3(field(policy, "type"), "type"),
|
|
15083
|
+
generation: nonNegativeInteger2(field(policy, "generation"), "generation"),
|
|
15084
|
+
...state == null ? {} : { state },
|
|
15085
|
+
...version == null ? {} : { version },
|
|
15086
|
+
...mode == null ? {} : { mode },
|
|
15087
|
+
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
15088
|
+
retry: retrySnapshot(field(policy, "retry"), "retry"),
|
|
15089
|
+
retention: retentionSnapshot(field(policy, "retention"), "retention"),
|
|
15090
|
+
indexedAttributes: stringArray(field(policy, "indexed_attributes"), "indexed_attributes"),
|
|
15091
|
+
...indexedStateMeta == null ? {} : { indexedStateMeta },
|
|
15092
|
+
...governance == null ? {} : { governance },
|
|
15093
|
+
...states == null ? {} : { states },
|
|
15094
|
+
raw: value
|
|
15095
|
+
};
|
|
15096
|
+
}
|
|
15097
|
+
function retrySnapshot(value, context) {
|
|
15098
|
+
const retry2 = requiredRecord(value, `FLOW policy ${context}`);
|
|
15099
|
+
const backoff = requiredRecord(field(retry2, "backoff"), `FLOW policy ${context}.backoff`);
|
|
15100
|
+
return {
|
|
15101
|
+
maxRetries: nonNegativeInteger2(field(retry2, "max_retries"), `${context}.max_retries`),
|
|
15102
|
+
backoff: {
|
|
15103
|
+
kind: backoffKind(field(backoff, "kind"), `${context}.backoff.kind`),
|
|
15104
|
+
baseMs: nonNegativeInteger2(field(backoff, "base_ms"), `${context}.backoff.base_ms`),
|
|
15105
|
+
maxMs: nonNegativeInteger2(field(backoff, "max_ms"), `${context}.backoff.max_ms`),
|
|
15106
|
+
jitterPct: nonNegativeInteger2(field(backoff, "jitter_pct"), `${context}.backoff.jitter_pct`)
|
|
15107
|
+
},
|
|
15108
|
+
exhaustedTo: requiredText3(field(retry2, "exhausted_to"), `${context}.exhausted_to`)
|
|
15109
|
+
};
|
|
15110
|
+
}
|
|
15111
|
+
function retentionSnapshot(value, context) {
|
|
15112
|
+
const retention = requiredRecord(value, `FLOW policy ${context}`);
|
|
15113
|
+
return {
|
|
15114
|
+
ttlMs: nonNegativeInteger2(field(retention, "ttl_ms"), `${context}.ttl_ms`),
|
|
15115
|
+
historyMaxEvents: nonNegativeInteger2(
|
|
15116
|
+
field(retention, "history_max_events"),
|
|
15117
|
+
`${context}.history_max_events`
|
|
15118
|
+
)
|
|
15119
|
+
};
|
|
15120
|
+
}
|
|
15121
|
+
function optionalStates(value) {
|
|
15122
|
+
if (value == null) return void 0;
|
|
15123
|
+
const source = requiredRecord(value, "FLOW policy states");
|
|
15124
|
+
const result = {};
|
|
15125
|
+
for (const [state, raw] of Object.entries(source)) {
|
|
15126
|
+
const policy = requiredRecord(raw, `FLOW policy state ${state}`);
|
|
15127
|
+
const maxActiveMs = optionalPositiveInteger(
|
|
15128
|
+
field(policy, "max_active_ms"),
|
|
15129
|
+
`states.${state}.max_active_ms`
|
|
15130
|
+
);
|
|
15131
|
+
const governance = optionalRecord(field(policy, "governance"), `states.${state}.governance`);
|
|
15132
|
+
Object.defineProperty(result, state, {
|
|
15133
|
+
configurable: true,
|
|
15134
|
+
enumerable: true,
|
|
15135
|
+
value: {
|
|
15136
|
+
mode: requiredMode(field(policy, "mode"), `states.${state}.mode`),
|
|
15137
|
+
...maxActiveMs == null ? {} : { maxActiveMs },
|
|
15138
|
+
retry: retrySnapshot(field(policy, "retry"), `states.${state}.retry`),
|
|
15139
|
+
retention: retentionSnapshot(field(policy, "retention"), `states.${state}.retention`),
|
|
15140
|
+
...governance == null ? {} : { governance }
|
|
15141
|
+
},
|
|
15142
|
+
writable: true
|
|
15143
|
+
});
|
|
15144
|
+
}
|
|
15145
|
+
return result;
|
|
15146
|
+
}
|
|
15147
|
+
function requiredRecord(value, context) {
|
|
15148
|
+
if (value instanceof Map) {
|
|
15149
|
+
const result = {};
|
|
15150
|
+
for (const [key, item] of value.entries()) {
|
|
15151
|
+
setOwnValue(result, requiredText3(key, `${context} key`), item);
|
|
15152
|
+
}
|
|
15153
|
+
return result;
|
|
15154
|
+
}
|
|
15155
|
+
if (typeof value === "object" && value != null && !Array.isArray(value) && !Buffer51.isBuffer(value) && !(value instanceof Uint8Array)) return value;
|
|
15156
|
+
throw new TypeError(`${context} returned an unexpected response`);
|
|
15157
|
+
}
|
|
15158
|
+
function optionalRecord(value, context) {
|
|
15159
|
+
return value == null ? void 0 : requiredRecord(value, `FLOW policy ${context}`);
|
|
15160
|
+
}
|
|
15161
|
+
function stringArray(value, context) {
|
|
15162
|
+
if (!Array.isArray(value)) {
|
|
15163
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15164
|
+
}
|
|
15165
|
+
const result = new Array(value.length);
|
|
15166
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
15167
|
+
if (!Object.hasOwn(value, index)) {
|
|
15168
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15169
|
+
}
|
|
15170
|
+
result[index] = requiredText3(value[index], `${context}[${index}]`);
|
|
15171
|
+
}
|
|
15172
|
+
return result;
|
|
15173
|
+
}
|
|
15174
|
+
function requiredText3(value, context) {
|
|
15175
|
+
if (typeof value === "string") return value;
|
|
15176
|
+
if (Buffer51.isBuffer(value) || value instanceof Uint8Array) {
|
|
15177
|
+
return Buffer51.from(value).toString("utf8");
|
|
15178
|
+
}
|
|
15179
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15180
|
+
}
|
|
15181
|
+
function optionalText3(value, context) {
|
|
15182
|
+
return value == null ? void 0 : requiredText3(value, context);
|
|
15183
|
+
}
|
|
15184
|
+
function nonNegativeInteger2(value, context) {
|
|
15185
|
+
let parsed;
|
|
15186
|
+
try {
|
|
15187
|
+
parsed = integer(value);
|
|
15188
|
+
} catch {
|
|
15189
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15190
|
+
}
|
|
15191
|
+
if (parsed < 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15192
|
+
return parsed;
|
|
15193
|
+
}
|
|
15194
|
+
function optionalPositiveInteger(value, context) {
|
|
15195
|
+
if (value == null) return void 0;
|
|
15196
|
+
const parsed = nonNegativeInteger2(value, context);
|
|
15197
|
+
if (parsed === 0) throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15198
|
+
return parsed;
|
|
15199
|
+
}
|
|
15200
|
+
function optionalVersion(value) {
|
|
15201
|
+
if (value == null) return void 0;
|
|
15202
|
+
if (typeof value === "number" || typeof value === "bigint") {
|
|
15203
|
+
return nonNegativeInteger2(value, "version");
|
|
15204
|
+
}
|
|
15205
|
+
return requiredText3(value, "version");
|
|
15206
|
+
}
|
|
15207
|
+
function backoffKind(value, context) {
|
|
15208
|
+
const kind = requiredText3(value, context).toLowerCase();
|
|
15209
|
+
if (kind === "none" || kind === "fixed" || kind === "linear" || kind === "exponential") {
|
|
15210
|
+
return kind;
|
|
15211
|
+
}
|
|
15212
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15213
|
+
}
|
|
15214
|
+
function requiredMode(value, context) {
|
|
15215
|
+
const mode = requiredText3(value, context).toLowerCase();
|
|
15216
|
+
if (mode === "fifo" || mode === "parallel") return mode;
|
|
15217
|
+
throw new TypeError(`FLOW policy ${context} returned an unexpected response`);
|
|
15218
|
+
}
|
|
15219
|
+
function optionalMode(value, context) {
|
|
15220
|
+
return value == null ? void 0 : requiredMode(value, context);
|
|
15221
|
+
}
|
|
15222
|
+
|
|
13265
15223
|
// src/client-flow-support.ts
|
|
13266
|
-
var FerricStoreFlowSupportClient = class extends
|
|
15224
|
+
var FerricStoreFlowSupportClient = class extends FerricStoreFlowQueryClient {
|
|
13267
15225
|
async rewind(id, options = {}) {
|
|
13268
15226
|
const partitionKey = options.partitionKey;
|
|
13269
15227
|
const returnRecord = options.returnRecord === true;
|
|
@@ -13289,43 +15247,9 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13289
15247
|
}
|
|
13290
15248
|
return flowRecordFromResp(response, this.codec);
|
|
13291
15249
|
}
|
|
13292
|
-
async list(type, options = {}) {
|
|
13293
|
-
return await this.indexQuery("FLOW.LIST", type, options);
|
|
13294
|
-
}
|
|
13295
|
-
async search(type, options = {}) {
|
|
13296
|
-
const args = ["FLOW.SEARCH", type];
|
|
13297
|
-
appendReadOptions(args, options);
|
|
13298
|
-
appendAttributes(args, options.attributes);
|
|
13299
|
-
appendSearchStateMeta(args, options.state, options.stateMeta);
|
|
13300
|
-
const response = await this.commandArgs(args);
|
|
13301
|
-
return this.records(requiredArrayResponse(response, "FLOW.SEARCH"));
|
|
13302
|
-
}
|
|
13303
|
-
async terminals(type, options = {}) {
|
|
13304
|
-
return await this.indexQuery("FLOW.TERMINALS", type, options);
|
|
13305
|
-
}
|
|
13306
|
-
async failures(type, options = {}) {
|
|
13307
|
-
return await this.indexQuery("FLOW.FAILURES", type, options);
|
|
13308
|
-
}
|
|
13309
|
-
async byParent(parentFlowId, options = {}) {
|
|
13310
|
-
return await this.indexQuery("FLOW.BY_PARENT", parentFlowId, options);
|
|
13311
|
-
}
|
|
13312
|
-
async byRoot(rootFlowId, options = {}) {
|
|
13313
|
-
return await this.indexQuery("FLOW.BY_ROOT", rootFlowId, options);
|
|
13314
|
-
}
|
|
13315
|
-
async byCorrelation(correlationId, options = {}) {
|
|
13316
|
-
return await this.indexQuery("FLOW.BY_CORRELATION", correlationId, options);
|
|
13317
|
-
}
|
|
13318
15250
|
async info(type) {
|
|
13319
15251
|
return parseKvResponse(await this.command("FLOW.INFO", type));
|
|
13320
15252
|
}
|
|
13321
|
-
async stuck(type, options = {}) {
|
|
13322
|
-
const args = ["FLOW.STUCK", type];
|
|
13323
|
-
append(args, "PARTITION", options.partitionKey);
|
|
13324
|
-
append(args, "COUNT", options.count);
|
|
13325
|
-
append(args, "OLDER_THAN", options.olderThanMs);
|
|
13326
|
-
append(args, "NOW", options.nowMs);
|
|
13327
|
-
return this.records(arrayResponse(await this.commandArgs(args)));
|
|
13328
|
-
}
|
|
13329
15253
|
async history(id, options = {}) {
|
|
13330
15254
|
const args = ["FLOW.HISTORY", id];
|
|
13331
15255
|
append(args, "PARTITION", options.partitionKey);
|
|
@@ -13404,27 +15328,36 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13404
15328
|
}
|
|
13405
15329
|
async installPolicy(type, options = {}) {
|
|
13406
15330
|
const args = ["FLOW.POLICY.SET", type];
|
|
15331
|
+
const expectedGeneration = Object.hasOwn(options, "expectedGeneration") ? options.expectedGeneration : void 0;
|
|
15332
|
+
const replace = Object.hasOwn(options, "replace") ? options.replace : void 0;
|
|
15333
|
+
if (expectedGeneration != null) assertFlowPolicyGeneration(expectedGeneration);
|
|
15334
|
+
if (replace != null && typeof replace !== "boolean") {
|
|
15335
|
+
throw new TypeError("replace must be a boolean");
|
|
15336
|
+
}
|
|
15337
|
+
append(args, "EXPECTED_GENERATION", expectedGeneration);
|
|
15338
|
+
appendBool(args, "REPLACE", replace);
|
|
13407
15339
|
if (options.indexedAttributes != null) {
|
|
13408
15340
|
args.push("INDEXED_ATTRIBUTES", JSON.stringify(options.indexedAttributes));
|
|
13409
15341
|
}
|
|
13410
15342
|
append(args, "INDEXED_STATE_META", options.indexedStateMeta);
|
|
13411
15343
|
append(args, "MAX_ACTIVE_MS", options.maxActiveMs);
|
|
15344
|
+
if (options.state == null) append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
13412
15345
|
append(args, "STATE", options.state);
|
|
13413
15346
|
appendPolicyMode(args, options.state, options.mode);
|
|
13414
15347
|
if (options.retry != null) {
|
|
13415
15348
|
appendRetryPolicy(args, options.retry);
|
|
13416
15349
|
}
|
|
15350
|
+
if (options.state != null) append(args, "RETENTION_TTL_MS", options.retentionTtlMs);
|
|
13417
15351
|
for (const [state, policy] of Object.entries(options.states ?? {})) {
|
|
13418
15352
|
args.push("STATE", state);
|
|
13419
15353
|
appendFlowStatePolicy(args, policy);
|
|
13420
15354
|
}
|
|
13421
|
-
|
|
13422
|
-
return await this.commandArgs(args);
|
|
15355
|
+
return flowPolicySnapshotFromResp(await this.commandArgs(args));
|
|
13423
15356
|
}
|
|
13424
15357
|
async policyGet(type, options = {}) {
|
|
13425
15358
|
const args = ["FLOW.POLICY.GET", type];
|
|
13426
15359
|
append(args, "STATE", options.state);
|
|
13427
|
-
return
|
|
15360
|
+
return flowPolicySnapshotFromResp(await this.commandArgs(args));
|
|
13428
15361
|
}
|
|
13429
15362
|
async retentionCleanup() {
|
|
13430
15363
|
return parseKvResponse(await this.command("FLOW.RETENTION_CLEANUP"));
|
|
@@ -13446,16 +15379,6 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13446
15379
|
}
|
|
13447
15380
|
return record;
|
|
13448
15381
|
}
|
|
13449
|
-
records(values) {
|
|
13450
|
-
const records = new Array(values.length);
|
|
13451
|
-
for (let index = 0; index < values.length; index += 1) {
|
|
13452
|
-
if (!Object.hasOwn(values, index)) {
|
|
13453
|
-
throw new TypeError(`Flow record response item ${index} is missing`);
|
|
13454
|
-
}
|
|
13455
|
-
records[index] = flowRecordFromResp(values[index], this.codec);
|
|
13456
|
-
}
|
|
13457
|
-
return records;
|
|
13458
|
-
}
|
|
13459
15382
|
recordsOrResponse(value) {
|
|
13460
15383
|
if (Array.isArray(value) && value.every(isRecordLike)) {
|
|
13461
15384
|
return this.records(value);
|
|
@@ -13485,12 +15408,6 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13485
15408
|
}
|
|
13486
15409
|
return results;
|
|
13487
15410
|
}
|
|
13488
|
-
async indexQuery(command, key, options) {
|
|
13489
|
-
const args = [command, key];
|
|
13490
|
-
appendReadOptions(args, options);
|
|
13491
|
-
const response = await this.commandArgs(args);
|
|
13492
|
-
return this.records(requiredArrayResponse(response, command));
|
|
13493
|
-
}
|
|
13494
15411
|
appendPartitionOptions(args, options) {
|
|
13495
15412
|
if (options.partitionKey != null && options.partitionKeys != null) {
|
|
13496
15413
|
throw new Error("partitionKey and partitionKeys are mutually exclusive");
|
|
@@ -13513,7 +15430,7 @@ var FerricStoreFlowSupportClient = class extends FerricStoreManagementClient {
|
|
|
13513
15430
|
};
|
|
13514
15431
|
|
|
13515
15432
|
// src/flow-many-snapshot.ts
|
|
13516
|
-
import { Buffer as
|
|
15433
|
+
import { Buffer as Buffer53 } from "buffer";
|
|
13517
15434
|
var encodedOptionFields = ["error", "payload", "reason", "result"];
|
|
13518
15435
|
function snapshotCreateItem(item, codec) {
|
|
13519
15436
|
const snapshot = {
|
|
@@ -13531,9 +15448,9 @@ function snapshotCreateItem(item, codec) {
|
|
|
13531
15448
|
function snapshotFlowManyOptions(options, codec) {
|
|
13532
15449
|
const snapshot = { ...options };
|
|
13533
15450
|
const mutable = snapshot;
|
|
13534
|
-
for (const
|
|
13535
|
-
const value = options[
|
|
13536
|
-
if (value != null) mutable[
|
|
15451
|
+
for (const field3 of encodedOptionFields) {
|
|
15452
|
+
const value = options[field3];
|
|
15453
|
+
if (value != null) mutable[field3] = snapshotFlowValue(codec, value);
|
|
13537
15454
|
}
|
|
13538
15455
|
if (options.attributes != null) mutable.attributes = snapshotCommandRecord(options.attributes);
|
|
13539
15456
|
if (options.attributesMerge != null) {
|
|
@@ -13553,7 +15470,7 @@ function snapshotFlowManyOptions(options, codec) {
|
|
|
13553
15470
|
}
|
|
13554
15471
|
function snapshotClaimedItem(item) {
|
|
13555
15472
|
const wire = item[CLAIMED_ITEM_WIRE];
|
|
13556
|
-
const leaseToken =
|
|
15473
|
+
const leaseToken = Buffer53.from(wire?.leaseToken ?? item.leaseToken);
|
|
13557
15474
|
const snapshot = {
|
|
13558
15475
|
...item,
|
|
13559
15476
|
fencingToken: wire?.fencingToken ?? item.fencingToken,
|
|
@@ -13570,15 +15487,15 @@ function snapshotClaimedItem(item) {
|
|
|
13570
15487
|
function snapshotFencedItem(item) {
|
|
13571
15488
|
return Object.freeze({
|
|
13572
15489
|
...item,
|
|
13573
|
-
...item.leaseToken == null ? {} : { leaseToken:
|
|
15490
|
+
...item.leaseToken == null ? {} : { leaseToken: Buffer53.from(item.leaseToken) }
|
|
13574
15491
|
});
|
|
13575
15492
|
}
|
|
13576
15493
|
function snapshotClaimedItemWire(wire, leaseToken) {
|
|
13577
15494
|
return Object.freeze({
|
|
13578
15495
|
fencingToken: wire.fencingToken,
|
|
13579
|
-
id:
|
|
15496
|
+
id: Buffer53.from(wire.id),
|
|
13580
15497
|
leaseToken,
|
|
13581
|
-
partitionKey: wire.partitionKey == null ? wire.partitionKey :
|
|
15498
|
+
partitionKey: wire.partitionKey == null ? wire.partitionKey : Buffer53.from(wire.partitionKey)
|
|
13582
15499
|
});
|
|
13583
15500
|
}
|
|
13584
15501
|
function snapshotArray(values) {
|
|
@@ -13589,7 +15506,7 @@ function snapshotArray(values) {
|
|
|
13589
15506
|
return Object.freeze(snapshot);
|
|
13590
15507
|
}
|
|
13591
15508
|
function snapshotStateMeta(stateMeta) {
|
|
13592
|
-
return snapshotRecord(stateMeta, (value) =>
|
|
15509
|
+
return snapshotRecord(stateMeta, (value) => Buffer53.isBuffer(value) ? Buffer53.from(value) : value);
|
|
13593
15510
|
}
|
|
13594
15511
|
function snapshotCommandRecord(values) {
|
|
13595
15512
|
const seen = /* @__PURE__ */ new WeakMap();
|
|
@@ -13607,7 +15524,7 @@ function snapshotRecord(values, capture) {
|
|
|
13607
15524
|
}
|
|
13608
15525
|
function snapshotCommandArgument(value, seen) {
|
|
13609
15526
|
if (typeof value !== "object" || value == null) return value;
|
|
13610
|
-
if (
|
|
15527
|
+
if (Buffer53.isBuffer(value) || value instanceof Uint8Array) return Buffer53.from(value);
|
|
13611
15528
|
const objectValue = value;
|
|
13612
15529
|
const existing = seen.get(objectValue);
|
|
13613
15530
|
if (existing != null) return existing;
|
|
@@ -14594,6 +16511,142 @@ function nativeOptionsForBootstrap(options, signal) {
|
|
|
14594
16511
|
};
|
|
14595
16512
|
}
|
|
14596
16513
|
|
|
16514
|
+
// src/flow-query-projection.ts
|
|
16515
|
+
import { Buffer as Buffer54 } from "buffer";
|
|
16516
|
+
var MAX_PROJECTION_FIELDS = 32;
|
|
16517
|
+
var MAX_DYNAMIC_NAME_BYTES = 64;
|
|
16518
|
+
var FIELD_BRAND = /* @__PURE__ */ Symbol("FerricStoreFlowProjectionField");
|
|
16519
|
+
function field2(source, selector) {
|
|
16520
|
+
return Object.freeze({ source, selector, [FIELD_BRAND]: true });
|
|
16521
|
+
}
|
|
16522
|
+
var run = Object.freeze({
|
|
16523
|
+
id: field2("runs", "run_id"),
|
|
16524
|
+
type: field2("runs", "type"),
|
|
16525
|
+
state: field2("runs", "state"),
|
|
16526
|
+
version: field2("runs", "version"),
|
|
16527
|
+
priority: field2("runs", "priority"),
|
|
16528
|
+
partitionKey: field2("runs", "partition_key"),
|
|
16529
|
+
createdAtMs: field2("runs", "created_at_ms"),
|
|
16530
|
+
updatedAtMs: field2("runs", "updated_at_ms"),
|
|
16531
|
+
nextRunAtMs: field2("runs", "next_run_at_ms"),
|
|
16532
|
+
leaseDeadlineMs: field2("runs", "lease_deadline_ms"),
|
|
16533
|
+
attempts: field2("runs", "attempts"),
|
|
16534
|
+
runState: field2("runs", "run_state"),
|
|
16535
|
+
maxActiveMs: field2("runs", "max_active_ms"),
|
|
16536
|
+
parentFlowId: field2("runs", "parent_flow_id"),
|
|
16537
|
+
rootFlowId: field2("runs", "root_flow_id"),
|
|
16538
|
+
correlationId: field2("runs", "correlation_id"),
|
|
16539
|
+
attributes: field2("runs", "attributes"),
|
|
16540
|
+
stateMetadata: field2("runs", "state_meta"),
|
|
16541
|
+
attribute(name) {
|
|
16542
|
+
return field2("runs", `attribute[${quoteName(name, false)}]`);
|
|
16543
|
+
},
|
|
16544
|
+
stateMeta(state, name) {
|
|
16545
|
+
return field2(
|
|
16546
|
+
"runs",
|
|
16547
|
+
`state_meta[${quoteName(state, true)}][${quoteName(name, false)}]`
|
|
16548
|
+
);
|
|
16549
|
+
}
|
|
16550
|
+
});
|
|
16551
|
+
var event = Object.freeze({
|
|
16552
|
+
id: field2("events", "event_id"),
|
|
16553
|
+
fields: field2("events", "fields"),
|
|
16554
|
+
field(name) {
|
|
16555
|
+
return field2("events", `fields[${quoteName(name, false)}]`);
|
|
16556
|
+
}
|
|
16557
|
+
});
|
|
16558
|
+
var FlowProjection = Object.freeze({ run, event });
|
|
16559
|
+
function projectFlowQuery(query, shape, ...fields) {
|
|
16560
|
+
validateFlowQueryText(query);
|
|
16561
|
+
if (shape !== "record" && shape !== "records") {
|
|
16562
|
+
throw new TypeError("Flow query projection shape must be record or records");
|
|
16563
|
+
}
|
|
16564
|
+
if (fields.length === 0 || fields.length > MAX_PROJECTION_FIELDS) {
|
|
16565
|
+
throw new TypeError(
|
|
16566
|
+
`Flow query projection must contain 1..${MAX_PROJECTION_FIELDS} fields`
|
|
16567
|
+
);
|
|
16568
|
+
}
|
|
16569
|
+
if (!fields.every((item) => item?.[FIELD_BRAND])) {
|
|
16570
|
+
throw new TypeError("Flow query projection accepts only FlowProjection fields");
|
|
16571
|
+
}
|
|
16572
|
+
const source = querySource(query);
|
|
16573
|
+
if (fields.some((item) => item.source !== source)) {
|
|
16574
|
+
throw new TypeError(`Flow query projection fields must belong to ${source}`);
|
|
16575
|
+
}
|
|
16576
|
+
const selectors = fields.map((item) => item.selector);
|
|
16577
|
+
if (new Set(selectors).size !== selectors.length) {
|
|
16578
|
+
throw new TypeError("Flow query projection contains a duplicate field");
|
|
16579
|
+
}
|
|
16580
|
+
if (containsReturnKeyword(query)) {
|
|
16581
|
+
throw new TypeError("Flow query already contains a RETURN clause");
|
|
16582
|
+
}
|
|
16583
|
+
const trimmed = query.trim();
|
|
16584
|
+
const base = trimmed.endsWith(";") ? trimmed.slice(0, -1).trimEnd() : trimmed;
|
|
16585
|
+
const result = `${base} RETURN ${shape.toUpperCase()} (${selectors.join(", ")})`;
|
|
16586
|
+
if (Buffer54.byteLength(result, "utf8") > FLOW_QUERY_MAX_BYTES) {
|
|
16587
|
+
throw new TypeError(`FLOW.QUERY query exceeds ${FLOW_QUERY_MAX_BYTES} bytes`);
|
|
16588
|
+
}
|
|
16589
|
+
return result;
|
|
16590
|
+
}
|
|
16591
|
+
function querySource(query) {
|
|
16592
|
+
const match = /^\s*FROM\s+(runs|events)\b/iu.exec(query);
|
|
16593
|
+
if (match?.[1] == null) {
|
|
16594
|
+
throw new TypeError("Projected Flow query must start with FROM runs or FROM events");
|
|
16595
|
+
}
|
|
16596
|
+
return match[1].toLowerCase();
|
|
16597
|
+
}
|
|
16598
|
+
function containsReturnKeyword(query) {
|
|
16599
|
+
let quoted = false;
|
|
16600
|
+
for (let index = 0; index < query.length; ) {
|
|
16601
|
+
const character = query.charAt(index);
|
|
16602
|
+
if (character === "'") {
|
|
16603
|
+
if (quoted && query[index + 1] === "'") {
|
|
16604
|
+
index += 2;
|
|
16605
|
+
continue;
|
|
16606
|
+
}
|
|
16607
|
+
quoted = !quoted;
|
|
16608
|
+
index += 1;
|
|
16609
|
+
continue;
|
|
16610
|
+
}
|
|
16611
|
+
if (!quoted && /[A-Za-z_]/u.test(character)) {
|
|
16612
|
+
let end = index + 1;
|
|
16613
|
+
while (end < query.length && /[A-Za-z0-9_]/u.test(query.charAt(end))) end += 1;
|
|
16614
|
+
if (query.slice(index, end).toUpperCase() === "RETURN") return true;
|
|
16615
|
+
index = end;
|
|
16616
|
+
continue;
|
|
16617
|
+
}
|
|
16618
|
+
index += 1;
|
|
16619
|
+
}
|
|
16620
|
+
return false;
|
|
16621
|
+
}
|
|
16622
|
+
function quoteName(value, allowPrivate) {
|
|
16623
|
+
if (typeof value !== "string") {
|
|
16624
|
+
throw new TypeError("Flow query projection metadata name must be text");
|
|
16625
|
+
}
|
|
16626
|
+
validateUnicodeScalarText2(value);
|
|
16627
|
+
const size = Buffer54.byteLength(value, "utf8");
|
|
16628
|
+
if (size === 0 || size > MAX_DYNAMIC_NAME_BYTES || !allowPrivate && value.startsWith("__")) {
|
|
16629
|
+
throw new TypeError(
|
|
16630
|
+
`Flow query projection metadata names must be 1..${MAX_DYNAMIC_NAME_BYTES} UTF-8 bytes`
|
|
16631
|
+
);
|
|
16632
|
+
}
|
|
16633
|
+
return `'${value.replaceAll("'", "''")}'`;
|
|
16634
|
+
}
|
|
16635
|
+
function validateUnicodeScalarText2(value) {
|
|
16636
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
16637
|
+
const code = value.charCodeAt(index);
|
|
16638
|
+
if (code >= 55296 && code <= 56319) {
|
|
16639
|
+
const low = value.charCodeAt(index + 1);
|
|
16640
|
+
if (!(low >= 56320 && low <= 57343)) {
|
|
16641
|
+
throw new TypeError("Flow query projection metadata name must be valid UTF-8");
|
|
16642
|
+
}
|
|
16643
|
+
index += 1;
|
|
16644
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
16645
|
+
throw new TypeError("Flow query projection metadata name must be valid UTF-8");
|
|
16646
|
+
}
|
|
16647
|
+
}
|
|
16648
|
+
}
|
|
16649
|
+
|
|
14597
16650
|
// src/outcomes.ts
|
|
14598
16651
|
var OUTCOME_BRAND = /* @__PURE__ */ Symbol("ferricstore.outcome");
|
|
14599
16652
|
function transition(toState, options = {}) {
|
|
@@ -14673,7 +16726,7 @@ var LeaseRenewalGuard = class {
|
|
|
14673
16726
|
if (options.leaseRenewal === false) {
|
|
14674
16727
|
return;
|
|
14675
16728
|
}
|
|
14676
|
-
const intervalMs =
|
|
16729
|
+
const intervalMs = positiveInteger2(options.leaseRenewIntervalMs, Math.max(1, Math.trunc(leaseMs / 2)));
|
|
14677
16730
|
this.timer = setLongInterval(() => this.renew(), intervalMs);
|
|
14678
16731
|
this.timer.unref();
|
|
14679
16732
|
}
|
|
@@ -14745,7 +16798,7 @@ function snapshotLeasedJob(job) {
|
|
|
14745
16798
|
return snapshot;
|
|
14746
16799
|
}
|
|
14747
16800
|
function workerConcurrency(options) {
|
|
14748
|
-
return
|
|
16801
|
+
return positiveInteger2(options.concurrency ?? options.workers, 1);
|
|
14749
16802
|
}
|
|
14750
16803
|
function workerRefillStrategy(options) {
|
|
14751
16804
|
return options.refillStrategy === "wave" ? "wave" : "continuous";
|
|
@@ -14788,18 +16841,18 @@ function workerErrorPayload(error, options, codec) {
|
|
|
14788
16841
|
}
|
|
14789
16842
|
function workerBatchSize(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
14790
16843
|
return Math.min(
|
|
14791
|
-
|
|
14792
|
-
|
|
16844
|
+
positiveInteger2(options.batchSize, 10),
|
|
16845
|
+
positiveInteger2(flowManyBatchLimit, DEFAULT_FLOW_MANY_BATCH_LIMIT2)
|
|
14793
16846
|
);
|
|
14794
16847
|
}
|
|
14795
16848
|
function workerClaimLimit(options, flowManyBatchLimit = DEFAULT_FLOW_MANY_BATCH_LIMIT2) {
|
|
14796
16849
|
return Math.min(workerBatchSize(options, flowManyBatchLimit), workerConcurrency(options));
|
|
14797
16850
|
}
|
|
14798
16851
|
function workerDrainBatches(options) {
|
|
14799
|
-
return
|
|
16852
|
+
return positiveInteger2(options.claimDrainBatches, 1);
|
|
14800
16853
|
}
|
|
14801
16854
|
function workerLeaseMs(options, fallback = 3e4) {
|
|
14802
|
-
return
|
|
16855
|
+
return positiveInteger2(options.leaseMs, positiveInteger2(fallback, 3e4));
|
|
14803
16856
|
}
|
|
14804
16857
|
function workerIdleSleepMs(options) {
|
|
14805
16858
|
return nonNegativeDuration(options.idleSleepMs, 250);
|
|
@@ -14811,7 +16864,7 @@ function workerClaimBlockMs(options, useBlocking) {
|
|
|
14811
16864
|
if (options.signal == null || !Number.isFinite(options.blockMs) || options.blockMs < 0) {
|
|
14812
16865
|
return options.blockMs;
|
|
14813
16866
|
}
|
|
14814
|
-
const abortPollMs =
|
|
16867
|
+
const abortPollMs = positiveInteger2(options.abortPollMs, 1e3);
|
|
14815
16868
|
return options.blockMs === 0 ? abortPollMs : Math.min(Math.trunc(options.blockMs), abortPollMs);
|
|
14816
16869
|
}
|
|
14817
16870
|
function workerMaxIdleSleepMs(options, idleSleepMs = workerIdleSleepMs(options)) {
|
|
@@ -14822,14 +16875,14 @@ function nextWorkerIdleSleepMs(currentIdleSleepMs, maxIdleSleepMs) {
|
|
|
14822
16875
|
return Math.min(maxIdleSleepMs, Math.max(1, currentIdleSleepMs * 2));
|
|
14823
16876
|
}
|
|
14824
16877
|
async function runContinuousWorkerPool(options) {
|
|
14825
|
-
const concurrency =
|
|
14826
|
-
const maxClaimSize =
|
|
16878
|
+
const concurrency = positiveInteger2(options.concurrency, 1);
|
|
16879
|
+
const maxClaimSize = positiveInteger2(options.maxClaimSize, concurrency);
|
|
14827
16880
|
const initialIdleSleepMs = nonNegativeDuration(options.idleSleepMs, 250);
|
|
14828
16881
|
const maxIdleSleepMs = Math.max(
|
|
14829
16882
|
initialIdleSleepMs,
|
|
14830
16883
|
nonNegativeDuration(options.maxIdleSleepMs, 5e3)
|
|
14831
16884
|
);
|
|
14832
|
-
const refillDelayMs =
|
|
16885
|
+
const refillDelayMs = nonNegativeInteger3(options.refillDelayMs, 0);
|
|
14833
16886
|
const active = /* @__PURE__ */ new Set();
|
|
14834
16887
|
const pending = [];
|
|
14835
16888
|
let pendingIndex = 0;
|
|
@@ -14945,10 +16998,10 @@ function normalizeWorkflowWorkerConfig(options) {
|
|
|
14945
16998
|
...captured
|
|
14946
16999
|
});
|
|
14947
17000
|
}
|
|
14948
|
-
function
|
|
17001
|
+
function positiveInteger2(value, fallback) {
|
|
14949
17002
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(1, Math.trunc(value));
|
|
14950
17003
|
}
|
|
14951
|
-
function
|
|
17004
|
+
function nonNegativeInteger3(value, fallback) {
|
|
14952
17005
|
return value == null || !Number.isFinite(value) ? fallback : Math.max(0, Math.trunc(value));
|
|
14953
17006
|
}
|
|
14954
17007
|
function nonNegativeDuration(value, fallback) {
|
|
@@ -16364,6 +18417,7 @@ var Workflow = class {
|
|
|
16364
18417
|
}
|
|
16365
18418
|
return await this.client.installPolicy(this.type, {
|
|
16366
18419
|
...options,
|
|
18420
|
+
replace: Object.hasOwn(options, "replace") ? options.replace ?? true : true,
|
|
16367
18421
|
states
|
|
16368
18422
|
});
|
|
16369
18423
|
}
|
|
@@ -16576,8 +18630,8 @@ var WorkflowWorker = class {
|
|
|
16576
18630
|
};
|
|
16577
18631
|
|
|
16578
18632
|
// src/version.ts
|
|
16579
|
-
var FERRICSTORE_SDK_VERSION = "0.
|
|
16580
|
-
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.
|
|
18633
|
+
var FERRICSTORE_SDK_VERSION = "0.5.0";
|
|
18634
|
+
var FERRICSTORE_MINIMUM_SERVER_VERSION = "0.11.0";
|
|
16581
18635
|
var FERRICSTORE_NATIVE_PROTOCOL_VERSION = 1;
|
|
16582
18636
|
export {
|
|
16583
18637
|
BitmapStore,
|
|
@@ -16595,6 +18649,8 @@ export {
|
|
|
16595
18649
|
FlowAlreadyExistsError,
|
|
16596
18650
|
FlowBatchError,
|
|
16597
18651
|
FlowNotFoundError,
|
|
18652
|
+
FlowProjection,
|
|
18653
|
+
FlowQueryError,
|
|
16598
18654
|
FlowWrongStateError,
|
|
16599
18655
|
GeoStore,
|
|
16600
18656
|
HashStore,
|
|
@@ -16606,6 +18662,7 @@ export {
|
|
|
16606
18662
|
ListStore,
|
|
16607
18663
|
LockHeldError,
|
|
16608
18664
|
LockNotOwnedError,
|
|
18665
|
+
MAX_FLOW_POLICY_GENERATION,
|
|
16609
18666
|
NativeAdapter,
|
|
16610
18667
|
OverloadedError,
|
|
16611
18668
|
Queue,
|
|
@@ -16620,6 +18677,7 @@ export {
|
|
|
16620
18677
|
SetStore,
|
|
16621
18678
|
SortedSetStore,
|
|
16622
18679
|
StaleLeaseError,
|
|
18680
|
+
StalePolicyGenerationError,
|
|
16623
18681
|
StreamStore,
|
|
16624
18682
|
TDigestStore,
|
|
16625
18683
|
TopKStore,
|
|
@@ -16635,6 +18693,7 @@ export {
|
|
|
16635
18693
|
isOutcome,
|
|
16636
18694
|
isReconnectableClosedConnectionError,
|
|
16637
18695
|
mapException,
|
|
18696
|
+
projectFlowQuery,
|
|
16638
18697
|
retry,
|
|
16639
18698
|
transition
|
|
16640
18699
|
};
|