memx 0.0.4 → 0.0.7
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.js +264 -219
- package/dist/index.js.map +2 -2
- package/dist/index.mjs +262 -230
- package/dist/index.mjs.map +2 -2
- package/index.d.ts +87 -78
- package/package.json +6 -6
- package/src/buffers.ts +1 -1
- package/src/client.ts +87 -66
- package/src/cluster.ts +14 -2
- package/src/connection.ts +1 -1
- package/src/fake.ts +24 -4
- package/src/index.ts +2 -0
- package/src/internals.ts +12 -24
- package/src/server.ts +17 -6
- package/src/types.ts +7 -1
- package/src/utils.ts +19 -14
package/dist/index.mjs
CHANGED
|
@@ -274,25 +274,13 @@ __export(connection_exports, {
|
|
|
274
274
|
|
|
275
275
|
// src/internals.ts
|
|
276
276
|
import assert2 from "assert";
|
|
277
|
-
import {
|
|
278
|
-
isUint8Array,
|
|
279
|
-
isUint8ClampedArray,
|
|
280
|
-
isUint16Array,
|
|
281
|
-
isUint32Array,
|
|
282
|
-
isInt8Array,
|
|
283
|
-
isInt16Array,
|
|
284
|
-
isInt32Array,
|
|
285
|
-
isBigUint64Array,
|
|
286
|
-
isBigInt64Array,
|
|
287
|
-
isFloat32Array,
|
|
288
|
-
isFloat64Array
|
|
289
|
-
} from "util/types";
|
|
277
|
+
import { types } from "util";
|
|
290
278
|
var socketFinalizationRegistry = new FinalizationRegistry((socket) => {
|
|
291
279
|
if (!socket.destroyed)
|
|
292
280
|
socket.destroy();
|
|
293
281
|
});
|
|
294
282
|
function typedArrayFlags(value) {
|
|
295
|
-
const flags = isUint8Array(value) ? 3402235920 /* UINT8ARRAY */ : isUint8ClampedArray(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : isUint16Array(value) ? 3402235922 /* UINT16ARRAY */ : isUint32Array(value) ? 3402235923 /* UINT32ARRAY */ : isInt8Array(value) ? 3402235924 /* INT8ARRAY */ : isInt16Array(value) ? 3402235925 /* INT16ARRAY */ : isInt32Array(value) ? 3402235926 /* INT32ARRAY */ : isBigUint64Array(value) ? 3402235927 /* BIGUINT64ARRAY */ : isBigInt64Array(value) ? 3402235928 /* BIGINT64ARRAY */ : isFloat32Array(value) ? 3402235929 /* FLOAT32ARRAY */ : isFloat64Array(value) ? 3402235930 /* FLOAT64ARRAY */ : assert2.fail("Unsupported kind of TypedArray");
|
|
283
|
+
const flags = types.isUint8Array(value) ? 3402235920 /* UINT8ARRAY */ : types.isUint8ClampedArray(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : types.isUint16Array(value) ? 3402235922 /* UINT16ARRAY */ : types.isUint32Array(value) ? 3402235923 /* UINT32ARRAY */ : types.isInt8Array(value) ? 3402235924 /* INT8ARRAY */ : types.isInt16Array(value) ? 3402235925 /* INT16ARRAY */ : types.isInt32Array(value) ? 3402235926 /* INT32ARRAY */ : types.isBigUint64Array(value) ? 3402235927 /* BIGUINT64ARRAY */ : types.isBigInt64Array(value) ? 3402235928 /* BIGINT64ARRAY */ : types.isFloat32Array(value) ? 3402235929 /* FLOAT32ARRAY */ : types.isFloat64Array(value) ? 3402235930 /* FLOAT64ARRAY */ : assert2.fail("Unsupported kind of TypedArray");
|
|
296
284
|
return flags;
|
|
297
285
|
}
|
|
298
286
|
function logPromiseError(promise, message) {
|
|
@@ -441,144 +429,6 @@ var Connection = class {
|
|
|
441
429
|
}
|
|
442
430
|
};
|
|
443
431
|
|
|
444
|
-
// src/fake.ts
|
|
445
|
-
function toExp(ttl = 0) {
|
|
446
|
-
if (ttl === 0)
|
|
447
|
-
return Number.MAX_SAFE_INTEGER;
|
|
448
|
-
return Date.now() + ttl * 1e3;
|
|
449
|
-
}
|
|
450
|
-
var FakeAdapter = class {
|
|
451
|
-
#cache = /* @__PURE__ */ new Map();
|
|
452
|
-
#cas = 1n;
|
|
453
|
-
#get(key) {
|
|
454
|
-
if (key.length > 250)
|
|
455
|
-
throw new TypeError(`Key too long (len=${key.length})`);
|
|
456
|
-
const entry = this.#cache.get(key);
|
|
457
|
-
if (!entry)
|
|
458
|
-
return;
|
|
459
|
-
if (Date.now() > entry.exp) {
|
|
460
|
-
this.#cache.delete(key);
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
return entry;
|
|
464
|
-
}
|
|
465
|
-
#set(key, value, flags, ttl) {
|
|
466
|
-
this.#cache.set(key, {
|
|
467
|
-
value,
|
|
468
|
-
flags: flags || 0,
|
|
469
|
-
cas: ++this.#cas,
|
|
470
|
-
exp: toExp(ttl)
|
|
471
|
-
});
|
|
472
|
-
return this.#cas;
|
|
473
|
-
}
|
|
474
|
-
async get(key, options = {}) {
|
|
475
|
-
const entry = this.#get(key);
|
|
476
|
-
if (!entry)
|
|
477
|
-
return;
|
|
478
|
-
if (options.ttl !== void 0) {
|
|
479
|
-
const exp = toExp(options.ttl);
|
|
480
|
-
entry.exp = exp;
|
|
481
|
-
}
|
|
482
|
-
return {
|
|
483
|
-
value: entry.value,
|
|
484
|
-
flags: entry.flags,
|
|
485
|
-
cas: entry.cas,
|
|
486
|
-
recycle: () => void 0
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
|
-
async touch(key, ttl) {
|
|
490
|
-
const entry = this.#get(key);
|
|
491
|
-
if (entry)
|
|
492
|
-
entry.exp = toExp(ttl);
|
|
493
|
-
return !!entry;
|
|
494
|
-
}
|
|
495
|
-
async set(key, value, options = {}) {
|
|
496
|
-
const entry = this.#get(key);
|
|
497
|
-
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
498
|
-
return;
|
|
499
|
-
}
|
|
500
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
501
|
-
}
|
|
502
|
-
async add(key, value, options = {}) {
|
|
503
|
-
if (this.#get(key))
|
|
504
|
-
return;
|
|
505
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
506
|
-
}
|
|
507
|
-
async replace(key, value, options = {}) {
|
|
508
|
-
if (!this.#get(key))
|
|
509
|
-
return;
|
|
510
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
511
|
-
}
|
|
512
|
-
async append(key, value, options = {}) {
|
|
513
|
-
const entry = this.#get(key);
|
|
514
|
-
if (!entry)
|
|
515
|
-
return false;
|
|
516
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
517
|
-
return false;
|
|
518
|
-
entry.value = Buffer.concat([entry.value, value]);
|
|
519
|
-
return true;
|
|
520
|
-
}
|
|
521
|
-
async prepend(key, value, options = {}) {
|
|
522
|
-
const entry = this.#get(key);
|
|
523
|
-
if (!entry)
|
|
524
|
-
return false;
|
|
525
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
526
|
-
return false;
|
|
527
|
-
entry.value = Buffer.concat([value, entry.value]);
|
|
528
|
-
return true;
|
|
529
|
-
}
|
|
530
|
-
async #counter(key, delta, options) {
|
|
531
|
-
const entry = this.#get(key);
|
|
532
|
-
if (!entry) {
|
|
533
|
-
if (options.initial !== void 0) {
|
|
534
|
-
const value = Buffer.from(options.initial.toString());
|
|
535
|
-
this.#set(key, value, void 0, options.ttl);
|
|
536
|
-
return { value: BigInt(options.initial), cas: this.#cas };
|
|
537
|
-
} else {
|
|
538
|
-
return;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
542
|
-
return;
|
|
543
|
-
try {
|
|
544
|
-
const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
|
|
545
|
-
this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
|
|
546
|
-
return { value, cas: this.#cas };
|
|
547
|
-
} catch (error) {
|
|
548
|
-
throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
increment(key, delta = 1n, options = {}) {
|
|
552
|
-
return this.#counter(key, delta, options);
|
|
553
|
-
}
|
|
554
|
-
decrement(key, delta = 1n, options = {}) {
|
|
555
|
-
return this.#counter(key, -delta, options);
|
|
556
|
-
}
|
|
557
|
-
async delete(key, options = {}) {
|
|
558
|
-
const entry = this.#get(key);
|
|
559
|
-
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
560
|
-
return false;
|
|
561
|
-
}
|
|
562
|
-
return this.#cache.delete(key);
|
|
563
|
-
}
|
|
564
|
-
async flush(ttl) {
|
|
565
|
-
if (!ttl)
|
|
566
|
-
return this.#cache.clear();
|
|
567
|
-
const wait = toExp(ttl) - Date.now();
|
|
568
|
-
setTimeout(() => this.#cache.clear(), wait);
|
|
569
|
-
}
|
|
570
|
-
async noop() {
|
|
571
|
-
}
|
|
572
|
-
async quit() {
|
|
573
|
-
}
|
|
574
|
-
async version() {
|
|
575
|
-
return { fake: "0.0.0-fake" };
|
|
576
|
-
}
|
|
577
|
-
async stats() {
|
|
578
|
-
return { fake: { version: "0.0.0-fake" } };
|
|
579
|
-
}
|
|
580
|
-
};
|
|
581
|
-
|
|
582
432
|
// src/server.ts
|
|
583
433
|
var statsBigInt = [
|
|
584
434
|
"auth_cmds",
|
|
@@ -726,10 +576,9 @@ var ServerAdapter = class {
|
|
|
726
576
|
throw new Error(`Key too long (len=${keyLength})`);
|
|
727
577
|
return keyLength;
|
|
728
578
|
}
|
|
729
|
-
async get(key,
|
|
730
|
-
const { ttl } = options;
|
|
579
|
+
async #get(key, ttl) {
|
|
731
580
|
let keyOffset = 0;
|
|
732
|
-
if (ttl)
|
|
581
|
+
if (ttl !== void 0)
|
|
733
582
|
keyOffset = this.#buffer.writeUInt32BE(ttl);
|
|
734
583
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
735
584
|
const [response] = await this.#connection.send({
|
|
@@ -755,8 +604,14 @@ var ServerAdapter = class {
|
|
|
755
604
|
fail(response, key);
|
|
756
605
|
}
|
|
757
606
|
}
|
|
607
|
+
async get(key) {
|
|
608
|
+
return this.#get(key);
|
|
609
|
+
}
|
|
610
|
+
async gat(key, ttl) {
|
|
611
|
+
return this.#get(key, ttl || 2592e3);
|
|
612
|
+
}
|
|
758
613
|
async touch(key, ttl) {
|
|
759
|
-
const timeToLive = ttl
|
|
614
|
+
const timeToLive = ttl ?? this.#ttl;
|
|
760
615
|
const keyOffset = this.#buffer.writeUInt32BE(timeToLive);
|
|
761
616
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
762
617
|
const [response] = await this.#connection.send({
|
|
@@ -1004,6 +859,7 @@ var ServerAdapter = class {
|
|
|
1004
859
|
};
|
|
1005
860
|
|
|
1006
861
|
// src/cluster.ts
|
|
862
|
+
import assert4 from "assert";
|
|
1007
863
|
function parseHosts(hosts) {
|
|
1008
864
|
const result = [];
|
|
1009
865
|
if (!hosts)
|
|
@@ -1017,6 +873,7 @@ function parseHosts(hosts) {
|
|
|
1017
873
|
}
|
|
1018
874
|
var ClusterAdapter = class {
|
|
1019
875
|
servers;
|
|
876
|
+
ttl;
|
|
1020
877
|
constructor(serversOrOptions) {
|
|
1021
878
|
if (Array.isArray(serversOrOptions)) {
|
|
1022
879
|
this.servers = [...serversOrOptions];
|
|
@@ -1044,6 +901,10 @@ var ClusterAdapter = class {
|
|
|
1044
901
|
throw new Error("No hosts configured");
|
|
1045
902
|
if (this.servers.length === 1)
|
|
1046
903
|
this.server = () => this.servers[0];
|
|
904
|
+
this.ttl = this.servers[0].ttl;
|
|
905
|
+
this.servers.slice(1).forEach((server) => {
|
|
906
|
+
assert4.equal(server.ttl, this.ttl, `TTL Mismatch (${server.ttl} != ${this.ttl})`);
|
|
907
|
+
});
|
|
1047
908
|
Object.freeze(this.servers);
|
|
1048
909
|
}
|
|
1049
910
|
server(key) {
|
|
@@ -1053,8 +914,11 @@ var ClusterAdapter = class {
|
|
|
1053
914
|
hash = hash * 31 + key.charCodeAt(i);
|
|
1054
915
|
return this.servers[hash % this.servers.length];
|
|
1055
916
|
}
|
|
1056
|
-
get(key
|
|
1057
|
-
return this.server(key).get(key
|
|
917
|
+
get(key) {
|
|
918
|
+
return this.server(key).get(key);
|
|
919
|
+
}
|
|
920
|
+
gat(key, ttl) {
|
|
921
|
+
return this.server(key).gat(key, ttl);
|
|
1058
922
|
}
|
|
1059
923
|
touch(key, ttl) {
|
|
1060
924
|
return this.server(key).touch(key, ttl);
|
|
@@ -1103,8 +967,8 @@ var ClusterAdapter = class {
|
|
|
1103
967
|
};
|
|
1104
968
|
|
|
1105
969
|
// src/client.ts
|
|
1106
|
-
import
|
|
1107
|
-
import {
|
|
970
|
+
import assert5 from "assert";
|
|
971
|
+
import { types as types2 } from "util";
|
|
1108
972
|
function replacer(key, value) {
|
|
1109
973
|
if (typeof this[key] === "bigint")
|
|
1110
974
|
return ["\0__$BIGINT$__\0", this[key].toString()];
|
|
@@ -1146,9 +1010,9 @@ function toBuffer(value, options) {
|
|
|
1146
1010
|
case "object":
|
|
1147
1011
|
break;
|
|
1148
1012
|
default:
|
|
1149
|
-
|
|
1013
|
+
assert5.fail(`Unable to store value of type "${typeof value}"`);
|
|
1150
1014
|
}
|
|
1151
|
-
if (isTypedArray(value)) {
|
|
1015
|
+
if (types2.isTypedArray(value)) {
|
|
1152
1016
|
const flags = typedArrayFlags(value);
|
|
1153
1017
|
const buffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
1154
1018
|
return [buffer, __spreadProps(__spreadValues({}, options), { flags })];
|
|
@@ -1158,12 +1022,58 @@ function toBuffer(value, options) {
|
|
|
1158
1022
|
const json = JSON.stringify(value, replacer);
|
|
1159
1023
|
return [Buffer.from(json, "utf-8"), __spreadProps(__spreadValues({}, options), { flags: 3402235919 /* JSON */ })];
|
|
1160
1024
|
}
|
|
1025
|
+
function fromBuffer(result) {
|
|
1026
|
+
try {
|
|
1027
|
+
const { flags, value, cas } = result;
|
|
1028
|
+
switch (flags) {
|
|
1029
|
+
case 3402235904 /* BIGINT */:
|
|
1030
|
+
return { value: BigInt(value.toString("utf-8")), cas };
|
|
1031
|
+
case 3402235905 /* BOOLEAN */:
|
|
1032
|
+
return { value: !!value[0], cas };
|
|
1033
|
+
case 3402235906 /* NUMBER */:
|
|
1034
|
+
return { value: Number(value.toString("utf-8")), cas };
|
|
1035
|
+
case 3402235907 /* STRING */:
|
|
1036
|
+
return { value: value.toString("utf-8"), cas };
|
|
1037
|
+
case 3402235918 /* NULL */:
|
|
1038
|
+
return { value: null, cas };
|
|
1039
|
+
case 3402235919 /* JSON */:
|
|
1040
|
+
return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
|
|
1041
|
+
case 3402235920 /* UINT8ARRAY */:
|
|
1042
|
+
return { value: makeTypedArray(Uint8Array, value), cas };
|
|
1043
|
+
case 3402235921 /* UINT8CLAMPEDARRAY */:
|
|
1044
|
+
return { value: makeTypedArray(Uint8ClampedArray, value), cas };
|
|
1045
|
+
case 3402235922 /* UINT16ARRAY */:
|
|
1046
|
+
return { value: makeTypedArray(Uint16Array, value), cas };
|
|
1047
|
+
case 3402235923 /* UINT32ARRAY */:
|
|
1048
|
+
return { value: makeTypedArray(Uint32Array, value), cas };
|
|
1049
|
+
case 3402235924 /* INT8ARRAY */:
|
|
1050
|
+
return { value: makeTypedArray(Int8Array, value), cas };
|
|
1051
|
+
case 3402235925 /* INT16ARRAY */:
|
|
1052
|
+
return { value: makeTypedArray(Int16Array, value), cas };
|
|
1053
|
+
case 3402235926 /* INT32ARRAY */:
|
|
1054
|
+
return { value: makeTypedArray(Int32Array, value), cas };
|
|
1055
|
+
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1056
|
+
return { value: makeTypedArray(BigUint64Array, value), cas };
|
|
1057
|
+
case 3402235928 /* BIGINT64ARRAY */:
|
|
1058
|
+
return { value: makeTypedArray(BigInt64Array, value), cas };
|
|
1059
|
+
case 3402235929 /* FLOAT32ARRAY */:
|
|
1060
|
+
return { value: makeTypedArray(Float32Array, value), cas };
|
|
1061
|
+
case 3402235930 /* FLOAT64ARRAY */:
|
|
1062
|
+
return { value: makeTypedArray(Float64Array, value), cas };
|
|
1063
|
+
case 0 /* BUFFER */:
|
|
1064
|
+
default:
|
|
1065
|
+
return { value: Buffer.from(value), cas };
|
|
1066
|
+
}
|
|
1067
|
+
} finally {
|
|
1068
|
+
result.recycle();
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1161
1071
|
function makeTypedArray(constructor, source) {
|
|
1162
1072
|
const clone = Buffer.from(source);
|
|
1163
1073
|
const { buffer, byteOffset, byteLength } = clone;
|
|
1164
1074
|
return new constructor(buffer, byteOffset, byteLength / constructor.BYTES_PER_ELEMENT);
|
|
1165
1075
|
}
|
|
1166
|
-
var
|
|
1076
|
+
var MemxClient = class {
|
|
1167
1077
|
#adapter;
|
|
1168
1078
|
#prefix;
|
|
1169
1079
|
constructor(adapterOrOptions) {
|
|
@@ -1175,7 +1085,7 @@ var Client = class {
|
|
|
1175
1085
|
this.#adapter = new ClusterAdapter(adapterOrOptions);
|
|
1176
1086
|
}
|
|
1177
1087
|
this.#prefix = "";
|
|
1178
|
-
|
|
1088
|
+
assert5(this.#adapter, "Invalid client constructor arguments");
|
|
1179
1089
|
}
|
|
1180
1090
|
get adapter() {
|
|
1181
1091
|
return this.#adapter;
|
|
@@ -1184,59 +1094,26 @@ var Client = class {
|
|
|
1184
1094
|
return this.#prefix;
|
|
1185
1095
|
}
|
|
1186
1096
|
withPrefix(prefix) {
|
|
1187
|
-
|
|
1188
|
-
const client = new
|
|
1097
|
+
assert5(prefix, "Invalid prefix");
|
|
1098
|
+
const client = new MemxClient(this.#adapter);
|
|
1189
1099
|
client.#prefix = prefix;
|
|
1190
1100
|
return client;
|
|
1191
1101
|
}
|
|
1192
|
-
async get(key
|
|
1193
|
-
const result = await this.#adapter.get(this.#prefix + key
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
case 3402235918 /* NULL */:
|
|
1208
|
-
return { value: null, cas };
|
|
1209
|
-
case 3402235919 /* JSON */:
|
|
1210
|
-
return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
|
|
1211
|
-
case 3402235920 /* UINT8ARRAY */:
|
|
1212
|
-
return { value: makeTypedArray(Uint8Array, value), cas };
|
|
1213
|
-
case 3402235921 /* UINT8CLAMPEDARRAY */:
|
|
1214
|
-
return { value: makeTypedArray(Uint8ClampedArray, value), cas };
|
|
1215
|
-
case 3402235922 /* UINT16ARRAY */:
|
|
1216
|
-
return { value: makeTypedArray(Uint16Array, value), cas };
|
|
1217
|
-
case 3402235923 /* UINT32ARRAY */:
|
|
1218
|
-
return { value: makeTypedArray(Uint32Array, value), cas };
|
|
1219
|
-
case 3402235924 /* INT8ARRAY */:
|
|
1220
|
-
return { value: makeTypedArray(Int8Array, value), cas };
|
|
1221
|
-
case 3402235925 /* INT16ARRAY */:
|
|
1222
|
-
return { value: makeTypedArray(Int16Array, value), cas };
|
|
1223
|
-
case 3402235926 /* INT32ARRAY */:
|
|
1224
|
-
return { value: makeTypedArray(Int32Array, value), cas };
|
|
1225
|
-
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1226
|
-
return { value: makeTypedArray(BigUint64Array, value), cas };
|
|
1227
|
-
case 3402235928 /* BIGINT64ARRAY */:
|
|
1228
|
-
return { value: makeTypedArray(BigInt64Array, value), cas };
|
|
1229
|
-
case 3402235929 /* FLOAT32ARRAY */:
|
|
1230
|
-
return { value: makeTypedArray(Float32Array, value), cas };
|
|
1231
|
-
case 3402235930 /* FLOAT64ARRAY */:
|
|
1232
|
-
return { value: makeTypedArray(Float64Array, value), cas };
|
|
1233
|
-
case 0 /* BUFFER */:
|
|
1234
|
-
default:
|
|
1235
|
-
return { value: Buffer.from(value), cas };
|
|
1236
|
-
}
|
|
1237
|
-
} finally {
|
|
1238
|
-
result.recycle();
|
|
1239
|
-
}
|
|
1102
|
+
async get(key) {
|
|
1103
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1104
|
+
return result && fromBuffer(result).value;
|
|
1105
|
+
}
|
|
1106
|
+
async gat(key, ttl) {
|
|
1107
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1108
|
+
return result && fromBuffer(result).value;
|
|
1109
|
+
}
|
|
1110
|
+
async getc(key) {
|
|
1111
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1112
|
+
return result && fromBuffer(result);
|
|
1113
|
+
}
|
|
1114
|
+
async gatc(key, ttl) {
|
|
1115
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1116
|
+
return result && fromBuffer(result);
|
|
1240
1117
|
}
|
|
1241
1118
|
async set(key, value, options) {
|
|
1242
1119
|
return this.#adapter.set(this.#prefix + key, ...toBuffer(value, options));
|
|
@@ -1292,23 +1169,177 @@ var Client = class {
|
|
|
1292
1169
|
}
|
|
1293
1170
|
};
|
|
1294
1171
|
|
|
1172
|
+
// src/fake.ts
|
|
1173
|
+
function toExp(ttl = 0) {
|
|
1174
|
+
if (ttl === 0)
|
|
1175
|
+
return Number.MAX_SAFE_INTEGER;
|
|
1176
|
+
return Date.now() + ttl * 1e3;
|
|
1177
|
+
}
|
|
1178
|
+
var FakeAdapter = class {
|
|
1179
|
+
#cache = /* @__PURE__ */ new Map();
|
|
1180
|
+
#cas = 1n;
|
|
1181
|
+
ttl = 0;
|
|
1182
|
+
#get(key) {
|
|
1183
|
+
if (key.length > 250)
|
|
1184
|
+
throw new TypeError(`Key too long (len=${key.length})`);
|
|
1185
|
+
const entry = this.#cache.get(key);
|
|
1186
|
+
if (!entry)
|
|
1187
|
+
return;
|
|
1188
|
+
if (Date.now() > entry.exp) {
|
|
1189
|
+
this.#cache.delete(key);
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
return entry;
|
|
1193
|
+
}
|
|
1194
|
+
#set(key, value, flags, ttl) {
|
|
1195
|
+
this.#cache.set(key, {
|
|
1196
|
+
value,
|
|
1197
|
+
flags: flags || 0,
|
|
1198
|
+
cas: ++this.#cas,
|
|
1199
|
+
exp: toExp(ttl)
|
|
1200
|
+
});
|
|
1201
|
+
return this.#cas;
|
|
1202
|
+
}
|
|
1203
|
+
async get(key) {
|
|
1204
|
+
const entry = this.#get(key);
|
|
1205
|
+
if (!entry)
|
|
1206
|
+
return;
|
|
1207
|
+
return {
|
|
1208
|
+
value: entry.value,
|
|
1209
|
+
flags: entry.flags,
|
|
1210
|
+
cas: entry.cas,
|
|
1211
|
+
recycle: () => void 0
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
1214
|
+
async gat(key, ttl) {
|
|
1215
|
+
const entry = this.#get(key);
|
|
1216
|
+
if (!entry)
|
|
1217
|
+
return;
|
|
1218
|
+
entry.exp = toExp(ttl);
|
|
1219
|
+
return {
|
|
1220
|
+
value: entry.value,
|
|
1221
|
+
flags: entry.flags,
|
|
1222
|
+
cas: entry.cas,
|
|
1223
|
+
recycle: () => void 0
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
async touch(key, ttl) {
|
|
1227
|
+
const entry = this.#get(key);
|
|
1228
|
+
if (entry)
|
|
1229
|
+
entry.exp = toExp(ttl);
|
|
1230
|
+
return !!entry;
|
|
1231
|
+
}
|
|
1232
|
+
async set(key, value, options = {}) {
|
|
1233
|
+
const entry = this.#get(key);
|
|
1234
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
1235
|
+
return;
|
|
1236
|
+
}
|
|
1237
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1238
|
+
}
|
|
1239
|
+
async add(key, value, options = {}) {
|
|
1240
|
+
if (this.#get(key))
|
|
1241
|
+
return;
|
|
1242
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1243
|
+
}
|
|
1244
|
+
async replace(key, value, options = {}) {
|
|
1245
|
+
if (!this.#get(key))
|
|
1246
|
+
return;
|
|
1247
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1248
|
+
}
|
|
1249
|
+
async append(key, value, options = {}) {
|
|
1250
|
+
const entry = this.#get(key);
|
|
1251
|
+
if (!entry)
|
|
1252
|
+
return false;
|
|
1253
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1254
|
+
return false;
|
|
1255
|
+
entry.value = Buffer.concat([entry.value, value]);
|
|
1256
|
+
return true;
|
|
1257
|
+
}
|
|
1258
|
+
async prepend(key, value, options = {}) {
|
|
1259
|
+
const entry = this.#get(key);
|
|
1260
|
+
if (!entry)
|
|
1261
|
+
return false;
|
|
1262
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1263
|
+
return false;
|
|
1264
|
+
entry.value = Buffer.concat([value, entry.value]);
|
|
1265
|
+
return true;
|
|
1266
|
+
}
|
|
1267
|
+
async #counter(key, delta, options) {
|
|
1268
|
+
const entry = this.#get(key);
|
|
1269
|
+
if (!entry) {
|
|
1270
|
+
if (options.initial !== void 0) {
|
|
1271
|
+
const value = Buffer.from(options.initial.toString());
|
|
1272
|
+
this.#set(key, value, void 0, options.ttl);
|
|
1273
|
+
return { value: BigInt(options.initial), cas: this.#cas };
|
|
1274
|
+
} else {
|
|
1275
|
+
return;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1279
|
+
return;
|
|
1280
|
+
try {
|
|
1281
|
+
const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
|
|
1282
|
+
this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
|
|
1283
|
+
return { value, cas: this.#cas };
|
|
1284
|
+
} catch (error) {
|
|
1285
|
+
throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
increment(key, delta = 1n, options = {}) {
|
|
1289
|
+
return this.#counter(key, delta, options);
|
|
1290
|
+
}
|
|
1291
|
+
decrement(key, delta = 1n, options = {}) {
|
|
1292
|
+
return this.#counter(key, -delta, options);
|
|
1293
|
+
}
|
|
1294
|
+
async delete(key, options = {}) {
|
|
1295
|
+
const entry = this.#get(key);
|
|
1296
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
1297
|
+
return false;
|
|
1298
|
+
}
|
|
1299
|
+
return this.#cache.delete(key);
|
|
1300
|
+
}
|
|
1301
|
+
async flush(ttl) {
|
|
1302
|
+
if (!ttl)
|
|
1303
|
+
return this.#cache.clear();
|
|
1304
|
+
const wait = toExp(ttl) - Date.now();
|
|
1305
|
+
setTimeout(() => this.#cache.clear(), wait);
|
|
1306
|
+
}
|
|
1307
|
+
async noop() {
|
|
1308
|
+
}
|
|
1309
|
+
async quit() {
|
|
1310
|
+
}
|
|
1311
|
+
async version() {
|
|
1312
|
+
return { fake: "0.0.0-fake" };
|
|
1313
|
+
}
|
|
1314
|
+
async stats() {
|
|
1315
|
+
return { fake: { version: "0.0.0-fake" } };
|
|
1316
|
+
}
|
|
1317
|
+
};
|
|
1318
|
+
var MemxFakeClient = class extends MemxClient {
|
|
1319
|
+
constructor() {
|
|
1320
|
+
super(new FakeAdapter());
|
|
1321
|
+
}
|
|
1322
|
+
};
|
|
1323
|
+
|
|
1295
1324
|
// src/utils.ts
|
|
1296
|
-
import
|
|
1325
|
+
import assert6 from "assert";
|
|
1297
1326
|
var Factory = class {
|
|
1298
1327
|
#factory;
|
|
1299
1328
|
#client;
|
|
1300
1329
|
#ttl;
|
|
1301
1330
|
constructor(client, factory, ttl) {
|
|
1302
|
-
|
|
1303
|
-
|
|
1331
|
+
assert6(typeof factory === "function", "Invalid or no factory specified");
|
|
1332
|
+
assert6(client, "No client specified");
|
|
1304
1333
|
this.#factory = factory;
|
|
1305
1334
|
this.#client = client;
|
|
1306
1335
|
this.#ttl = ttl;
|
|
1307
1336
|
}
|
|
1308
1337
|
async get(key) {
|
|
1309
|
-
const cached = await this.#client.
|
|
1310
|
-
if (cached)
|
|
1338
|
+
const cached = await this.#client.getc(key);
|
|
1339
|
+
if (cached) {
|
|
1340
|
+
void logPromiseError(this.#client.touch(key), `Factory error touching key "${this.#client.prefix}${key}"`);
|
|
1311
1341
|
return cached.value;
|
|
1342
|
+
}
|
|
1312
1343
|
const created = await this.#factory(key);
|
|
1313
1344
|
if (created) {
|
|
1314
1345
|
void logPromiseError(this.#client.set(key, created, { ttl: this.#ttl }), `Factory error setting key "${this.#client.prefix}${key}"`);
|
|
@@ -1321,8 +1352,8 @@ var Bundle = class {
|
|
|
1321
1352
|
#name;
|
|
1322
1353
|
#ttl;
|
|
1323
1354
|
constructor(client, name, ttl) {
|
|
1324
|
-
|
|
1325
|
-
|
|
1355
|
+
assert6(client, "No client specified");
|
|
1356
|
+
assert6(name, "No bundle name specified");
|
|
1326
1357
|
this.#client = client;
|
|
1327
1358
|
this.#name = name;
|
|
1328
1359
|
this.#ttl = ttl || 0;
|
|
@@ -1338,7 +1369,7 @@ var Bundle = class {
|
|
|
1338
1369
|
}
|
|
1339
1370
|
async #removeKey(key) {
|
|
1340
1371
|
await logPromiseError((async () => {
|
|
1341
|
-
const result = await this.#client.
|
|
1372
|
+
const result = await this.#client.getc(this.#name);
|
|
1342
1373
|
if (!result)
|
|
1343
1374
|
return;
|
|
1344
1375
|
const keys = result.value.split("\0").filter((k) => k !== key).join("\0");
|
|
@@ -1350,7 +1381,7 @@ var Bundle = class {
|
|
|
1350
1381
|
await this.#appendKey(key);
|
|
1351
1382
|
}
|
|
1352
1383
|
async get(key) {
|
|
1353
|
-
const result = await this.#client.
|
|
1384
|
+
const result = await this.#client.getc(`${this.#name}:${key}`);
|
|
1354
1385
|
if (result)
|
|
1355
1386
|
return result.value;
|
|
1356
1387
|
await this.#removeKey(key);
|
|
@@ -1360,13 +1391,13 @@ var Bundle = class {
|
|
|
1360
1391
|
await this.#removeKey(key);
|
|
1361
1392
|
}
|
|
1362
1393
|
async list() {
|
|
1363
|
-
const result = await this.#client.
|
|
1394
|
+
const result = await this.#client.getc(this.#name);
|
|
1364
1395
|
if (!result)
|
|
1365
1396
|
return {};
|
|
1366
1397
|
const results = {};
|
|
1367
1398
|
const promises = [];
|
|
1368
1399
|
for (const key of new Set(result.value.split("\0"))) {
|
|
1369
|
-
promises.push(this.#client.
|
|
1400
|
+
promises.push(this.#client.getc(`${this.#name}:${key}`).then((result2) => {
|
|
1370
1401
|
if (result2)
|
|
1371
1402
|
results[key] = result2.value;
|
|
1372
1403
|
}));
|
|
@@ -1380,8 +1411,8 @@ var PoorManLock = class {
|
|
|
1380
1411
|
#client;
|
|
1381
1412
|
#name;
|
|
1382
1413
|
constructor(client, name) {
|
|
1383
|
-
|
|
1384
|
-
|
|
1414
|
+
assert6(client, "No client specified");
|
|
1415
|
+
assert6(name, "No lock name specified");
|
|
1385
1416
|
this.#client = client;
|
|
1386
1417
|
this.#name = name;
|
|
1387
1418
|
}
|
|
@@ -1396,14 +1427,14 @@ var PoorManLock = class {
|
|
|
1396
1427
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1397
1428
|
} while (Date.now() < end);
|
|
1398
1429
|
if (cas === void 0) {
|
|
1399
|
-
const other = await this.#client.
|
|
1430
|
+
const other = await this.#client.getc(this.#name);
|
|
1400
1431
|
const owner2 = other && other.value ? `"${other.value}"` : "anonymous";
|
|
1401
1432
|
throw new Error(`Lock "${this.#client.prefix}${this.#name}" timeout (owner=${owner2})`);
|
|
1402
1433
|
}
|
|
1403
1434
|
const interval = setInterval(() => {
|
|
1404
1435
|
void logPromiseError((async () => {
|
|
1405
1436
|
const replaced = await this.#client.replace(this.#name, owner, { ttl: 2, cas });
|
|
1406
|
-
|
|
1437
|
+
assert6(replaced !== void 0, `Lock "${this.#client.prefix}${this.#name}" not replaced`);
|
|
1407
1438
|
cas = replaced;
|
|
1408
1439
|
})(), `Error extending lock "${this.#client.prefix}${this.#name}"`);
|
|
1409
1440
|
}, 100);
|
|
@@ -1417,10 +1448,11 @@ var PoorManLock = class {
|
|
|
1417
1448
|
};
|
|
1418
1449
|
export {
|
|
1419
1450
|
Bundle,
|
|
1420
|
-
Client,
|
|
1421
1451
|
ClusterAdapter,
|
|
1422
1452
|
Factory,
|
|
1423
1453
|
FakeAdapter,
|
|
1454
|
+
MemxClient,
|
|
1455
|
+
MemxFakeClient,
|
|
1424
1456
|
PoorManLock,
|
|
1425
1457
|
ServerAdapter,
|
|
1426
1458
|
connection_exports as connection,
|