@ferricstore/ferricstore 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -1
- package/dist/index.cjs +5348 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1322 -0
- package/dist/index.d.ts +34 -4
- package/dist/index.js +130 -3
- package/dist/index.js.map +1 -1
- package/docs/api/assets/hierarchy.js +1 -1
- package/docs/api/assets/highlight.css +10 -10
- package/docs/api/assets/navigation.js +1 -1
- package/docs/api/assets/search.js +1 -1
- package/docs/api/classes/FerricStoreClient.html +2 -2
- package/docs/api/classes/FerricStoreError.html +6 -6
- package/docs/api/classes/FlowAlreadyExistsError.html +6 -6
- package/docs/api/classes/FlowNotFoundError.html +6 -6
- package/docs/api/classes/FlowWrongStateError.html +6 -6
- package/docs/api/classes/InvalidCommandError.html +6 -6
- package/docs/api/classes/LockHeldError.html +6 -6
- package/docs/api/classes/LockNotOwnedError.html +6 -6
- package/docs/api/classes/NativeAdapter.html +2 -2
- package/docs/api/classes/OverloadedError.html +6 -6
- package/docs/api/classes/ReconnectingExecutor.html +5 -0
- package/docs/api/classes/StaleLeaseError.html +6 -6
- package/docs/api/functions/isReconnectableClosedConnectionError.html +1 -0
- package/docs/api/hierarchy.html +1 -1
- package/docs/api/index.html +18 -10
- package/docs/api/interfaces/AutoBatchOptions.html +2 -2
- package/docs/api/interfaces/CancelOptions.html +2 -2
- package/docs/api/interfaces/ClaimDueOptions.html +2 -2
- package/docs/api/interfaces/CommandExecutor.html +1 -1
- package/docs/api/interfaces/CompleteOptions.html +2 -2
- package/docs/api/interfaces/CompleteOutcome.html +1 -1
- package/docs/api/interfaces/CreateManyOptions.html +2 -2
- package/docs/api/interfaces/CreateOptions.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 +6 -0
- package/docs/api/interfaces/FerricStoreClientOptions.html +2 -2
- package/docs/api/interfaces/MutateOptions.html +2 -2
- package/docs/api/interfaces/NamedValueMutation.html +1 -1
- package/docs/api/interfaces/NativeAdapterOptions.html +6 -2
- package/docs/api/interfaces/ReadOptions.html +2 -2
- package/docs/api/interfaces/ReclaimOptions.html +2 -2
- package/docs/api/interfaces/ReconnectOptions.html +2 -0
- package/docs/api/interfaces/RetryOptions.html +2 -2
- package/docs/api/interfaces/RetryOutcome.html +1 -1
- 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/package.json +17 -7
package/dist/index.d.ts
CHANGED
|
@@ -25,8 +25,12 @@ interface ExecutePipelineOptions {
|
|
|
25
25
|
throwOnItemError?: boolean;
|
|
26
26
|
}
|
|
27
27
|
interface NativeAdapterOptions {
|
|
28
|
+
autoReconnect?: boolean | ReconnectOptions;
|
|
28
29
|
clientName?: string;
|
|
29
30
|
connectTimeoutMs?: number;
|
|
31
|
+
heartbeatIntervalMs?: number;
|
|
32
|
+
keepAlive?: boolean;
|
|
33
|
+
keepAliveInitialDelayMs?: number;
|
|
30
34
|
maxChunkBytes?: number;
|
|
31
35
|
protocolLanes?: number;
|
|
32
36
|
timeoutMs?: number;
|
|
@@ -34,6 +38,9 @@ interface NativeAdapterOptions {
|
|
|
34
38
|
password?: string;
|
|
35
39
|
tlsOptions?: tls.ConnectionOptions;
|
|
36
40
|
}
|
|
41
|
+
interface ReconnectOptions {
|
|
42
|
+
maxRetries?: number;
|
|
43
|
+
}
|
|
37
44
|
declare class NativeAdapter implements CommandExecutor {
|
|
38
45
|
private readonly socket;
|
|
39
46
|
private readonly pending;
|
|
@@ -45,6 +52,10 @@ declare class NativeAdapter implements CommandExecutor {
|
|
|
45
52
|
private readonly maxChunkBytes;
|
|
46
53
|
private requestId;
|
|
47
54
|
private readonly protocolLanes;
|
|
55
|
+
private readonly heartbeatIntervalMs?;
|
|
56
|
+
private heartbeatInFlight;
|
|
57
|
+
private heartbeatTimer?;
|
|
58
|
+
private lastActivityMs;
|
|
48
59
|
private readonly timeoutMs;
|
|
49
60
|
private constructor();
|
|
50
61
|
static fromUrl(url: string, options?: NativeAdapterOptions): Promise<NativeAdapter>;
|
|
@@ -54,6 +65,9 @@ declare class NativeAdapter implements CommandExecutor {
|
|
|
54
65
|
private startup;
|
|
55
66
|
private auth;
|
|
56
67
|
private request;
|
|
68
|
+
private startHeartbeat;
|
|
69
|
+
private stopHeartbeat;
|
|
70
|
+
private sendHeartbeat;
|
|
57
71
|
private onData;
|
|
58
72
|
private handleFrame;
|
|
59
73
|
private failAll;
|
|
@@ -61,6 +75,20 @@ declare class NativeAdapter implements CommandExecutor {
|
|
|
61
75
|
private nextRequestId;
|
|
62
76
|
private assignLane;
|
|
63
77
|
}
|
|
78
|
+
declare class ReconnectingExecutor implements CommandExecutor {
|
|
79
|
+
private readonly createExecutor;
|
|
80
|
+
private closed;
|
|
81
|
+
private readonly maxRetries;
|
|
82
|
+
private executorPromise;
|
|
83
|
+
private reconnectPromise?;
|
|
84
|
+
constructor(createExecutor: () => Promise<CommandExecutor>, options?: ReconnectOptions);
|
|
85
|
+
executeCommand(...args: CommandArgument[]): Promise<unknown>;
|
|
86
|
+
executePipeline(commands: readonly Command[], options?: ExecutePipelineOptions): Promise<unknown[]>;
|
|
87
|
+
close(): Promise<void>;
|
|
88
|
+
private withReconnect;
|
|
89
|
+
private reconnect;
|
|
90
|
+
}
|
|
91
|
+
declare function isReconnectableClosedConnectionError(error: unknown): boolean;
|
|
64
92
|
|
|
65
93
|
interface StoreCommandClient {
|
|
66
94
|
readonly codec: Codec;
|
|
@@ -576,6 +604,10 @@ interface FerricStoreClientOptions {
|
|
|
576
604
|
codec?: Codec;
|
|
577
605
|
backpressure?: BackpressurePolicy;
|
|
578
606
|
}
|
|
607
|
+
interface FerricStoreClientFromUrlOptions extends FerricStoreClientOptions {
|
|
608
|
+
nativeOptions?: NativeAdapterOptions;
|
|
609
|
+
reconnect?: boolean | ReconnectOptions;
|
|
610
|
+
}
|
|
579
611
|
interface CreateOptions {
|
|
580
612
|
type: string;
|
|
581
613
|
state?: string;
|
|
@@ -695,9 +727,7 @@ declare class FerricStoreClient {
|
|
|
695
727
|
readonly topk: TopKStore;
|
|
696
728
|
readonly zset: SortedSetStore;
|
|
697
729
|
constructor(executor: CommandExecutor, options?: FerricStoreClientOptions);
|
|
698
|
-
static fromUrl(url: string, options?:
|
|
699
|
-
nativeOptions?: NativeAdapterOptions;
|
|
700
|
-
}): Promise<FerricStoreClient>;
|
|
730
|
+
static fromUrl(url: string, options?: FerricStoreClientFromUrlOptions): Promise<FerricStoreClient>;
|
|
701
731
|
command(...args: CommandArgument[]): Promise<unknown>;
|
|
702
732
|
pipeline(commands: readonly Command[]): Promise<unknown[]>;
|
|
703
733
|
close(): Promise<void>;
|
|
@@ -1289,4 +1319,4 @@ declare class WorkflowWorker {
|
|
|
1289
1319
|
private applyHandlerError;
|
|
1290
1320
|
}
|
|
1291
1321
|
|
|
1292
|
-
export { type AutoBatchOptions, type BackoffKind, type BackpressurePolicy, BitmapStore, BloomFilterStore, type CancelOptions, type ChildSpec, type ClaimDueOptions, type ClaimedItem, type Codec, type Command, type CommandArgument, type CommandExecutor, type CompleteOptions, type CompleteOutcome, type CountMinMergeOptions, CountMinSketchStore, type CreateItem, type CreateManyOptions, type CreateOptions, CuckooFilterStore, type ExceptionPolicy, type ExecutePipelineOptions, type FailOptions, type FailOutcome, type FencedItem, FerricStoreClient, type FerricStoreClientOptions, FerricStoreError, type FetchOrComputeResult, FlowAlreadyExistsError, FlowNotFoundError, type FlowRecord, FlowWrongStateError, type GeoAddOptions, type GeoMember, GeoStore, type GetExOptions, HashStore, HyperLogLogStore, InvalidCommandError, JsonCodec, type JsonSetOptions, JsonStore, type KeyInfo, KeyValueStore, ListStore, LockHeldError, LockNotOwnedError, type MutateOptions, type NamedValueMutation, NativeAdapter, type NativeAdapterOptions, type Outcome, OverloadedError, Queue, type QueueBatchHandler, QueueClient, type QueueHandler, type QueueOptions, QueueWorker, type QueueWorkerResult, type RangeLimit, type RateLimitResult, RawCodec, type ReadOptions, type ReclaimOptions, type RetryOptions, type RetryOutcome, type RetryPolicy, type ScanOptions, type SetOptions, SetStore, SortedSetStore, StaleLeaseError, type StateMeta, type StateMetaValue, type StateOptions, type StateRegistration, type StoreCommandClient, StreamStore, type TDigestCreateOptions, type TDigestMergeOptions, TDigestStore, type TopKReserveOptions, TopKStore, type TransitionOptions, type TransitionOutcome, type ValueConfig, type WorkerConfig, type WorkerProfile, Workflow, WorkflowClient, WorkflowContext, WorkflowFlowCommands, type WorkflowHandler, type WorkflowOptions, WorkflowWorker, type WorkflowWorkerResult, type XReadStream, type ZAddMember, type ZAddOptions, classifyServerError, complete, fail, mapException, retry, transition };
|
|
1322
|
+
export { type AutoBatchOptions, type BackoffKind, type BackpressurePolicy, BitmapStore, BloomFilterStore, type CancelOptions, type ChildSpec, type ClaimDueOptions, type ClaimedItem, type Codec, type Command, type CommandArgument, type CommandExecutor, type CompleteOptions, type CompleteOutcome, type CountMinMergeOptions, CountMinSketchStore, type CreateItem, type CreateManyOptions, type CreateOptions, CuckooFilterStore, type ExceptionPolicy, type ExecutePipelineOptions, type FailOptions, type FailOutcome, type FencedItem, FerricStoreClient, type FerricStoreClientFromUrlOptions, type FerricStoreClientOptions, FerricStoreError, type FetchOrComputeResult, FlowAlreadyExistsError, FlowNotFoundError, type FlowRecord, FlowWrongStateError, type GeoAddOptions, type GeoMember, GeoStore, type GetExOptions, HashStore, HyperLogLogStore, InvalidCommandError, JsonCodec, type JsonSetOptions, JsonStore, type KeyInfo, KeyValueStore, ListStore, LockHeldError, LockNotOwnedError, type MutateOptions, type NamedValueMutation, NativeAdapter, type NativeAdapterOptions, type Outcome, OverloadedError, Queue, type QueueBatchHandler, QueueClient, type QueueHandler, type QueueOptions, QueueWorker, type QueueWorkerResult, type RangeLimit, type RateLimitResult, RawCodec, type ReadOptions, type ReclaimOptions, type ReconnectOptions, ReconnectingExecutor, type RetryOptions, type RetryOutcome, type RetryPolicy, type ScanOptions, type SetOptions, SetStore, SortedSetStore, StaleLeaseError, type StateMeta, type StateMetaValue, type StateOptions, type StateRegistration, type StoreCommandClient, StreamStore, type TDigestCreateOptions, type TDigestMergeOptions, TDigestStore, type TopKReserveOptions, TopKStore, type TransitionOptions, type TransitionOutcome, type ValueConfig, type WorkerConfig, type WorkerProfile, Workflow, WorkflowClient, WorkflowContext, WorkflowFlowCommands, type WorkflowHandler, type WorkflowOptions, WorkflowWorker, type WorkflowWorkerResult, type XReadStream, type ZAddMember, type ZAddOptions, classifyServerError, complete, fail, isReconnectableClosedConnectionError, mapException, retry, transition };
|
package/dist/index.js
CHANGED
|
@@ -1393,15 +1393,21 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1393
1393
|
maxChunkBytes;
|
|
1394
1394
|
requestId = 0n;
|
|
1395
1395
|
protocolLanes;
|
|
1396
|
+
heartbeatIntervalMs;
|
|
1397
|
+
heartbeatInFlight = false;
|
|
1398
|
+
heartbeatTimer;
|
|
1399
|
+
lastActivityMs = Date.now();
|
|
1396
1400
|
timeoutMs;
|
|
1397
|
-
constructor(socket, timeoutMs, protocolLanes, maxChunkBytes) {
|
|
1401
|
+
constructor(socket, timeoutMs, protocolLanes, maxChunkBytes, heartbeatIntervalMs) {
|
|
1398
1402
|
this.socket = socket;
|
|
1399
1403
|
this.maxChunkBytes = Math.max(1, Math.trunc(maxChunkBytes));
|
|
1400
1404
|
this.timeoutMs = timeoutMs;
|
|
1401
1405
|
this.protocolLanes = Math.max(1, Math.trunc(protocolLanes));
|
|
1406
|
+
this.heartbeatIntervalMs = normalizeHeartbeatInterval(heartbeatIntervalMs);
|
|
1402
1407
|
this.socket.on("data", (chunk) => this.onData(chunk));
|
|
1403
1408
|
this.socket.on("error", (error) => this.failAll(error));
|
|
1404
1409
|
this.socket.on("close", () => this.failAll(new FerricStoreError("FerricStore connection closed")));
|
|
1410
|
+
this.startHeartbeat();
|
|
1405
1411
|
}
|
|
1406
1412
|
static async fromUrl(url, options = {}) {
|
|
1407
1413
|
const parsed = parseFerricUrl(url);
|
|
@@ -1410,7 +1416,8 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1410
1416
|
socket,
|
|
1411
1417
|
options.timeoutMs ?? 3e4,
|
|
1412
1418
|
options.protocolLanes ?? 8,
|
|
1413
|
-
options.maxChunkBytes ?? 64 * 1024 * 1024
|
|
1419
|
+
options.maxChunkBytes ?? 64 * 1024 * 1024,
|
|
1420
|
+
options.heartbeatIntervalMs
|
|
1414
1421
|
);
|
|
1415
1422
|
await adapter.startup(options.clientName);
|
|
1416
1423
|
const password = options.password ?? parsed.password;
|
|
@@ -1434,6 +1441,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1434
1441
|
return;
|
|
1435
1442
|
}
|
|
1436
1443
|
this.closed = true;
|
|
1444
|
+
this.stopHeartbeat();
|
|
1437
1445
|
this.socket.end();
|
|
1438
1446
|
}
|
|
1439
1447
|
async startup(clientName) {
|
|
@@ -1455,6 +1463,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1455
1463
|
if (this.closed) {
|
|
1456
1464
|
throw new FerricStoreError("FerricStore connection is closed");
|
|
1457
1465
|
}
|
|
1466
|
+
this.lastActivityMs = Date.now();
|
|
1458
1467
|
const requestId = this.nextRequestId();
|
|
1459
1468
|
const frame = encodeRequest(this.assignLane(command), requestId);
|
|
1460
1469
|
return await new Promise((resolve, reject) => {
|
|
@@ -1468,10 +1477,12 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1468
1477
|
opcode: command.opcode,
|
|
1469
1478
|
reject: (reason) => {
|
|
1470
1479
|
clearTimeout(timer);
|
|
1480
|
+
this.lastActivityMs = Date.now();
|
|
1471
1481
|
reject(reason instanceof Error ? reason : classifyServerError(String(reason), reason));
|
|
1472
1482
|
},
|
|
1473
1483
|
resolve: (value) => {
|
|
1474
1484
|
clearTimeout(timer);
|
|
1485
|
+
this.lastActivityMs = Date.now();
|
|
1475
1486
|
resolve(value);
|
|
1476
1487
|
}
|
|
1477
1488
|
});
|
|
@@ -1480,11 +1491,43 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1480
1491
|
this.pending.delete(requestId);
|
|
1481
1492
|
this.cleanupChunksForRequest(requestId);
|
|
1482
1493
|
clearTimeout(timer);
|
|
1494
|
+
this.lastActivityMs = Date.now();
|
|
1483
1495
|
reject(error);
|
|
1484
1496
|
}
|
|
1485
1497
|
});
|
|
1486
1498
|
});
|
|
1487
1499
|
}
|
|
1500
|
+
startHeartbeat() {
|
|
1501
|
+
if (this.heartbeatIntervalMs == null) {
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
this.heartbeatTimer = setInterval(() => {
|
|
1505
|
+
void this.sendHeartbeat();
|
|
1506
|
+
}, this.heartbeatIntervalMs);
|
|
1507
|
+
this.heartbeatTimer.unref?.();
|
|
1508
|
+
}
|
|
1509
|
+
stopHeartbeat() {
|
|
1510
|
+
if (this.heartbeatTimer == null) {
|
|
1511
|
+
return;
|
|
1512
|
+
}
|
|
1513
|
+
clearInterval(this.heartbeatTimer);
|
|
1514
|
+
this.heartbeatTimer = void 0;
|
|
1515
|
+
}
|
|
1516
|
+
async sendHeartbeat() {
|
|
1517
|
+
if (this.closed || this.heartbeatInFlight || this.pending.size > 0 || this.heartbeatIntervalMs == null) {
|
|
1518
|
+
return;
|
|
1519
|
+
}
|
|
1520
|
+
if (Date.now() - this.lastActivityMs < this.heartbeatIntervalMs) {
|
|
1521
|
+
return;
|
|
1522
|
+
}
|
|
1523
|
+
this.heartbeatInFlight = true;
|
|
1524
|
+
try {
|
|
1525
|
+
await this.request(buildProtocolCommand(["PING"]));
|
|
1526
|
+
} catch {
|
|
1527
|
+
} finally {
|
|
1528
|
+
this.heartbeatInFlight = false;
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1488
1531
|
onData(chunk) {
|
|
1489
1532
|
try {
|
|
1490
1533
|
this.buffer = this.buffer.byteLength === 0 ? chunk : Buffer3.concat([this.buffer, chunk]);
|
|
@@ -1543,6 +1586,7 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1543
1586
|
return;
|
|
1544
1587
|
}
|
|
1545
1588
|
this.closed = true;
|
|
1589
|
+
this.stopHeartbeat();
|
|
1546
1590
|
const error = reason instanceof Error ? reason : classifyServerError(String(reason), reason);
|
|
1547
1591
|
for (const pending of this.pending.values()) {
|
|
1548
1592
|
pending.reject(error);
|
|
@@ -1575,6 +1619,74 @@ var NativeAdapter = class _NativeAdapter {
|
|
|
1575
1619
|
return { ...command, laneId: this.dataLane };
|
|
1576
1620
|
}
|
|
1577
1621
|
};
|
|
1622
|
+
var ReconnectingExecutor = class {
|
|
1623
|
+
constructor(createExecutor, options = {}) {
|
|
1624
|
+
this.createExecutor = createExecutor;
|
|
1625
|
+
this.maxRetries = Math.max(0, Math.trunc(options.maxRetries ?? 1));
|
|
1626
|
+
this.executorPromise = createExecutor();
|
|
1627
|
+
}
|
|
1628
|
+
createExecutor;
|
|
1629
|
+
closed = false;
|
|
1630
|
+
maxRetries;
|
|
1631
|
+
executorPromise;
|
|
1632
|
+
reconnectPromise;
|
|
1633
|
+
async executeCommand(...args) {
|
|
1634
|
+
return await this.withReconnect((executor) => executor.executeCommand(...args));
|
|
1635
|
+
}
|
|
1636
|
+
async executePipeline(commands, options = {}) {
|
|
1637
|
+
return await this.withReconnect(async (executor) => {
|
|
1638
|
+
if (executor.executePipeline != null) {
|
|
1639
|
+
return await executor.executePipeline(commands, options);
|
|
1640
|
+
}
|
|
1641
|
+
return await Promise.all(commands.map((command) => executor.executeCommand(...command)));
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1644
|
+
async close() {
|
|
1645
|
+
if (this.closed) {
|
|
1646
|
+
return;
|
|
1647
|
+
}
|
|
1648
|
+
this.closed = true;
|
|
1649
|
+
const executor = await this.executorPromise.catch(() => void 0);
|
|
1650
|
+
await Promise.resolve(executor?.close?.());
|
|
1651
|
+
}
|
|
1652
|
+
async withReconnect(operation) {
|
|
1653
|
+
let executor = await this.executorPromise;
|
|
1654
|
+
for (let attempt = 0; ; attempt++) {
|
|
1655
|
+
try {
|
|
1656
|
+
return await operation(executor);
|
|
1657
|
+
} catch (error) {
|
|
1658
|
+
if (this.closed || attempt >= this.maxRetries || !isReconnectableClosedConnectionError(error)) {
|
|
1659
|
+
throw error;
|
|
1660
|
+
}
|
|
1661
|
+
executor = await this.reconnect(executor);
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
}
|
|
1665
|
+
async reconnect(staleExecutor) {
|
|
1666
|
+
if (this.closed) {
|
|
1667
|
+
throw new FerricStoreError("FerricStore client is closed");
|
|
1668
|
+
}
|
|
1669
|
+
if (this.reconnectPromise != null) {
|
|
1670
|
+
return await this.reconnectPromise;
|
|
1671
|
+
}
|
|
1672
|
+
const currentExecutor = await this.executorPromise.catch(() => void 0);
|
|
1673
|
+
if (currentExecutor != null && currentExecutor !== staleExecutor) {
|
|
1674
|
+
return currentExecutor;
|
|
1675
|
+
}
|
|
1676
|
+
this.reconnectPromise = (async () => {
|
|
1677
|
+
await Promise.resolve(staleExecutor.close?.()).catch(() => void 0);
|
|
1678
|
+
const nextExecutor = await this.createExecutor();
|
|
1679
|
+
this.executorPromise = Promise.resolve(nextExecutor);
|
|
1680
|
+
return nextExecutor;
|
|
1681
|
+
})().finally(() => {
|
|
1682
|
+
this.reconnectPromise = void 0;
|
|
1683
|
+
});
|
|
1684
|
+
return await this.reconnectPromise;
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
function isReconnectableClosedConnectionError(error) {
|
|
1688
|
+
return error instanceof Error && error.message === "FerricStore connection is closed";
|
|
1689
|
+
}
|
|
1578
1690
|
function parseFerricUrl(value) {
|
|
1579
1691
|
const url = new URL(value);
|
|
1580
1692
|
if (url.protocol !== "ferric:" && url.protocol !== "ferrics:") {
|
|
@@ -1598,6 +1710,7 @@ async function connect(parsed, options) {
|
|
|
1598
1710
|
}, timeoutMs);
|
|
1599
1711
|
timer.unref?.();
|
|
1600
1712
|
socket.setNoDelay(true);
|
|
1713
|
+
socket.setKeepAlive(options.keepAlive ?? true, normalizeKeepAliveInitialDelay(options.keepAliveInitialDelayMs));
|
|
1601
1714
|
socket.once("connect", () => {
|
|
1602
1715
|
clearTimeout(timer);
|
|
1603
1716
|
resolve(socket);
|
|
@@ -1608,6 +1721,15 @@ async function connect(parsed, options) {
|
|
|
1608
1721
|
});
|
|
1609
1722
|
});
|
|
1610
1723
|
}
|
|
1724
|
+
function normalizeHeartbeatInterval(value) {
|
|
1725
|
+
if (value != null && value <= 0) {
|
|
1726
|
+
return void 0;
|
|
1727
|
+
}
|
|
1728
|
+
return Math.trunc(value ?? 6e4);
|
|
1729
|
+
}
|
|
1730
|
+
function normalizeKeepAliveInitialDelay(value) {
|
|
1731
|
+
return Math.max(0, Math.trunc(value ?? 3e4));
|
|
1732
|
+
}
|
|
1611
1733
|
|
|
1612
1734
|
// src/codecs.ts
|
|
1613
1735
|
var RawCodec = class {
|
|
@@ -2998,7 +3120,10 @@ var FerricStoreClient = class _FerricStoreClient {
|
|
|
2998
3120
|
this.zset = new SortedSetStore(this);
|
|
2999
3121
|
}
|
|
3000
3122
|
static async fromUrl(url, options = {}) {
|
|
3001
|
-
|
|
3123
|
+
const reconnectOptions = options.reconnect ?? options.nativeOptions?.autoReconnect ?? true;
|
|
3124
|
+
const createExecutor = async () => await NativeAdapter.fromUrl(url, options.nativeOptions);
|
|
3125
|
+
const executor = reconnectOptions === false ? await createExecutor() : new ReconnectingExecutor(createExecutor, reconnectOptions === true ? {} : reconnectOptions);
|
|
3126
|
+
return new _FerricStoreClient(executor, options);
|
|
3002
3127
|
}
|
|
3003
3128
|
async command(...args) {
|
|
3004
3129
|
return await this.executor.executeCommand(...args);
|
|
@@ -5120,6 +5245,7 @@ export {
|
|
|
5120
5245
|
QueueClient,
|
|
5121
5246
|
QueueWorker,
|
|
5122
5247
|
RawCodec,
|
|
5248
|
+
ReconnectingExecutor,
|
|
5123
5249
|
SetStore,
|
|
5124
5250
|
SortedSetStore,
|
|
5125
5251
|
StaleLeaseError,
|
|
@@ -5134,6 +5260,7 @@ export {
|
|
|
5134
5260
|
classifyServerError,
|
|
5135
5261
|
complete,
|
|
5136
5262
|
fail,
|
|
5263
|
+
isReconnectableClosedConnectionError,
|
|
5137
5264
|
mapException,
|
|
5138
5265
|
retry,
|
|
5139
5266
|
transition
|