memx 0.0.1
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.md +211 -0
- package/NOTICE.md +13 -0
- package/README.md +1 -0
- package/dist/index.js +1147 -0
- package/dist/index.js.map +6 -0
- package/dist/index.mjs +1124 -0
- package/dist/index.mjs.map +6 -0
- package/index.d.ts +623 -0
- package/package.json +48 -0
- package/src/buffers.ts +27 -0
- package/src/client.ts +228 -0
- package/src/cluster.ts +139 -0
- package/src/connection.ts +191 -0
- package/src/constants.ts +103 -0
- package/src/decode.ts +95 -0
- package/src/encode.ts +81 -0
- package/src/index.ts +16 -0
- package/src/internals.ts +41 -0
- package/src/server.ts +489 -0
- package/src/types.ts +263 -0
package/src/server.ts
ADDED
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
import { Adapter, Counter, AdapterResult, Stats } from './types'
|
|
2
|
+
import { Connection, ConnectionOptions } from './connection'
|
|
3
|
+
import { BUFFERS, OPCODE, STATUS } from './constants'
|
|
4
|
+
import { RawIncomingPacket } from './decode'
|
|
5
|
+
|
|
6
|
+
const statsBigInt: readonly string[] = [
|
|
7
|
+
'auth_cmds', 'auth_errors', 'bytes', 'bytes_read', 'bytes_written', 'cas_badval', 'cas_hits', 'cas_misses',
|
|
8
|
+
'cmd_flush', 'cmd_get', 'cmd_set', 'cmd_touch', 'conn_yields', 'crawler_items_checked', 'crawler_reclaimed',
|
|
9
|
+
'curr_items', 'decr_hits', 'decr_misses', 'delete_hits', 'delete_misses', 'direct_reclaims', 'evicted_active',
|
|
10
|
+
'evicted_unfetched', 'evictions', 'expired_unfetched', 'get_expired', 'get_flushed', 'get_hits', 'get_misses',
|
|
11
|
+
'hash_bytes', 'idle_kicks', 'incr_hits', 'incr_misses', 'limit_maxbytes', 'listen_disabled_num', 'log_watcher_sent',
|
|
12
|
+
'log_watcher_skipped', 'log_watchers', 'log_worker_dropped', 'log_worker_written', 'lru_crawler_running',
|
|
13
|
+
'lru_crawler_starts', 'lru_maintainer_juggles', 'lrutail_reflocked', 'malloc_fails', 'moves_to_cold',
|
|
14
|
+
'moves_to_warm', 'moves_within_lru', 'read_buf_bytes', 'read_buf_bytes_free', 'read_buf_count', 'read_buf_oom',
|
|
15
|
+
'reclaimed', 'rejected_connections', 'response_obj_bytes', 'response_obj_count', 'response_obj_oom',
|
|
16
|
+
'round_robin_fallback', 'slab_reassign_busy_deletes', 'slab_reassign_busy_items', 'slab_reassign_chunk_rescues',
|
|
17
|
+
'slab_reassign_evictions_nomem', 'slab_reassign_inline_reclaim', 'slab_reassign_rescues', 'slabs_moved',
|
|
18
|
+
'store_no_memory', 'store_too_large', 'time_in_listen_disabled_us', 'total_items', 'touch_hits', 'touch_misses',
|
|
19
|
+
'unexpected_napi_ids',
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
const statsNumber: readonly string[] = [
|
|
23
|
+
'connection_structures', 'curr_connections', 'hash_power_level', 'max_connections', 'pid', 'pointer_size',
|
|
24
|
+
'reserved_fds', 'slab_global_page_pool', 'threads', 'time', 'total_connections', 'uptime',
|
|
25
|
+
] as const
|
|
26
|
+
|
|
27
|
+
const statsBoolean: readonly string[] = [ 'accepting_conns', 'hash_is_expanding', 'slab_reassign_running' ] as const
|
|
28
|
+
|
|
29
|
+
const statsMicroseconds: readonly string[] = [ 'rusage_system', 'rusage_user' ] as const
|
|
30
|
+
|
|
31
|
+
function injectStats(key: string, value: string, stats: any): Stats {
|
|
32
|
+
if (! key) return stats
|
|
33
|
+
|
|
34
|
+
if (statsBigInt.includes(key)) {
|
|
35
|
+
stats[key] = BigInt(value)
|
|
36
|
+
} else if (statsNumber.includes(key)) {
|
|
37
|
+
stats[key] = Number(value)
|
|
38
|
+
} else if (statsBoolean.includes(key)) {
|
|
39
|
+
stats[key] = !! Number(value)
|
|
40
|
+
} else if (statsMicroseconds.includes(key)) {
|
|
41
|
+
const splits = value.split('.')
|
|
42
|
+
stats[key] = BigInt(`${splits[0]}${splits[1].padEnd(6, '0')}`)
|
|
43
|
+
} else {
|
|
44
|
+
stats[key] = value
|
|
45
|
+
}
|
|
46
|
+
return stats
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
function fail(packet: RawIncomingPacket, key?: string): never {
|
|
51
|
+
const message = packet.value.toString('utf-8') || 'Unknown Error'
|
|
52
|
+
const status = STATUS[packet.status] || `0x${packet.status.toString(16).padStart(4, '0')}`
|
|
53
|
+
throw new Error(`${message} (status=${status}${key ? `, key=${key}` : ''})`)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ServerOptions extends ConnectionOptions {
|
|
57
|
+
ttl?: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export class ServerAdapter implements Adapter {
|
|
61
|
+
#buffer = Buffer.alloc(BUFFERS.KEY_TOO_BIG + 20) // 20 is the max extras we'll write
|
|
62
|
+
|
|
63
|
+
#connection!: Connection
|
|
64
|
+
#ttl!: number
|
|
65
|
+
|
|
66
|
+
readonly #id!: string
|
|
67
|
+
|
|
68
|
+
constructor(options: ServerOptions) {
|
|
69
|
+
this.#connection = new Connection(options)
|
|
70
|
+
this.#ttl = options.ttl || 0 // never
|
|
71
|
+
this.#id = `${this.#connection.host}:${this.#connection.port}`
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ======================================================================== */
|
|
75
|
+
|
|
76
|
+
get connected(): boolean {
|
|
77
|
+
return this.#connection.connected
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get host(): string {
|
|
81
|
+
return this.#connection.host
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get port(): number {
|
|
85
|
+
return this.#connection.port
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
get timeout(): number {
|
|
89
|
+
return this.#connection.timeout
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
get ttl(): number {
|
|
93
|
+
return this.#ttl
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
get id(): string {
|
|
97
|
+
return this.#id
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* ======================================================================== */
|
|
101
|
+
|
|
102
|
+
#writeKey(key: string, offset: number = 0): number {
|
|
103
|
+
const keyLength = this.#buffer.write(key, offset, BUFFERS.KEY_TOO_BIG, 'utf-8')
|
|
104
|
+
if (keyLength > BUFFERS.KEY_SIZE) throw new Error(`Key too long (len=${keyLength})`)
|
|
105
|
+
return keyLength
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* ======================================================================== */
|
|
109
|
+
|
|
110
|
+
async get(
|
|
111
|
+
key: string,
|
|
112
|
+
options: { ttl?: number } = {},
|
|
113
|
+
): Promise<AdapterResult | void> {
|
|
114
|
+
const { ttl } = options
|
|
115
|
+
|
|
116
|
+
let keyOffset = 0
|
|
117
|
+
if (ttl) keyOffset = this.#buffer.writeUInt32BE(ttl)
|
|
118
|
+
const keyLength = this.#writeKey(key, keyOffset)
|
|
119
|
+
|
|
120
|
+
const [ response ] = await this.#connection.send({
|
|
121
|
+
opcode: ttl ? OPCODE.GAT : OPCODE.GET,
|
|
122
|
+
extras: this.#buffer,
|
|
123
|
+
extrasOffset: 0,
|
|
124
|
+
extrasLength: keyOffset,
|
|
125
|
+
key: this.#buffer,
|
|
126
|
+
keyOffset,
|
|
127
|
+
keyLength,
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
switch (response.status) {
|
|
131
|
+
case STATUS.OK:
|
|
132
|
+
return {
|
|
133
|
+
value: response.value,
|
|
134
|
+
flags: response.extras.readUInt32BE(),
|
|
135
|
+
cas: response.cas,
|
|
136
|
+
recycle: () => response.recycle(),
|
|
137
|
+
}
|
|
138
|
+
case STATUS.KEY_NOT_FOUND:
|
|
139
|
+
return
|
|
140
|
+
default:
|
|
141
|
+
fail(response, key)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
async touch(
|
|
146
|
+
key: string,
|
|
147
|
+
options: { ttl?: number } = {},
|
|
148
|
+
): Promise<boolean> {
|
|
149
|
+
const { ttl = this.#ttl } = options
|
|
150
|
+
|
|
151
|
+
const keyOffset = this.#buffer.writeUInt32BE(ttl)
|
|
152
|
+
const keyLength = this.#writeKey(key, keyOffset)
|
|
153
|
+
|
|
154
|
+
const [ response ] = await this.#connection.send({
|
|
155
|
+
opcode: OPCODE.TOUCH,
|
|
156
|
+
extras: this.#buffer,
|
|
157
|
+
extrasOffset: 0,
|
|
158
|
+
extrasLength: keyOffset,
|
|
159
|
+
key: this.#buffer,
|
|
160
|
+
keyOffset,
|
|
161
|
+
keyLength,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
switch (response.status) {
|
|
166
|
+
case STATUS.OK:
|
|
167
|
+
return true
|
|
168
|
+
case STATUS.KEY_NOT_FOUND:
|
|
169
|
+
return false
|
|
170
|
+
default:
|
|
171
|
+
fail(response, key)
|
|
172
|
+
}
|
|
173
|
+
} finally {
|
|
174
|
+
response.recycle()
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/* ======================================================================== */
|
|
179
|
+
|
|
180
|
+
async #sar(
|
|
181
|
+
opcode: OPCODE.SET | OPCODE.ADD | OPCODE.REPLACE,
|
|
182
|
+
key: string,
|
|
183
|
+
value: Buffer,
|
|
184
|
+
options: { flags?: number, cas?: bigint, ttl?: number },
|
|
185
|
+
): Promise<bigint | void> {
|
|
186
|
+
const { flags = 0, cas = 0n, ttl = this.#ttl } = options
|
|
187
|
+
|
|
188
|
+
let keyOffset: number
|
|
189
|
+
keyOffset = this.#buffer.writeUInt32BE(flags)
|
|
190
|
+
keyOffset = this.#buffer.writeUInt32BE(ttl, keyOffset)
|
|
191
|
+
const keyLength = this.#writeKey(key, keyOffset)
|
|
192
|
+
|
|
193
|
+
const [ response ] = await this.#connection.send({
|
|
194
|
+
opcode: opcode,
|
|
195
|
+
cas,
|
|
196
|
+
extras: this.#buffer,
|
|
197
|
+
extrasOffset: 0,
|
|
198
|
+
extrasLength: keyOffset,
|
|
199
|
+
key: this.#buffer,
|
|
200
|
+
keyOffset,
|
|
201
|
+
keyLength,
|
|
202
|
+
value,
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
try {
|
|
206
|
+
switch (response.status) {
|
|
207
|
+
case STATUS.OK:
|
|
208
|
+
return response.cas
|
|
209
|
+
case STATUS.KEY_NOT_FOUND:
|
|
210
|
+
case STATUS.KEY_EXISTS:
|
|
211
|
+
return
|
|
212
|
+
default:
|
|
213
|
+
fail(response, key)
|
|
214
|
+
}
|
|
215
|
+
} finally {
|
|
216
|
+
response.recycle()
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
set(
|
|
221
|
+
key: string,
|
|
222
|
+
value: Buffer,
|
|
223
|
+
options: { flags?: number, cas?: bigint, ttl?: number } = {},
|
|
224
|
+
): Promise<bigint | void> {
|
|
225
|
+
return this.#sar(OPCODE.SET, key, value, options)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
add(
|
|
229
|
+
key: string,
|
|
230
|
+
value: Buffer,
|
|
231
|
+
options: { flags?: number, cas?: bigint, ttl?: number } = {},
|
|
232
|
+
): Promise<bigint | void> {
|
|
233
|
+
return this.#sar(OPCODE.ADD, key, value, options)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
replace(
|
|
237
|
+
key: string,
|
|
238
|
+
value: Buffer,
|
|
239
|
+
options: { flags?: number, cas?: bigint, ttl?: number } = {},
|
|
240
|
+
): Promise<bigint | void> {
|
|
241
|
+
return this.#sar(OPCODE.REPLACE, key, value, options)
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* ======================================================================== */
|
|
245
|
+
|
|
246
|
+
async #pend(
|
|
247
|
+
opcode: OPCODE.APPEND | OPCODE.PREPEND,
|
|
248
|
+
key: string,
|
|
249
|
+
value: Buffer,
|
|
250
|
+
options: { cas?: bigint },
|
|
251
|
+
): Promise<boolean> {
|
|
252
|
+
const { cas = 0n } = options
|
|
253
|
+
|
|
254
|
+
const keyLength = this.#writeKey(key)
|
|
255
|
+
|
|
256
|
+
const [ response ] = await this.#connection.send({
|
|
257
|
+
opcode: opcode,
|
|
258
|
+
cas,
|
|
259
|
+
key: Buffer.from(key, 'utf-8'),
|
|
260
|
+
keyOffset: 0,
|
|
261
|
+
keyLength,
|
|
262
|
+
value,
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
try {
|
|
266
|
+
switch (response.status) {
|
|
267
|
+
case STATUS.OK:
|
|
268
|
+
return true
|
|
269
|
+
case STATUS.ITEM_NOT_STORED:
|
|
270
|
+
case STATUS.KEY_EXISTS:
|
|
271
|
+
return false
|
|
272
|
+
default:
|
|
273
|
+
fail(response, key)
|
|
274
|
+
}
|
|
275
|
+
} finally {
|
|
276
|
+
response.recycle()
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
append(
|
|
281
|
+
key: string,
|
|
282
|
+
value: Buffer,
|
|
283
|
+
options: { cas?: bigint } = {},
|
|
284
|
+
): Promise<boolean> {
|
|
285
|
+
return this.#pend(OPCODE.APPEND, key, value, options)
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
prepend(
|
|
289
|
+
key: string,
|
|
290
|
+
value: Buffer,
|
|
291
|
+
options: { cas?: bigint } = {},
|
|
292
|
+
): Promise<boolean> {
|
|
293
|
+
return this.#pend(OPCODE.PREPEND, key, value, options)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* ======================================================================== */
|
|
297
|
+
|
|
298
|
+
async #counter(
|
|
299
|
+
opcode: OPCODE.INCREMENT | OPCODE.DECREMENT,
|
|
300
|
+
key: string,
|
|
301
|
+
delta: bigint | number,
|
|
302
|
+
options: { initial?: bigint | number, cas?: bigint, ttl?: number },
|
|
303
|
+
): Promise<Counter | void> {
|
|
304
|
+
const {
|
|
305
|
+
initial,
|
|
306
|
+
cas = 0n,
|
|
307
|
+
ttl = this.#ttl,
|
|
308
|
+
} = options
|
|
309
|
+
|
|
310
|
+
let keyOffset: number
|
|
311
|
+
keyOffset = this.#buffer.writeBigUInt64BE(BigInt(delta))
|
|
312
|
+
keyOffset = this.#buffer.writeBigUInt64BE(BigInt(initial || 0n), keyOffset)
|
|
313
|
+
keyOffset = this.#buffer.writeUInt32BE(initial == undefined ? 0xffffffff : ttl, keyOffset)
|
|
314
|
+
const keyLength = this.#writeKey(key, keyOffset)
|
|
315
|
+
|
|
316
|
+
const [ response ] = await this.#connection.send({
|
|
317
|
+
opcode: opcode,
|
|
318
|
+
extras: this.#buffer,
|
|
319
|
+
extrasOffset: 0,
|
|
320
|
+
extrasLength: keyOffset,
|
|
321
|
+
key: this.#buffer,
|
|
322
|
+
keyOffset,
|
|
323
|
+
keyLength,
|
|
324
|
+
cas,
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
try {
|
|
328
|
+
switch (response.status) {
|
|
329
|
+
case STATUS.OK:
|
|
330
|
+
return {
|
|
331
|
+
value: response.value.readBigUInt64BE(0),
|
|
332
|
+
cas: response.cas,
|
|
333
|
+
}
|
|
334
|
+
case STATUS.KEY_NOT_FOUND:
|
|
335
|
+
case STATUS.KEY_EXISTS:
|
|
336
|
+
return
|
|
337
|
+
default:
|
|
338
|
+
fail(response, key)
|
|
339
|
+
}
|
|
340
|
+
} finally {
|
|
341
|
+
response.recycle()
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
increment(
|
|
346
|
+
key: string,
|
|
347
|
+
delta: bigint | number = 1,
|
|
348
|
+
options: { initial?: bigint | number, cas?: bigint, ttl?: number, create?: boolean } = {},
|
|
349
|
+
): Promise<Counter | void> {
|
|
350
|
+
return this.#counter(OPCODE.INCREMENT, key, delta, options)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
decrement(
|
|
354
|
+
key: string,
|
|
355
|
+
delta: bigint | number = 1,
|
|
356
|
+
options: { initial?: bigint | number, cas?: bigint, ttl?: number, create?: boolean } = {},
|
|
357
|
+
): Promise<Counter | void> {
|
|
358
|
+
return this.#counter(OPCODE.DECREMENT, key, delta, options)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/* ======================================================================== */
|
|
362
|
+
|
|
363
|
+
async delete(
|
|
364
|
+
key: string,
|
|
365
|
+
options: { cas?: bigint } = {},
|
|
366
|
+
): Promise<boolean> {
|
|
367
|
+
const { cas = 0n } = options
|
|
368
|
+
|
|
369
|
+
const keyLength = this.#writeKey(key)
|
|
370
|
+
|
|
371
|
+
const [ response ] = await this.#connection.send({
|
|
372
|
+
opcode: OPCODE.DELETE,
|
|
373
|
+
key: this.#buffer,
|
|
374
|
+
keyOffset: 0,
|
|
375
|
+
keyLength,
|
|
376
|
+
cas,
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
try {
|
|
380
|
+
switch (response.status) {
|
|
381
|
+
case STATUS.OK:
|
|
382
|
+
return true
|
|
383
|
+
case STATUS.KEY_NOT_FOUND:
|
|
384
|
+
case STATUS.KEY_EXISTS:
|
|
385
|
+
return false
|
|
386
|
+
default:
|
|
387
|
+
fail(response, key)
|
|
388
|
+
}
|
|
389
|
+
} finally {
|
|
390
|
+
response.recycle()
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async flush(ttl: number = 0): Promise<void> {
|
|
395
|
+
const extrasLength = ttl ? this.#buffer.writeUInt32BE(ttl) : 0
|
|
396
|
+
|
|
397
|
+
const [ response ] = await this.#connection.send({
|
|
398
|
+
opcode: OPCODE.FLUSH,
|
|
399
|
+
extras: this.#buffer,
|
|
400
|
+
extrasOffset: 0,
|
|
401
|
+
extrasLength,
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
try {
|
|
405
|
+
switch (response.status) {
|
|
406
|
+
case STATUS.OK:
|
|
407
|
+
return
|
|
408
|
+
default:
|
|
409
|
+
fail(response)
|
|
410
|
+
}
|
|
411
|
+
} finally {
|
|
412
|
+
response.recycle()
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/* ======================================================================== */
|
|
417
|
+
|
|
418
|
+
async noop(): Promise<void> {
|
|
419
|
+
const [ response ] = await this.#connection.send({
|
|
420
|
+
opcode: OPCODE.NOOP,
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
try {
|
|
424
|
+
switch (response.status) {
|
|
425
|
+
case STATUS.OK:
|
|
426
|
+
return
|
|
427
|
+
default:
|
|
428
|
+
fail(response)
|
|
429
|
+
}
|
|
430
|
+
} finally {
|
|
431
|
+
response.recycle()
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
async quit(): Promise<void> {
|
|
436
|
+
const [ response ] = await this.#connection.send({
|
|
437
|
+
opcode: OPCODE.QUIT,
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
try {
|
|
441
|
+
switch (response.status) {
|
|
442
|
+
case STATUS.OK:
|
|
443
|
+
return
|
|
444
|
+
default:
|
|
445
|
+
fail(response)
|
|
446
|
+
}
|
|
447
|
+
} finally {
|
|
448
|
+
response.recycle()
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
async version(): Promise<Record<string, string>> {
|
|
453
|
+
const [ response ] = await this.#connection.send({
|
|
454
|
+
opcode: OPCODE.VERSION,
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
try {
|
|
458
|
+
switch (response.status) {
|
|
459
|
+
case STATUS.OK:
|
|
460
|
+
return { [this.#id]: response.value.toString('utf-8') }
|
|
461
|
+
default:
|
|
462
|
+
fail(response)
|
|
463
|
+
}
|
|
464
|
+
} finally {
|
|
465
|
+
response.recycle()
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
async stats(): Promise<Record<string, Stats>> {
|
|
470
|
+
const responses = await this.#connection.send({
|
|
471
|
+
opcode: OPCODE.STAT,
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
const stats = responses.reduce((result, packet) => {
|
|
475
|
+
try {
|
|
476
|
+
if (packet.status !== STATUS.OK) fail(packet)
|
|
477
|
+
|
|
478
|
+
const key = packet.key.toString('utf-8')
|
|
479
|
+
const value = packet.value.toString('utf-8')
|
|
480
|
+
|
|
481
|
+
return injectStats(key, value, result)
|
|
482
|
+
} finally {
|
|
483
|
+
packet.recycle()
|
|
484
|
+
}
|
|
485
|
+
}, {})
|
|
486
|
+
|
|
487
|
+
return { [this.#id]: stats as Stats }
|
|
488
|
+
}
|
|
489
|
+
}
|