memcache 0.3.0 → 1.1.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/LICENSE +21 -0
- package/README.md +447 -74
- package/dist/index.cjs +1509 -0
- package/dist/index.d.cts +501 -0
- package/dist/index.d.ts +501 -0
- package/dist/index.js +1482 -0
- package/package.json +49 -18
- package/.gitignore +0 -2
- package/Makefile +0 -13
- package/example.js +0 -68
- package/index.js +0 -1
- package/lib/memcache.js +0 -344
- package/test/test-memcache.js +0 -238
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Jared Wray
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,109 +1,482 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
[<img src="https://jaredwray.com/images/memcache.svg" alt="Memcache Logo" align="center">](https://memcachejs.org)
|
|
2
|
+
|
|
3
|
+
[](https://codecov.io/gh/jaredwray/memcache)
|
|
4
|
+
[](https://github.com/jaredwray/memcache/actions/workflows/tests.yaml)
|
|
5
|
+
[](https://www.npmjs.com/package/memcache)
|
|
6
|
+
[](https://www.npmjs.com/package/memcache)
|
|
7
|
+
[](https://github.com/jaredwray/memcache/blob/main/LICENSE)
|
|
8
|
+
|
|
9
|
+
# Memcache
|
|
10
|
+
Nodejs Memcache Client
|
|
11
|
+
|
|
12
|
+
# Table of Contents
|
|
13
|
+
|
|
14
|
+
- [Getting Started](#getting-started)
|
|
15
|
+
- [Installation](#installation)
|
|
16
|
+
- [Basic Usage](#basic-usage)
|
|
17
|
+
- [Custom Connection](#custom-connection)
|
|
18
|
+
- [API](#api)
|
|
19
|
+
- [Constructor](#constructor)
|
|
20
|
+
- [Properties](#properties)
|
|
21
|
+
- [Connection Management](#connection-management)
|
|
22
|
+
- [Node Management](#node-management)
|
|
23
|
+
- [Data Storage Operations](#data-storage-operations)
|
|
24
|
+
- [String Modification Operations](#string-modification-operations)
|
|
25
|
+
- [Deletion & Expiration](#deletion--expiration)
|
|
26
|
+
- [Numeric Operations](#numeric-operations)
|
|
27
|
+
- [Server Management & Statistics](#server-management--statistics)
|
|
28
|
+
- [Validation](#validation)
|
|
29
|
+
- [Helper Functions](#helper-functions)
|
|
30
|
+
- [Hooks and Events](#hooks-and-events)
|
|
31
|
+
- [Events](#events)
|
|
32
|
+
- [Available Events](#available-events)
|
|
33
|
+
- [Hooks](#hooks)
|
|
34
|
+
- [Available Hooks](#available-hooks)
|
|
35
|
+
- [get(key)](#getkey)
|
|
36
|
+
- [set(key, value, exptime?, flags?)](#setkey-value-exptime-flags)
|
|
37
|
+
- [gets(keys[])](#getskeys)
|
|
38
|
+
- [add(key, value, exptime?, flags?)](#addkey-value-exptime-flags)
|
|
39
|
+
- [replace(key, value, exptime?, flags?)](#replacekey-value-exptime-flags)
|
|
40
|
+
- [append(key, value)](#appendkey-value)
|
|
41
|
+
- [prepend(key, value)](#prependkey-value)
|
|
42
|
+
- [delete(key)](#deletekey)
|
|
43
|
+
- [incr(key, value?)](#incrkey-value)
|
|
44
|
+
- [decr(key, value?)](#decrkey-value)
|
|
45
|
+
- [touch(key, exptime)](#touchkey-exptime)
|
|
46
|
+
- [Hook Examples](#hook-examples)
|
|
47
|
+
- [Contributing](#contributing)
|
|
48
|
+
- [License and Copyright](#license-and-copyright)
|
|
49
|
+
|
|
50
|
+
# Getting Started
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npm install memcache
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
or with pnpm:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pnpm add memcache
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Basic Usage
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
import { Memcache } from 'memcache';
|
|
68
|
+
|
|
69
|
+
// Create a new client
|
|
70
|
+
const client = new Memcache();
|
|
71
|
+
|
|
72
|
+
// Set a value
|
|
73
|
+
await client.set('mykey', 'Hello, Memcache!');
|
|
74
|
+
|
|
75
|
+
// Get a value
|
|
76
|
+
const value = await client.get('mykey');
|
|
77
|
+
console.log(value); // ['Hello, Memcache!']
|
|
78
|
+
|
|
79
|
+
// Delete a value
|
|
80
|
+
await client.delete('mykey');
|
|
81
|
+
|
|
82
|
+
// Close the connection
|
|
83
|
+
await client.quit();
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
You can also just pass in the `uri` into the constructor
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// Single node as string
|
|
90
|
+
const client = new Memcache('localhost:11211');
|
|
91
|
+
|
|
92
|
+
// Single node with protocol
|
|
93
|
+
const client = new Memcache('memcache://192.168.1.100:11211');
|
|
94
|
+
|
|
95
|
+
// Multiple nodes with options
|
|
96
|
+
const client = new Memcache({
|
|
97
|
+
nodes: ['localhost:11211', 'server2:11211'],
|
|
98
|
+
timeout: 10000
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
You can specify multiple Memcache nodes by passing an array of connection strings:
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
import { Memcache } from 'memcache';
|
|
106
|
+
|
|
107
|
+
// Create a client with multiple nodes
|
|
108
|
+
const client = new Memcache({
|
|
109
|
+
nodes: ['localhost:11211', '192.168.1.100:11211', 'memcache://192.168.1.101:11211']
|
|
110
|
+
});
|
|
3
111
|
|
|
4
|
-
|
|
112
|
+
// Set and get values (automatically distributed across nodes)
|
|
113
|
+
await client.set('mykey', 'Hello, Memcache!');
|
|
114
|
+
const value = await client.get('mykey');
|
|
115
|
+
console.log(value); // ['Hello, Memcache!']
|
|
5
116
|
|
|
117
|
+
// Close the connection
|
|
118
|
+
await client.quit();
|
|
119
|
+
```
|
|
6
120
|
|
|
7
|
-
|
|
8
|
-
-----
|
|
121
|
+
You can also pass an array of MemcacheNode instances for advanced configuration:
|
|
9
122
|
|
|
10
|
-
|
|
11
|
-
|
|
123
|
+
```javascript
|
|
124
|
+
import { Memcache, createNode } from 'memcache';
|
|
12
125
|
|
|
13
|
-
|
|
14
|
-
|
|
126
|
+
// Create nodes with custom settings
|
|
127
|
+
const node1 = createNode('localhost', 11211, { weight: 2 });
|
|
128
|
+
const node2 = createNode('192.168.1.100', 11211, { weight: 1 });
|
|
129
|
+
const node3 = createNode('192.168.1.101', 11211, { weight: 1 });
|
|
15
130
|
|
|
131
|
+
// Create a client with MemcacheNode instances
|
|
132
|
+
const client = new Memcache({
|
|
133
|
+
nodes: [node1, node2, node3],
|
|
134
|
+
timeout: 10000
|
|
135
|
+
});
|
|
16
136
|
|
|
17
|
-
|
|
18
|
-
|
|
137
|
+
// node1 will receive twice as much traffic due to higher weight
|
|
138
|
+
await client.set('mykey', 'Hello, Memcache!');
|
|
139
|
+
const value = await client.get('mykey');
|
|
140
|
+
console.log(value); // ['Hello, Memcache!']
|
|
19
141
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
142
|
+
// Close the connection
|
|
143
|
+
await client.quit();
|
|
144
|
+
```
|
|
23
145
|
|
|
24
|
-
|
|
146
|
+
# API
|
|
25
147
|
|
|
26
|
-
|
|
27
|
-
client.port = 11211;
|
|
28
|
-
client.host = 'localhost';
|
|
148
|
+
## Constructor
|
|
29
149
|
|
|
30
|
-
|
|
150
|
+
```typescript
|
|
151
|
+
new Memcache(options?: string | MemcacheOptions)
|
|
152
|
+
```
|
|
31
153
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
154
|
+
Creates a new Memcache client instance. You can pass either:
|
|
155
|
+
- A **string** representing a single node URI (uses default settings)
|
|
156
|
+
- A **MemcacheOptions** object for custom configuration
|
|
35
157
|
|
|
36
|
-
|
|
37
|
-
// no arguments - connection has been closed
|
|
38
|
-
});
|
|
158
|
+
**Examples:**
|
|
39
159
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
160
|
+
```javascript
|
|
161
|
+
// Single node as string
|
|
162
|
+
const client = new Memcache('localhost:11211');
|
|
43
163
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// connect to the memcache server after subscribing to some or all of these events
|
|
49
|
-
client.connect()
|
|
164
|
+
// Single node with protocol
|
|
165
|
+
const client = new Memcache('memcache://192.168.1.100:11211');
|
|
50
166
|
|
|
51
|
-
|
|
167
|
+
// Multiple nodes with options
|
|
168
|
+
const client = new Memcache({
|
|
169
|
+
nodes: ['localhost:11211', 'server2:11211'],
|
|
170
|
+
timeout: 10000
|
|
171
|
+
});
|
|
172
|
+
```
|
|
52
173
|
|
|
53
|
-
|
|
174
|
+
### Options
|
|
54
175
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
176
|
+
- `nodes?: (string | MemcacheNode)[]` - Array of node URIs or MemcacheNode instances
|
|
177
|
+
- Examples: `["localhost:11211", "memcache://192.168.1.100:11212"]`
|
|
178
|
+
- `timeout?: number` - Operation timeout in milliseconds (default: 5000)
|
|
179
|
+
- `keepAlive?: boolean` - Keep connection alive (default: true)
|
|
180
|
+
- `keepAliveDelay?: number` - Keep alive delay in milliseconds (default: 1000)
|
|
181
|
+
- `hash?: HashProvider` - Hash provider for consistent hashing (default: KetamaHash)
|
|
58
182
|
|
|
59
|
-
|
|
183
|
+
## Properties
|
|
60
184
|
|
|
61
|
-
|
|
185
|
+
### `nodes: MemcacheNode[]` (readonly)
|
|
186
|
+
Returns the list of all MemcacheNode instances in the cluster.
|
|
62
187
|
|
|
63
|
-
|
|
64
|
-
|
|
188
|
+
### `nodeIds: string[]` (readonly)
|
|
189
|
+
Returns the list of node IDs (e.g., `["localhost:11211", "127.0.0.1:11212"]`).
|
|
65
190
|
|
|
66
|
-
|
|
191
|
+
### `hash: HashProvider`
|
|
192
|
+
Get or set the hash provider used for consistent hashing distribution.
|
|
67
193
|
|
|
68
|
-
|
|
194
|
+
### `timeout: number`
|
|
195
|
+
Get or set the timeout for operations in milliseconds (default: 5000).
|
|
69
196
|
|
|
70
|
-
|
|
71
|
-
|
|
197
|
+
### `keepAlive: boolean`
|
|
198
|
+
Get or set the keepAlive setting. Updates all existing nodes. Requires `reconnect()` to apply changes.
|
|
72
199
|
|
|
73
|
-
|
|
200
|
+
### `keepAliveDelay: number`
|
|
201
|
+
Get or set the keep alive delay in milliseconds. Updates all existing nodes. Requires `reconnect()` to apply changes.
|
|
74
202
|
|
|
75
|
-
|
|
76
|
-
});
|
|
203
|
+
## Connection Management
|
|
77
204
|
|
|
205
|
+
### `connect(nodeId?: string): Promise<void>`
|
|
206
|
+
Connect to all Memcache servers or a specific node.
|
|
78
207
|
|
|
79
|
-
|
|
208
|
+
### `disconnect(): Promise<void>`
|
|
209
|
+
Disconnect all connections.
|
|
80
210
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
client.set(key, value, callback, lifetime, flags);
|
|
84
|
-
client.add(key, value, callback, lifetime, flags);
|
|
85
|
-
client.replace(key, value, callback, lifetime, flags);
|
|
86
|
-
client.append(key, value, callback, lifetime, flags);
|
|
87
|
-
client.prepend(key, value, callback, lifetime, flags);
|
|
88
|
-
client.cas(key, value, unique, callback, lifetime, flags);
|
|
211
|
+
### `reconnect(): Promise<void>`
|
|
212
|
+
Reconnect all nodes by disconnecting and connecting them again.
|
|
89
213
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
client.increment('key', value, callback);
|
|
93
|
-
client.decrement('key', value, callback);
|
|
214
|
+
### `quit(): Promise<void>`
|
|
215
|
+
Quit all connections gracefully.
|
|
94
216
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
client.stats(callback);
|
|
98
|
-
client.stats('settings', callback);
|
|
99
|
-
client.stats('items', callback);
|
|
100
|
-
client.stats('mongeese', callback);
|
|
217
|
+
### `isConnected(): boolean`
|
|
218
|
+
Check if any node is connected to a Memcache server.
|
|
101
219
|
|
|
102
|
-
|
|
220
|
+
## Node Management
|
|
103
221
|
|
|
104
|
-
|
|
222
|
+
### `getNodes(): MemcacheNode[]`
|
|
223
|
+
Get an array of all MemcacheNode instances.
|
|
105
224
|
|
|
106
|
-
|
|
225
|
+
### `getNode(id: string): MemcacheNode | undefined`
|
|
226
|
+
Get a specific node by its ID (e.g., `"localhost:11211"`).
|
|
107
227
|
|
|
108
|
-
|
|
109
|
-
|
|
228
|
+
### `addNode(uri: string | MemcacheNode, weight?: number): Promise<void>`
|
|
229
|
+
Add a new node to the cluster. Throws error if node already exists.
|
|
230
|
+
|
|
231
|
+
### `removeNode(uri: string): Promise<void>`
|
|
232
|
+
Remove a node from the cluster.
|
|
233
|
+
|
|
234
|
+
### `getNodesByKey(key: string): Promise<MemcacheNode[]>`
|
|
235
|
+
Get the nodes for a given key using consistent hashing. Automatically connects to nodes if not already connected.
|
|
236
|
+
|
|
237
|
+
### `parseUri(uri: string): { host: string; port: number }`
|
|
238
|
+
Parse a URI string into host and port. Supports formats:
|
|
239
|
+
- Simple: `"localhost:11211"` or `"localhost"`
|
|
240
|
+
- Protocol: `"memcache://localhost:11211"`, `"tcp://localhost:11211"`
|
|
241
|
+
- IPv6: `"[::1]:11211"` or `"memcache://[2001:db8::1]:11212"`
|
|
242
|
+
- Unix socket: `"/var/run/memcached.sock"` or `"unix:///var/run/memcached.sock"`
|
|
243
|
+
|
|
244
|
+
## Data Storage Operations
|
|
245
|
+
|
|
246
|
+
### `get(key: string): Promise<string | undefined>`
|
|
247
|
+
Get a value from the Memcache server. Returns the first successful result from replica nodes.
|
|
248
|
+
|
|
249
|
+
### `gets(keys: string[]): Promise<Map<string, string>>`
|
|
250
|
+
Get multiple values from the Memcache server. Returns a Map with keys to values.
|
|
251
|
+
|
|
252
|
+
### `set(key: string, value: string, exptime?: number, flags?: number): Promise<boolean>`
|
|
253
|
+
Set a value in the Memcache server. Returns true only if all replica nodes succeed.
|
|
254
|
+
- `exptime` - Expiration time in seconds (default: 0 = never expire)
|
|
255
|
+
- `flags` - Flags/metadata (default: 0)
|
|
256
|
+
|
|
257
|
+
### `add(key: string, value: string, exptime?: number, flags?: number): Promise<boolean>`
|
|
258
|
+
Add a value (only if key doesn't exist). Returns true only if all replica nodes succeed.
|
|
259
|
+
|
|
260
|
+
### `replace(key: string, value: string, exptime?: number, flags?: number): Promise<boolean>`
|
|
261
|
+
Replace a value (only if key exists). Returns true only if all replica nodes succeed.
|
|
262
|
+
|
|
263
|
+
### `cas(key: string, value: string, casToken: string, exptime?: number, flags?: number): Promise<boolean>`
|
|
264
|
+
Check-And-Set: Store a value only if it hasn't been modified since last fetch. Returns true only if all replica nodes succeed.
|
|
265
|
+
|
|
266
|
+
## String Modification Operations
|
|
267
|
+
|
|
268
|
+
### `append(key: string, value: string): Promise<boolean>`
|
|
269
|
+
Append a value to an existing key. Returns true only if all replica nodes succeed.
|
|
270
|
+
|
|
271
|
+
### `prepend(key: string, value: string): Promise<boolean>`
|
|
272
|
+
Prepend a value to an existing key. Returns true only if all replica nodes succeed.
|
|
273
|
+
|
|
274
|
+
## Deletion & Expiration
|
|
275
|
+
|
|
276
|
+
### `delete(key: string): Promise<boolean>`
|
|
277
|
+
Delete a value from the Memcache server. Returns true only if all replica nodes succeed.
|
|
278
|
+
|
|
279
|
+
### `touch(key: string, exptime: number): Promise<boolean>`
|
|
280
|
+
Update expiration time without retrieving value. Returns true only if all replica nodes succeed.
|
|
281
|
+
|
|
282
|
+
## Numeric Operations
|
|
283
|
+
|
|
284
|
+
### `incr(key: string, value?: number): Promise<number | undefined>`
|
|
285
|
+
Increment a value. Returns the new value or undefined on failure.
|
|
286
|
+
- `value` - Amount to increment (default: 1)
|
|
287
|
+
|
|
288
|
+
### `decr(key: string, value?: number): Promise<number | undefined>`
|
|
289
|
+
Decrement a value. Returns the new value or undefined on failure.
|
|
290
|
+
- `value` - Amount to decrement (default: 1)
|
|
291
|
+
|
|
292
|
+
## Server Management & Statistics
|
|
293
|
+
|
|
294
|
+
### `flush(delay?: number): Promise<boolean>`
|
|
295
|
+
Flush all values from all Memcache servers. Returns true if all nodes successfully flushed.
|
|
296
|
+
- `delay` - Optional delay in seconds before flushing
|
|
297
|
+
|
|
298
|
+
### `stats(type?: string): Promise<Map<string, MemcacheStats>>`
|
|
299
|
+
Get statistics from all Memcache servers. Returns a Map of node IDs to their stats.
|
|
300
|
+
|
|
301
|
+
### `version(): Promise<Map<string, string>>`
|
|
302
|
+
Get the Memcache server version from all nodes. Returns a Map of node IDs to version strings.
|
|
303
|
+
|
|
304
|
+
## Validation
|
|
305
|
+
|
|
306
|
+
### `validateKey(key: string): void`
|
|
307
|
+
Validates a Memcache key according to protocol requirements. Throws error if:
|
|
308
|
+
- Key is empty
|
|
309
|
+
- Key exceeds 250 characters
|
|
310
|
+
- Key contains spaces, newlines, or null characters
|
|
311
|
+
|
|
312
|
+
## Helper Functions
|
|
313
|
+
|
|
314
|
+
### `createNode(host: string, port: number, options?: MemcacheNodeOptions): MemcacheNode`
|
|
315
|
+
Factory function to create a new MemcacheNode instance.
|
|
316
|
+
|
|
317
|
+
```javascript
|
|
318
|
+
import { createNode } from 'memcache';
|
|
319
|
+
|
|
320
|
+
const node = createNode('localhost', 11211, {
|
|
321
|
+
timeout: 5000,
|
|
322
|
+
keepAlive: true,
|
|
323
|
+
weight: 1
|
|
324
|
+
});
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
# Hooks and Events
|
|
328
|
+
|
|
329
|
+
The Memcache client extends [Hookified](https://github.com/jaredwray/hookified) to provide powerful hooks and events for monitoring and customizing behavior.
|
|
330
|
+
|
|
331
|
+
## Events
|
|
332
|
+
|
|
333
|
+
The client emits various events during operations that you can listen to:
|
|
334
|
+
|
|
335
|
+
```javascript
|
|
336
|
+
const client = new Memcache();
|
|
337
|
+
|
|
338
|
+
// Connection events
|
|
339
|
+
client.on('connect', () => {
|
|
340
|
+
console.log('Connected to Memcache server');
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
client.on('close', () => {
|
|
344
|
+
console.log('Connection closed');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
client.on('error', (error) => {
|
|
348
|
+
console.error('Error:', error);
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
client.on('timeout', () => {
|
|
352
|
+
console.log('Connection timeout');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// Cache hit/miss events
|
|
356
|
+
client.on('hit', (key, value) => {
|
|
357
|
+
console.log(`Cache hit for key: ${key}`);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
client.on('miss', (key) => {
|
|
361
|
+
console.log(`Cache miss for key: ${key}`);
|
|
362
|
+
});
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
## Available Events
|
|
366
|
+
|
|
367
|
+
- `connect` - Emitted when connection to Memcache server is established
|
|
368
|
+
- `close` - Emitted when connection is closed
|
|
369
|
+
- `error` - Emitted when an error occurs
|
|
370
|
+
- `timeout` - Emitted when a connection timeout occurs
|
|
371
|
+
- `hit` - Emitted when a key is found in cache (includes key and value)
|
|
372
|
+
- `miss` - Emitted when a key is not found in cache
|
|
373
|
+
- `quit` - Emitted when quit command is sent
|
|
374
|
+
- `warn` - Emitted for warning messages
|
|
375
|
+
- `info` - Emitted for informational messages
|
|
376
|
+
|
|
377
|
+
## Hooks
|
|
378
|
+
|
|
379
|
+
Hooks allow you to intercept and modify behavior before and after operations. Every operation supports `before` and `after` hooks.
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
const client = new Memcache();
|
|
383
|
+
|
|
384
|
+
// Add a before hook for get operations
|
|
385
|
+
client.onHook('before:get', async ({ key }) => {
|
|
386
|
+
console.log(`Getting key: ${key}`);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
// Add an after hook for set operations
|
|
390
|
+
client.onHook('after:set', async ({ key, value, success }) => {
|
|
391
|
+
if (success) {
|
|
392
|
+
console.log(`Successfully set ${key}`);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
// Hooks can be async and modify behavior
|
|
397
|
+
client.onHook('before:set', async ({ key, value }) => {
|
|
398
|
+
console.log(`About to set ${key} = ${value}`);
|
|
399
|
+
// Perform validation, logging, etc.
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Available Hooks
|
|
404
|
+
|
|
405
|
+
All operations support before and after hooks with specific parameters:
|
|
406
|
+
|
|
407
|
+
## get(key)
|
|
408
|
+
- `before:get` - `{ key }`
|
|
409
|
+
- `after:get` - `{ key, value }` (value is array or undefined)
|
|
410
|
+
|
|
411
|
+
## set(key, value, exptime?, flags?)
|
|
412
|
+
- `before:set` - `{ key, value, exptime, flags }`
|
|
413
|
+
- `after:set` - `{ key, value, exptime, flags, success }`
|
|
414
|
+
|
|
415
|
+
## gets(keys[])
|
|
416
|
+
- `before:gets` - `{ keys }`
|
|
417
|
+
- `after:gets` - `{ keys, values }` (values is a Map)
|
|
418
|
+
|
|
419
|
+
## add(key, value, exptime?, flags?)
|
|
420
|
+
- `before:add` - `{ key, value, exptime, flags }`
|
|
421
|
+
- `after:add` - `{ key, value, exptime, flags, success }`
|
|
422
|
+
|
|
423
|
+
## replace(key, value, exptime?, flags?)
|
|
424
|
+
- `before:replace` - `{ key, value, exptime, flags }`
|
|
425
|
+
- `after:replace` - `{ key, value, exptime, flags, success }`
|
|
426
|
+
|
|
427
|
+
## append(key, value)
|
|
428
|
+
- `before:append` - `{ key, value }`
|
|
429
|
+
- `after:append` - `{ key, value, success }`
|
|
430
|
+
|
|
431
|
+
## prepend(key, value)
|
|
432
|
+
- `before:prepend` - `{ key, value }`
|
|
433
|
+
- `after:prepend` - `{ key, value, success }`
|
|
434
|
+
|
|
435
|
+
## delete(key)
|
|
436
|
+
- `before:delete` - `{ key }`
|
|
437
|
+
- `after:delete` - `{ key, success }`
|
|
438
|
+
|
|
439
|
+
## incr(key, value?)
|
|
440
|
+
- `before:incr` - `{ key, value }`
|
|
441
|
+
- `after:incr` - `{ key, value, newValue }`
|
|
442
|
+
|
|
443
|
+
## decr(key, value?)
|
|
444
|
+
- `before:decr` - `{ key, value }`
|
|
445
|
+
- `after:decr` - `{ key, value, newValue }`
|
|
446
|
+
|
|
447
|
+
## touch(key, exptime)
|
|
448
|
+
- `before:touch` - `{ key, exptime }`
|
|
449
|
+
- `after:touch` - `{ key, exptime, success }`
|
|
450
|
+
|
|
451
|
+
## Hook Examples
|
|
452
|
+
|
|
453
|
+
```javascript
|
|
454
|
+
const client = new Memcache();
|
|
455
|
+
|
|
456
|
+
// Log all get operations
|
|
457
|
+
client.onHook('before:get', async ({ key }) => {
|
|
458
|
+
console.log(`[GET] Fetching key: ${key}`);
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
client.onHook('after:get', async ({ key, value }) => {
|
|
462
|
+
console.log(`[GET] Key: ${key}, Found: ${value !== undefined}`);
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
// Log all set operations with timing
|
|
466
|
+
client.onHook('before:set', async (context) => {
|
|
467
|
+
context.startTime = Date.now();
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
client.onHook('after:set', async (context) => {
|
|
471
|
+
const duration = Date.now() - context.startTime;
|
|
472
|
+
console.log(`[SET] Key: ${context.key}, Success: ${context.success}, Time: ${duration}ms`);
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
# Contributing
|
|
477
|
+
|
|
478
|
+
Please read our [Contributing Guidelines](./CONTRIBUTING.md) and also our [Code of Conduct](./CODE_OF_CONDUCT.md).
|
|
479
|
+
|
|
480
|
+
# License and Copyright
|
|
481
|
+
|
|
482
|
+
[MIT & Copyright (c) Jared Wray](https://github.com/jaredwray/memcache/blob/main/LICENSE)
|