memcache 1.3.0 → 1.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/dist/index.d.cts CHANGED
@@ -1,139 +1,6 @@
1
1
  import { Hookified } from 'hookified';
2
2
  import { Socket } from 'node:net';
3
3
 
4
- /**
5
- * SASL authentication credentials for connecting to a secured memcache server.
6
- */
7
- interface SASLCredentials {
8
- /**
9
- * Username for SASL authentication
10
- */
11
- username: string;
12
- /**
13
- * Password for SASL authentication
14
- */
15
- password: string;
16
- /**
17
- * SASL mechanism to use (default: 'PLAIN')
18
- * Currently only 'PLAIN' is supported.
19
- */
20
- mechanism?: "PLAIN";
21
- }
22
- declare enum MemcacheEvents {
23
- CONNECT = "connect",
24
- QUIT = "quit",
25
- HIT = "hit",
26
- MISS = "miss",
27
- ERROR = "error",
28
- WARN = "warn",
29
- INFO = "info",
30
- TIMEOUT = "timeout",
31
- CLOSE = "close"
32
- }
33
- /**
34
- * Function to calculate delay between retry attempts.
35
- * @param attempt - The current attempt number (0-indexed)
36
- * @param baseDelay - The base delay in milliseconds
37
- * @returns The delay in milliseconds before the next retry
38
- */
39
- type RetryBackoffFunction = (attempt: number, baseDelay: number) => number;
40
- interface HashProvider {
41
- name: string;
42
- nodes: Array<MemcacheNode>;
43
- addNode: (node: MemcacheNode) => void;
44
- removeNode: (id: string) => void;
45
- getNode: (id: string) => MemcacheNode | undefined;
46
- getNodesByKey: (key: string) => Array<MemcacheNode>;
47
- }
48
- interface MemcacheOptions {
49
- /**
50
- * Array of node URIs or MemcacheNode instances to add to the consistent hashing ring.
51
- * Examples: ["localhost:11211", "memcache://192.168.1.100:11212", "server3:11213"]
52
- * Can also pass MemcacheNode instances directly: [createNode("localhost", 11211), createNode("server2", 11211)]
53
- */
54
- nodes?: (string | MemcacheNode)[];
55
- /**
56
- * The timeout for Memcache operations.
57
- * @default 5000
58
- */
59
- timeout?: number;
60
- /**
61
- * Whether to keep the connection alive.
62
- * @default true
63
- */
64
- keepAlive?: boolean;
65
- /**
66
- * The delay before the connection is kept alive.
67
- * @default 1000
68
- */
69
- keepAliveDelay?: number;
70
- /**
71
- * The hash provider used to determine the distribution on each item is placed based
72
- * on the number of nodes and hashing. By default it uses KetamaHash as the provider
73
- */
74
- hash?: HashProvider;
75
- /**
76
- * The number of retry attempts for failed commands.
77
- * Set to 0 to disable retries.
78
- * @default 0
79
- */
80
- retries?: number;
81
- /**
82
- * The base delay in milliseconds between retry attempts.
83
- * @default 100
84
- */
85
- retryDelay?: number;
86
- /**
87
- * Function to calculate backoff delay between retries.
88
- * Receives (attempt, baseDelay) and returns delay in ms.
89
- * @default defaultRetryBackoff (fixed delay)
90
- */
91
- retryBackoff?: RetryBackoffFunction;
92
- /**
93
- * When true, retries are only performed for commands marked as idempotent.
94
- * This prevents accidental double-execution of non-idempotent operations
95
- * (like incr, decr, append) if the server applies the command but the
96
- * client doesn't receive the response before a timeout/disconnect.
97
- * @default true
98
- */
99
- retryOnlyIdempotent?: boolean;
100
- /**
101
- * SASL authentication credentials for all nodes.
102
- * When provided, nodes will authenticate using SASL PLAIN mechanism
103
- * before accepting commands.
104
- */
105
- sasl?: SASLCredentials;
106
- }
107
- interface MemcacheStats {
108
- [key: string]: string;
109
- }
110
- interface ExecuteOptions {
111
- /** Command options passed to node.command() */
112
- commandOptions?: CommandOptions;
113
- /**
114
- * Override the number of retries for this specific execution.
115
- * If undefined, uses the instance-level retries setting.
116
- */
117
- retries?: number;
118
- /**
119
- * Override the retry delay for this specific execution.
120
- * If undefined, uses the instance-level retryDelay setting.
121
- */
122
- retryDelay?: number;
123
- /**
124
- * Override the backoff function for this specific execution.
125
- * If undefined, uses the instance-level retryBackoff setting.
126
- */
127
- retryBackoff?: RetryBackoffFunction;
128
- /**
129
- * Mark this command as idempotent, allowing retries even when
130
- * retryOnlyIdempotent is true. Set this for read operations (get, gets)
131
- * or operations that are safe to repeat (set with same value).
132
- * @default false
133
- */
134
- idempotent?: boolean;
135
- }
136
-
137
4
  interface MemcacheNodeOptions {
138
5
  timeout?: number;
139
6
  keepAlive?: boolean;
@@ -145,6 +12,7 @@ interface MemcacheNodeOptions {
145
12
  interface CommandOptions {
146
13
  isMultiline?: boolean;
147
14
  isStats?: boolean;
15
+ isConfig?: boolean;
148
16
  requestedKeys?: string[];
149
17
  }
150
18
  type CommandQueueItem = {
@@ -153,6 +21,7 @@ type CommandQueueItem = {
153
21
  reject: (reason?: any) => void;
154
22
  isMultiline?: boolean;
155
23
  isStats?: boolean;
24
+ isConfig?: boolean;
156
25
  requestedKeys?: string[];
157
26
  foundKeys?: string[];
158
27
  };
@@ -348,6 +217,324 @@ declare class MemcacheNode extends Hookified {
348
217
  */
349
218
  declare function createNode(host: string, port: number, options?: MemcacheNodeOptions): MemcacheNode;
350
219
 
220
+ /**
221
+ * SASL authentication credentials for connecting to a secured memcache server.
222
+ */
223
+ interface SASLCredentials {
224
+ /**
225
+ * Username for SASL authentication
226
+ */
227
+ username: string;
228
+ /**
229
+ * Password for SASL authentication
230
+ */
231
+ password: string;
232
+ /**
233
+ * SASL mechanism to use (default: 'PLAIN')
234
+ * Currently only 'PLAIN' is supported.
235
+ */
236
+ mechanism?: "PLAIN";
237
+ }
238
+ declare enum MemcacheEvents {
239
+ CONNECT = "connect",
240
+ QUIT = "quit",
241
+ HIT = "hit",
242
+ MISS = "miss",
243
+ ERROR = "error",
244
+ WARN = "warn",
245
+ INFO = "info",
246
+ TIMEOUT = "timeout",
247
+ CLOSE = "close",
248
+ AUTO_DISCOVER = "autoDiscover",
249
+ AUTO_DISCOVER_ERROR = "autoDiscoverError",
250
+ AUTO_DISCOVER_UPDATE = "autoDiscoverUpdate"
251
+ }
252
+ /**
253
+ * Function to calculate delay between retry attempts.
254
+ * @param attempt - The current attempt number (0-indexed)
255
+ * @param baseDelay - The base delay in milliseconds
256
+ * @returns The delay in milliseconds before the next retry
257
+ */
258
+ type RetryBackoffFunction = (attempt: number, baseDelay: number) => number;
259
+ interface HashProvider {
260
+ name: string;
261
+ nodes: Array<MemcacheNode>;
262
+ addNode: (node: MemcacheNode) => void;
263
+ removeNode: (id: string) => void;
264
+ getNode: (id: string) => MemcacheNode | undefined;
265
+ getNodesByKey: (key: string) => Array<MemcacheNode>;
266
+ }
267
+ interface MemcacheOptions {
268
+ /**
269
+ * Array of node URIs or MemcacheNode instances to add to the consistent hashing ring.
270
+ * Examples: ["localhost:11211", "memcache://192.168.1.100:11212", "server3:11213"]
271
+ * Can also pass MemcacheNode instances directly: [createNode("localhost", 11211), createNode("server2", 11211)]
272
+ */
273
+ nodes?: (string | MemcacheNode)[];
274
+ /**
275
+ * The timeout for Memcache operations.
276
+ * @default 5000
277
+ */
278
+ timeout?: number;
279
+ /**
280
+ * Whether to keep the connection alive.
281
+ * @default true
282
+ */
283
+ keepAlive?: boolean;
284
+ /**
285
+ * The delay before the connection is kept alive.
286
+ * @default 1000
287
+ */
288
+ keepAliveDelay?: number;
289
+ /**
290
+ * The hash provider used to determine the distribution on each item is placed based
291
+ * on the number of nodes and hashing. By default it uses KetamaHash as the provider
292
+ */
293
+ hash?: HashProvider;
294
+ /**
295
+ * The number of retry attempts for failed commands.
296
+ * Set to 0 to disable retries.
297
+ * @default 0
298
+ */
299
+ retries?: number;
300
+ /**
301
+ * The base delay in milliseconds between retry attempts.
302
+ * @default 100
303
+ */
304
+ retryDelay?: number;
305
+ /**
306
+ * Function to calculate backoff delay between retries.
307
+ * Receives (attempt, baseDelay) and returns delay in ms.
308
+ * @default defaultRetryBackoff (fixed delay)
309
+ */
310
+ retryBackoff?: RetryBackoffFunction;
311
+ /**
312
+ * When true, retries are only performed for commands marked as idempotent.
313
+ * This prevents accidental double-execution of non-idempotent operations
314
+ * (like incr, decr, append) if the server applies the command but the
315
+ * client doesn't receive the response before a timeout/disconnect.
316
+ * @default true
317
+ */
318
+ retryOnlyIdempotent?: boolean;
319
+ /**
320
+ * SASL authentication credentials for all nodes.
321
+ * When provided, nodes will authenticate using SASL PLAIN mechanism
322
+ * before accepting commands.
323
+ */
324
+ sasl?: SASLCredentials;
325
+ /**
326
+ * AWS ElastiCache Auto Discovery configuration.
327
+ * When enabled, the client will periodically poll the configuration endpoint
328
+ * to detect cluster topology changes and automatically update the node list.
329
+ */
330
+ autoDiscover?: AutoDiscoverOptions;
331
+ }
332
+ interface MemcacheStats {
333
+ [key: string]: string;
334
+ }
335
+ /**
336
+ * Configuration for AWS ElastiCache Auto Discovery.
337
+ * When enabled, the client connects to a configuration endpoint and periodically
338
+ * polls for cluster topology changes, automatically adding/removing nodes.
339
+ */
340
+ interface AutoDiscoverOptions {
341
+ /**
342
+ * Enable auto discovery of cluster nodes.
343
+ */
344
+ enabled: boolean;
345
+ /**
346
+ * How often to poll for topology changes, in milliseconds.
347
+ * @default 60000
348
+ */
349
+ pollingInterval?: number;
350
+ /**
351
+ * The configuration endpoint to use for discovery.
352
+ * This is typically the .cfg endpoint from ElastiCache.
353
+ * If not specified, the first node in the nodes array will be used.
354
+ */
355
+ configEndpoint?: string;
356
+ /**
357
+ * Use the legacy `get AmazonElastiCache:cluster` command
358
+ * instead of `config get cluster` (for engine versions < 1.4.14).
359
+ * @default false
360
+ */
361
+ useLegacyCommand?: boolean;
362
+ }
363
+ /**
364
+ * Represents a discovered node from the ElastiCache cluster configuration.
365
+ */
366
+ interface DiscoveredNode {
367
+ /** The hostname of the node */
368
+ hostname: string;
369
+ /** The IP address of the node (may be empty string) */
370
+ ip: string;
371
+ /** The port number of the node */
372
+ port: number;
373
+ }
374
+ /**
375
+ * Represents the parsed result of an ElastiCache cluster config response.
376
+ */
377
+ interface ClusterConfig {
378
+ /** The config version number (increments on topology changes) */
379
+ version: number;
380
+ /** The list of discovered nodes */
381
+ nodes: DiscoveredNode[];
382
+ }
383
+ interface ExecuteOptions {
384
+ /** Command options passed to node.command() */
385
+ commandOptions?: CommandOptions;
386
+ /**
387
+ * Override the number of retries for this specific execution.
388
+ * If undefined, uses the instance-level retries setting.
389
+ */
390
+ retries?: number;
391
+ /**
392
+ * Override the retry delay for this specific execution.
393
+ * If undefined, uses the instance-level retryDelay setting.
394
+ */
395
+ retryDelay?: number;
396
+ /**
397
+ * Override the backoff function for this specific execution.
398
+ * If undefined, uses the instance-level retryBackoff setting.
399
+ */
400
+ retryBackoff?: RetryBackoffFunction;
401
+ /**
402
+ * Mark this command as idempotent, allowing retries even when
403
+ * retryOnlyIdempotent is true. Set this for read operations (get, gets)
404
+ * or operations that are safe to repeat (set with same value).
405
+ * @default false
406
+ */
407
+ idempotent?: boolean;
408
+ }
409
+
410
+ interface AutoDiscoveryOptions {
411
+ configEndpoint: string;
412
+ pollingInterval: number;
413
+ useLegacyCommand: boolean;
414
+ timeout: number;
415
+ keepAlive: boolean;
416
+ keepAliveDelay: number;
417
+ sasl?: SASLCredentials;
418
+ }
419
+ /**
420
+ * Handles AWS ElastiCache Auto Discovery for memcache clusters.
421
+ * Connects to a configuration endpoint, periodically polls for cluster
422
+ * topology changes, and emits events when nodes are added or removed.
423
+ */
424
+ declare class AutoDiscovery extends Hookified {
425
+ private _configEndpoint;
426
+ private _pollingInterval;
427
+ private _useLegacyCommand;
428
+ private _configVersion;
429
+ private _pollingTimer;
430
+ private _configNode;
431
+ private _timeout;
432
+ private _keepAlive;
433
+ private _keepAliveDelay;
434
+ private _sasl;
435
+ private _isRunning;
436
+ private _isPolling;
437
+ constructor(options: AutoDiscoveryOptions);
438
+ /** Current config version. -1 means no config has been fetched yet. */
439
+ get configVersion(): number;
440
+ /** Whether auto discovery is currently running. */
441
+ get isRunning(): boolean;
442
+ /** The configuration endpoint being used. */
443
+ get configEndpoint(): string;
444
+ /**
445
+ * Start the auto discovery process.
446
+ * Performs an initial discovery, then starts the polling timer.
447
+ */
448
+ start(): Promise<ClusterConfig>;
449
+ /**
450
+ * Stop the auto discovery process.
451
+ */
452
+ stop(): Promise<void>;
453
+ /**
454
+ * Perform a single discovery cycle.
455
+ * Returns the ClusterConfig if the version has changed, or undefined if unchanged.
456
+ */
457
+ discover(): Promise<ClusterConfig | undefined>;
458
+ /**
459
+ * Parse the raw response data from a config get cluster command.
460
+ * The raw data is the value content between the CONFIG/VALUE header and END.
461
+ * Format: "<version>\n<host1>|<ip1>|<port1> <host2>|<ip2>|<port2>\n"
462
+ */
463
+ static parseConfigResponse(rawData: string[]): ClusterConfig;
464
+ /**
465
+ * Parse a single node entry in the format "hostname|ip|port".
466
+ */
467
+ static parseNodeEntry(entry: string): DiscoveredNode;
468
+ /**
469
+ * Build a node ID from a DiscoveredNode.
470
+ * Prefers IP when available, falls back to hostname.
471
+ */
472
+ static nodeId(node: DiscoveredNode): string;
473
+ private ensureConfigNode;
474
+ private fetchConfig;
475
+ private poll;
476
+ private parseEndpoint;
477
+ }
478
+
479
+ /**
480
+ * A distribution hash implementation that sends every key to all nodes.
481
+ * Unlike KetamaHash or ModulaHash, this does not partition keys — every
482
+ * operation targets every node in the cluster.
483
+ *
484
+ * This is useful for replication scenarios where all nodes should hold
485
+ * the same data, or for broadcast operations like flush/delete.
486
+ *
487
+ * @example
488
+ * ```typescript
489
+ * const client = new Memcache({
490
+ * nodes: ['server1:11211', 'server2:11211'],
491
+ * hash: new BroadcastHash(),
492
+ * });
493
+ * // Every set/get/delete will hit all nodes
494
+ * ```
495
+ */
496
+ declare class BroadcastHash implements HashProvider {
497
+ /** The name of this distribution strategy */
498
+ readonly name = "broadcast";
499
+ /** Map of node IDs to MemcacheNode instances */
500
+ private nodeMap;
501
+ /** Cached array of nodes, rebuilt only on add/remove */
502
+ private nodeCache;
503
+ constructor();
504
+ /**
505
+ * Gets all nodes in the distribution.
506
+ * @returns Array of all MemcacheNode instances
507
+ */
508
+ get nodes(): Array<MemcacheNode>;
509
+ /**
510
+ * Adds a node to the distribution.
511
+ * @param node - The MemcacheNode to add
512
+ */
513
+ addNode(node: MemcacheNode): void;
514
+ /**
515
+ * Removes a node from the distribution by its ID.
516
+ * @param id - The node ID (e.g., "localhost:11211")
517
+ */
518
+ removeNode(id: string): void;
519
+ /**
520
+ * Gets a specific node by its ID.
521
+ * @param id - The node ID (e.g., "localhost:11211")
522
+ * @returns The MemcacheNode if found, undefined otherwise
523
+ */
524
+ getNode(id: string): MemcacheNode | undefined;
525
+ /**
526
+ * Returns all nodes regardless of key. Every operation is broadcast
527
+ * to every node in the cluster.
528
+ * @param _key - The cache key (ignored — all nodes are always returned)
529
+ * @returns Array of all MemcacheNode instances
530
+ */
531
+ getNodesByKey(_key: string): Array<MemcacheNode>;
532
+ /**
533
+ * Rebuilds the cached node array from the map.
534
+ */
535
+ private rebuildCache;
536
+ }
537
+
351
538
  /**
352
539
  * Function that returns an unsigned 32-bit hash of the input.
353
540
  */
@@ -482,6 +669,8 @@ declare class Memcache extends Hookified {
482
669
  private _retryBackoff;
483
670
  private _retryOnlyIdempotent;
484
671
  private _sasl;
672
+ private _autoDiscovery;
673
+ private _autoDiscoverOptions;
485
674
  constructor(options?: string | MemcacheOptions);
486
675
  /**
487
676
  * Get the list of nodes
@@ -862,6 +1051,8 @@ declare class Memcache extends Hookified {
862
1051
  * Forward events from a MemcacheNode to the Memcache instance
863
1052
  */
864
1053
  private forwardNodeEvents;
1054
+ private startAutoDiscovery;
1055
+ private applyClusterConfig;
865
1056
  }
866
1057
 
867
- export { type ExecuteOptions, type HashProvider, Memcache, MemcacheEvents, MemcacheNode, type MemcacheOptions, type MemcacheStats, ModulaHash, type RetryBackoffFunction, type SASLCredentials, createNode, Memcache as default, defaultRetryBackoff, exponentialRetryBackoff };
1058
+ export { type AutoDiscoverOptions, AutoDiscovery, BroadcastHash, type ClusterConfig, type DiscoveredNode, type ExecuteOptions, type HashProvider, Memcache, MemcacheEvents, MemcacheNode, type MemcacheOptions, type MemcacheStats, ModulaHash, type RetryBackoffFunction, type SASLCredentials, createNode, Memcache as default, defaultRetryBackoff, exponentialRetryBackoff };