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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [<img src="https://jaredwray.com/images/memcache.svg" alt="Memcache Logo" align="center">](https://memcachejs.org)
1
+ [<img src="https://jaredwray.com/images/memcache.svg" width="80%" height="80%" align="center" alt="Memcache Logo" align="center">](https://memcachejs.org)
2
2
 
3
3
  [![codecov](https://codecov.io/gh/jaredwray/memcache/graph/badge.svg?token=4DUANNWiIE)](https://codecov.io/gh/jaredwray/memcache)
4
4
  [![tests](https://github.com/jaredwray/memcache/actions/workflows/tests.yaml/badge.svg)](https://github.com/jaredwray/memcache/actions/workflows/tests.yaml)
@@ -14,7 +14,6 @@ Nodejs Memcache Client
14
14
  - [Getting Started](#getting-started)
15
15
  - [Installation](#installation)
16
16
  - [Basic Usage](#basic-usage)
17
- - [Custom Connection](#custom-connection)
18
17
  - [API](#api)
19
18
  - [Constructor](#constructor)
20
19
  - [Properties](#properties)
@@ -47,6 +46,7 @@ Nodejs Memcache Client
47
46
  - [Distribution Algorithms](#distribution-algorithms)
48
47
  - [KetamaHash (Default)](#ketamahash-default)
49
48
  - [ModulaHash](#modulahash)
49
+ - [BroadcastHash](#broadcasthash)
50
50
  - [Choosing an Algorithm](#choosing-an-algorithm)
51
51
  - [Retry Configuration](#retry-configuration)
52
52
  - [Basic Retry Setup](#basic-retry-setup)
@@ -59,6 +59,13 @@ Nodejs Memcache Client
59
59
  - [Per-Node SASL Configuration](#per-node-sasl-configuration)
60
60
  - [Authentication Events](#authentication-events)
61
61
  - [Server Configuration](#server-configuration)
62
+ - [Auto Discovery](#auto-discovery)
63
+ - [Enabling Auto Discovery](#enabling-auto-discovery)
64
+ - [Auto Discovery Options](#auto-discovery-options)
65
+ - [Auto Discovery Events](#auto-discovery-events)
66
+ - [Legacy Command Support](#legacy-command-support)
67
+ - [IPv6 Support](#ipv6-support)
68
+ - [Benchmarks](#benchmarks)
62
69
  - [Contributing](#contributing)
63
70
  - [License and Copyright](#license-and-copyright)
64
71
 
@@ -198,6 +205,7 @@ const client = new Memcache({
198
205
  - `retryDelay?: number` - Base delay in milliseconds between retries (default: 100)
199
206
  - `retryBackoff?: RetryBackoffFunction` - Function to calculate backoff delay (default: fixed delay)
200
207
  - `retryOnlyIdempotent?: boolean` - Only retry commands marked as idempotent (default: true)
208
+ - `autoDiscover?: AutoDiscoverOptions` - AWS ElastiCache Auto Discovery configuration (see [Auto Discovery](#auto-discovery))
201
209
 
202
210
  ## Properties
203
211
 
@@ -404,6 +412,9 @@ client.on('miss', (key) => {
404
412
  - `quit` - Emitted when quit command is sent
405
413
  - `warn` - Emitted for warning messages
406
414
  - `info` - Emitted for informational messages
415
+ - `autoDiscover` - Emitted on initial auto discovery with the cluster config
416
+ - `autoDiscoverUpdate` - Emitted when auto discovery detects a topology change
417
+ - `autoDiscoverError` - Emitted when auto discovery encounters an error
407
418
 
408
419
  ## Hooks
409
420
 
@@ -573,15 +584,39 @@ const client = new Memcache({
573
584
  // server2 will receive approximately 25% of keys
574
585
  ```
575
586
 
587
+ ## BroadcastHash
588
+
589
+ BroadcastHash sends every operation to all nodes in the cluster. Instead of partitioning keys across nodes, every `getNodesByKey()` call returns all nodes, so reads and writes are broadcast to every server.
590
+
591
+ ```javascript
592
+ import { Memcache, BroadcastHash } from 'memcache';
593
+
594
+ // Use BroadcastHash for full replication
595
+ const client = new Memcache({
596
+ nodes: ['server1:11211', 'server2:11211', 'server3:11211'],
597
+ hash: new BroadcastHash()
598
+ });
599
+
600
+ // Every set/get/delete hits all three nodes
601
+ await client.set('mykey', 'Hello!');
602
+ ```
603
+
604
+ **Characteristics:**
605
+ - Every operation targets all nodes
606
+ - No key partitioning — all nodes hold the same data
607
+ - Reads return the first successful result from any node
608
+ - Writes succeed only if all nodes succeed
609
+ - Best for replication, broadcast invalidation, or small clusters where all nodes should be in sync
610
+
576
611
  ## Choosing an Algorithm
577
612
 
578
- | Feature | KetamaHash | ModulaHash |
579
- |---------|------------|------------|
580
- | Key redistribution on node change | Minimal (~1/n keys) | All keys may move |
581
- | Complexity | Higher (virtual nodes) | Lower (simple modulo) |
582
- | Performance | Slightly slower | Faster |
583
- | Best for | Dynamic scaling | Fixed clusters |
584
- | Weighted nodes | Yes | Yes |
613
+ | Feature | KetamaHash | ModulaHash | BroadcastHash |
614
+ |---------|------------|------------|---------------|
615
+ | Key redistribution on node change | Minimal (~1/n keys) | All keys may move | N/A (all nodes always) |
616
+ | Complexity | Higher (virtual nodes) | Lower (simple modulo) | Simplest |
617
+ | Performance | Slightly slower | Faster | Depends on node count |
618
+ | Best for | Dynamic scaling | Fixed clusters | Replication |
619
+ | Weighted nodes | Yes | Yes | No |
585
620
 
586
621
  **Use KetamaHash (default) when:**
587
622
  - Your cluster size may change dynamically
@@ -593,6 +628,11 @@ const client = new Memcache({
593
628
  - You prefer simplicity over minimal redistribution
594
629
  - You're in a testing or development environment
595
630
 
631
+ **Use BroadcastHash when:**
632
+ - You want all nodes to hold the same data
633
+ - You need broadcast cache invalidation across all nodes
634
+ - You're running a small cluster where replication is more important than partitioning
635
+
596
636
  # Retry Configuration
597
637
 
598
638
  The Memcache client supports automatic retry of failed commands with configurable backoff strategies.
@@ -877,6 +917,158 @@ To use SASL authentication, your memcached server must be configured with SASL s
877
917
 
878
918
  For more details, see the [memcached SASL documentation](https://github.com/memcached/memcached/wiki/SASLHowto).
879
919
 
920
+ # Auto Discovery
921
+
922
+ The Memcache client supports AWS ElastiCache Auto Discovery, which automatically detects cluster topology changes and adds or removes nodes as needed. When enabled, the client connects to a configuration endpoint, retrieves the current list of cache nodes, and periodically polls for changes.
923
+
924
+ ## Enabling Auto Discovery
925
+
926
+ ```javascript
927
+ import { Memcache } from 'memcache';
928
+
929
+ const client = new Memcache({
930
+ nodes: [],
931
+ autoDiscover: {
932
+ enabled: true,
933
+ configEndpoint: 'my-cluster.cfg.use1.cache.amazonaws.com:11211',
934
+ },
935
+ });
936
+
937
+ await client.connect();
938
+ // The client automatically discovers and connects to all cluster nodes
939
+ ```
940
+
941
+ If you omit `configEndpoint`, the first node in the `nodes` array is used as the configuration endpoint:
942
+
943
+ ```javascript
944
+ const client = new Memcache({
945
+ nodes: ['my-cluster.cfg.use1.cache.amazonaws.com:11211'],
946
+ autoDiscover: {
947
+ enabled: true,
948
+ },
949
+ });
950
+ ```
951
+
952
+ ## Auto Discovery Options
953
+
954
+ The `autoDiscover` option accepts an object with the following properties:
955
+
956
+ - `enabled: boolean` - Enable auto discovery of cluster nodes (required)
957
+ - `pollingInterval?: number` - How often to poll for topology changes, in milliseconds (default: 60000)
958
+ - `configEndpoint?: string` - The configuration endpoint to use for discovery. This is typically the `.cfg` endpoint from ElastiCache. If not specified, the first node in the `nodes` array will be used
959
+ - `useLegacyCommand?: boolean` - Use the legacy `get AmazonElastiCache:cluster` command instead of `config get cluster` (default: false)
960
+
961
+ ## Auto Discovery Events
962
+
963
+ The client emits events during the auto discovery lifecycle:
964
+
965
+ ```javascript
966
+ const client = new Memcache({
967
+ nodes: [],
968
+ autoDiscover: {
969
+ enabled: true,
970
+ configEndpoint: 'my-cluster.cfg.use1.cache.amazonaws.com:11211',
971
+ },
972
+ });
973
+
974
+ // Emitted on initial discovery with the full cluster config
975
+ client.on('autoDiscover', (config) => {
976
+ console.log('Discovered nodes:', config.nodes);
977
+ console.log('Config version:', config.version);
978
+ });
979
+
980
+ // Emitted when polling detects a topology change
981
+ client.on('autoDiscoverUpdate', (config) => {
982
+ console.log('Cluster topology changed:', config.nodes);
983
+ });
984
+
985
+ // Emitted when discovery encounters an error (non-fatal, retries on next poll)
986
+ client.on('autoDiscoverError', (error) => {
987
+ console.error('Discovery error:', error.message);
988
+ });
989
+
990
+ await client.connect();
991
+ ```
992
+
993
+ ## Legacy Command Support
994
+
995
+ For ElastiCache engine versions older than 1.4.14, use the legacy discovery command:
996
+
997
+ ```javascript
998
+ const client = new Memcache({
999
+ nodes: [],
1000
+ autoDiscover: {
1001
+ enabled: true,
1002
+ configEndpoint: 'my-cluster.cfg.use1.cache.amazonaws.com:11211',
1003
+ useLegacyCommand: true, // Uses 'get AmazonElastiCache:cluster' instead of 'config get cluster'
1004
+ },
1005
+ });
1006
+ ```
1007
+
1008
+ # IPv6 Support
1009
+
1010
+ The Memcache client fully supports IPv6 addresses using standard bracket notation in URIs.
1011
+
1012
+ ## Connecting to IPv6 Nodes
1013
+
1014
+ ```javascript
1015
+ import { Memcache } from 'memcache';
1016
+
1017
+ // IPv6 loopback
1018
+ const client = new Memcache('[::1]:11211');
1019
+
1020
+ // Multiple IPv6 nodes
1021
+ const client = new Memcache({
1022
+ nodes: [
1023
+ '[::1]:11211',
1024
+ '[2001:db8::1]:11211',
1025
+ 'memcache://[2001:db8::2]:11212',
1026
+ ],
1027
+ });
1028
+
1029
+ await client.connect();
1030
+ ```
1031
+
1032
+ ## IPv6 in Auto Discovery
1033
+
1034
+ When auto discovery returns IPv6 node addresses, the client automatically brackets them for correct URI handling:
1035
+
1036
+ ```javascript
1037
+ const client = new Memcache({
1038
+ nodes: [],
1039
+ autoDiscover: {
1040
+ enabled: true,
1041
+ configEndpoint: '[2001:db8::1]:11211',
1042
+ },
1043
+ });
1044
+
1045
+ await client.connect();
1046
+ // Discovered IPv6 nodes are added as [host]:port automatically
1047
+ ```
1048
+
1049
+ ## IPv6 Node IDs
1050
+
1051
+ Node IDs for IPv6 addresses use bracket notation to avoid ambiguity:
1052
+
1053
+ ```javascript
1054
+ const client = new Memcache({
1055
+ nodes: ['[::1]:11211', '[2001:db8::1]:11212'],
1056
+ });
1057
+
1058
+ console.log(client.nodeIds);
1059
+ // ['[::1]:11211', '[2001:db8::1]:11212']
1060
+ ```
1061
+
1062
+ # Benchmarks
1063
+
1064
+ These are provided to show a simple benchmark against current libraries. This is not robust but it is something we update regularly to make sure we are keeping performant.
1065
+
1066
+ | name | summary | ops/sec | time/op | margin | samples |
1067
+ |------------------------------|:---------:|----------:|----------:|:--------:|----------:|
1068
+ | memcache set/get (v1.4.0) | 🥇 | 3K | 350µs | ±0.19% | 10K |
1069
+ | memcached set/get (v2.2.2) | -2.9% | 3K | 361µs | ±0.16% | 10K |
1070
+ | memjs set/get (v1.3.2) | -12% | 3K | 398µs | ±0.17% | 10K |
1071
+
880
1072
  # Contributing
881
1073
 
882
1074
  Please read our [Contributing Guidelines](./CONTRIBUTING.md) and also our [Code of Conduct](./CODE_OF_CONDUCT.md).