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.js
CHANGED
|
@@ -40,10 +40,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
40
40
|
var src_exports = {};
|
|
41
41
|
__export(src_exports, {
|
|
42
42
|
Bundle: () => Bundle,
|
|
43
|
-
Client: () => Client,
|
|
44
43
|
ClusterAdapter: () => ClusterAdapter,
|
|
45
44
|
Factory: () => Factory,
|
|
46
45
|
FakeAdapter: () => FakeAdapter,
|
|
46
|
+
MemxClient: () => MemxClient,
|
|
47
|
+
MemxFakeClient: () => MemxFakeClient,
|
|
47
48
|
PoorManLock: () => PoorManLock,
|
|
48
49
|
ServerAdapter: () => ServerAdapter,
|
|
49
50
|
connection: () => connection_exports,
|
|
@@ -305,13 +306,13 @@ __export(connection_exports, {
|
|
|
305
306
|
|
|
306
307
|
// src/internals.ts
|
|
307
308
|
var import_assert2 = __toESM(require("assert"));
|
|
308
|
-
var
|
|
309
|
+
var import_util = require("util");
|
|
309
310
|
var socketFinalizationRegistry = new FinalizationRegistry((socket) => {
|
|
310
311
|
if (!socket.destroyed)
|
|
311
312
|
socket.destroy();
|
|
312
313
|
});
|
|
313
314
|
function typedArrayFlags(value) {
|
|
314
|
-
const flags =
|
|
315
|
+
const flags = import_util.types.isUint8Array(value) ? 3402235920 /* UINT8ARRAY */ : import_util.types.isUint8ClampedArray(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : import_util.types.isUint16Array(value) ? 3402235922 /* UINT16ARRAY */ : import_util.types.isUint32Array(value) ? 3402235923 /* UINT32ARRAY */ : import_util.types.isInt8Array(value) ? 3402235924 /* INT8ARRAY */ : import_util.types.isInt16Array(value) ? 3402235925 /* INT16ARRAY */ : import_util.types.isInt32Array(value) ? 3402235926 /* INT32ARRAY */ : import_util.types.isBigUint64Array(value) ? 3402235927 /* BIGUINT64ARRAY */ : import_util.types.isBigInt64Array(value) ? 3402235928 /* BIGINT64ARRAY */ : import_util.types.isFloat32Array(value) ? 3402235929 /* FLOAT32ARRAY */ : import_util.types.isFloat64Array(value) ? 3402235930 /* FLOAT64ARRAY */ : import_assert2.default.fail("Unsupported kind of TypedArray");
|
|
315
316
|
return flags;
|
|
316
317
|
}
|
|
317
318
|
function logPromiseError(promise, message) {
|
|
@@ -460,144 +461,6 @@ var Connection = class {
|
|
|
460
461
|
}
|
|
461
462
|
};
|
|
462
463
|
|
|
463
|
-
// src/fake.ts
|
|
464
|
-
function toExp(ttl = 0) {
|
|
465
|
-
if (ttl === 0)
|
|
466
|
-
return Number.MAX_SAFE_INTEGER;
|
|
467
|
-
return Date.now() + ttl * 1e3;
|
|
468
|
-
}
|
|
469
|
-
var FakeAdapter = class {
|
|
470
|
-
#cache = /* @__PURE__ */ new Map();
|
|
471
|
-
#cas = 1n;
|
|
472
|
-
#get(key) {
|
|
473
|
-
if (key.length > 250)
|
|
474
|
-
throw new TypeError(`Key too long (len=${key.length})`);
|
|
475
|
-
const entry = this.#cache.get(key);
|
|
476
|
-
if (!entry)
|
|
477
|
-
return;
|
|
478
|
-
if (Date.now() > entry.exp) {
|
|
479
|
-
this.#cache.delete(key);
|
|
480
|
-
return;
|
|
481
|
-
}
|
|
482
|
-
return entry;
|
|
483
|
-
}
|
|
484
|
-
#set(key, value, flags, ttl) {
|
|
485
|
-
this.#cache.set(key, {
|
|
486
|
-
value,
|
|
487
|
-
flags: flags || 0,
|
|
488
|
-
cas: ++this.#cas,
|
|
489
|
-
exp: toExp(ttl)
|
|
490
|
-
});
|
|
491
|
-
return this.#cas;
|
|
492
|
-
}
|
|
493
|
-
async get(key, options = {}) {
|
|
494
|
-
const entry = this.#get(key);
|
|
495
|
-
if (!entry)
|
|
496
|
-
return;
|
|
497
|
-
if (options.ttl !== void 0) {
|
|
498
|
-
const exp = toExp(options.ttl);
|
|
499
|
-
entry.exp = exp;
|
|
500
|
-
}
|
|
501
|
-
return {
|
|
502
|
-
value: entry.value,
|
|
503
|
-
flags: entry.flags,
|
|
504
|
-
cas: entry.cas,
|
|
505
|
-
recycle: () => void 0
|
|
506
|
-
};
|
|
507
|
-
}
|
|
508
|
-
async touch(key, ttl) {
|
|
509
|
-
const entry = this.#get(key);
|
|
510
|
-
if (entry)
|
|
511
|
-
entry.exp = toExp(ttl);
|
|
512
|
-
return !!entry;
|
|
513
|
-
}
|
|
514
|
-
async set(key, value, options = {}) {
|
|
515
|
-
const entry = this.#get(key);
|
|
516
|
-
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
517
|
-
return;
|
|
518
|
-
}
|
|
519
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
520
|
-
}
|
|
521
|
-
async add(key, value, options = {}) {
|
|
522
|
-
if (this.#get(key))
|
|
523
|
-
return;
|
|
524
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
525
|
-
}
|
|
526
|
-
async replace(key, value, options = {}) {
|
|
527
|
-
if (!this.#get(key))
|
|
528
|
-
return;
|
|
529
|
-
return this.#set(key, value, options.flags, options.ttl);
|
|
530
|
-
}
|
|
531
|
-
async append(key, value, options = {}) {
|
|
532
|
-
const entry = this.#get(key);
|
|
533
|
-
if (!entry)
|
|
534
|
-
return false;
|
|
535
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
536
|
-
return false;
|
|
537
|
-
entry.value = Buffer.concat([entry.value, value]);
|
|
538
|
-
return true;
|
|
539
|
-
}
|
|
540
|
-
async prepend(key, value, options = {}) {
|
|
541
|
-
const entry = this.#get(key);
|
|
542
|
-
if (!entry)
|
|
543
|
-
return false;
|
|
544
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
545
|
-
return false;
|
|
546
|
-
entry.value = Buffer.concat([value, entry.value]);
|
|
547
|
-
return true;
|
|
548
|
-
}
|
|
549
|
-
async #counter(key, delta, options) {
|
|
550
|
-
const entry = this.#get(key);
|
|
551
|
-
if (!entry) {
|
|
552
|
-
if (options.initial !== void 0) {
|
|
553
|
-
const value = Buffer.from(options.initial.toString());
|
|
554
|
-
this.#set(key, value, void 0, options.ttl);
|
|
555
|
-
return { value: BigInt(options.initial), cas: this.#cas };
|
|
556
|
-
} else {
|
|
557
|
-
return;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
561
|
-
return;
|
|
562
|
-
try {
|
|
563
|
-
const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
|
|
564
|
-
this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
|
|
565
|
-
return { value, cas: this.#cas };
|
|
566
|
-
} catch (error) {
|
|
567
|
-
throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
increment(key, delta = 1n, options = {}) {
|
|
571
|
-
return this.#counter(key, delta, options);
|
|
572
|
-
}
|
|
573
|
-
decrement(key, delta = 1n, options = {}) {
|
|
574
|
-
return this.#counter(key, -delta, options);
|
|
575
|
-
}
|
|
576
|
-
async delete(key, options = {}) {
|
|
577
|
-
const entry = this.#get(key);
|
|
578
|
-
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
579
|
-
return false;
|
|
580
|
-
}
|
|
581
|
-
return this.#cache.delete(key);
|
|
582
|
-
}
|
|
583
|
-
async flush(ttl) {
|
|
584
|
-
if (!ttl)
|
|
585
|
-
return this.#cache.clear();
|
|
586
|
-
const wait = toExp(ttl) - Date.now();
|
|
587
|
-
setTimeout(() => this.#cache.clear(), wait);
|
|
588
|
-
}
|
|
589
|
-
async noop() {
|
|
590
|
-
}
|
|
591
|
-
async quit() {
|
|
592
|
-
}
|
|
593
|
-
async version() {
|
|
594
|
-
return { fake: "0.0.0-fake" };
|
|
595
|
-
}
|
|
596
|
-
async stats() {
|
|
597
|
-
return { fake: { version: "0.0.0-fake" } };
|
|
598
|
-
}
|
|
599
|
-
};
|
|
600
|
-
|
|
601
464
|
// src/server.ts
|
|
602
465
|
var statsBigInt = [
|
|
603
466
|
"auth_cmds",
|
|
@@ -745,10 +608,9 @@ var ServerAdapter = class {
|
|
|
745
608
|
throw new Error(`Key too long (len=${keyLength})`);
|
|
746
609
|
return keyLength;
|
|
747
610
|
}
|
|
748
|
-
async get(key,
|
|
749
|
-
const { ttl } = options;
|
|
611
|
+
async #get(key, ttl) {
|
|
750
612
|
let keyOffset = 0;
|
|
751
|
-
if (ttl)
|
|
613
|
+
if (ttl !== void 0)
|
|
752
614
|
keyOffset = this.#buffer.writeUInt32BE(ttl);
|
|
753
615
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
754
616
|
const [response] = await this.#connection.send({
|
|
@@ -774,8 +636,14 @@ var ServerAdapter = class {
|
|
|
774
636
|
fail(response, key);
|
|
775
637
|
}
|
|
776
638
|
}
|
|
639
|
+
async get(key) {
|
|
640
|
+
return this.#get(key);
|
|
641
|
+
}
|
|
642
|
+
async gat(key, ttl) {
|
|
643
|
+
return this.#get(key, ttl || 2592e3);
|
|
644
|
+
}
|
|
777
645
|
async touch(key, ttl) {
|
|
778
|
-
const timeToLive = ttl
|
|
646
|
+
const timeToLive = ttl ?? this.#ttl;
|
|
779
647
|
const keyOffset = this.#buffer.writeUInt32BE(timeToLive);
|
|
780
648
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
781
649
|
const [response] = await this.#connection.send({
|
|
@@ -1023,6 +891,7 @@ var ServerAdapter = class {
|
|
|
1023
891
|
};
|
|
1024
892
|
|
|
1025
893
|
// src/cluster.ts
|
|
894
|
+
var import_assert4 = __toESM(require("assert"));
|
|
1026
895
|
function parseHosts(hosts) {
|
|
1027
896
|
const result = [];
|
|
1028
897
|
if (!hosts)
|
|
@@ -1036,6 +905,7 @@ function parseHosts(hosts) {
|
|
|
1036
905
|
}
|
|
1037
906
|
var ClusterAdapter = class {
|
|
1038
907
|
servers;
|
|
908
|
+
ttl;
|
|
1039
909
|
constructor(serversOrOptions) {
|
|
1040
910
|
if (Array.isArray(serversOrOptions)) {
|
|
1041
911
|
this.servers = [...serversOrOptions];
|
|
@@ -1063,6 +933,10 @@ var ClusterAdapter = class {
|
|
|
1063
933
|
throw new Error("No hosts configured");
|
|
1064
934
|
if (this.servers.length === 1)
|
|
1065
935
|
this.server = () => this.servers[0];
|
|
936
|
+
this.ttl = this.servers[0].ttl;
|
|
937
|
+
this.servers.slice(1).forEach((server) => {
|
|
938
|
+
import_assert4.default.equal(server.ttl, this.ttl, `TTL Mismatch (${server.ttl} != ${this.ttl})`);
|
|
939
|
+
});
|
|
1066
940
|
Object.freeze(this.servers);
|
|
1067
941
|
}
|
|
1068
942
|
server(key) {
|
|
@@ -1072,8 +946,11 @@ var ClusterAdapter = class {
|
|
|
1072
946
|
hash = hash * 31 + key.charCodeAt(i);
|
|
1073
947
|
return this.servers[hash % this.servers.length];
|
|
1074
948
|
}
|
|
1075
|
-
get(key
|
|
1076
|
-
return this.server(key).get(key
|
|
949
|
+
get(key) {
|
|
950
|
+
return this.server(key).get(key);
|
|
951
|
+
}
|
|
952
|
+
gat(key, ttl) {
|
|
953
|
+
return this.server(key).gat(key, ttl);
|
|
1077
954
|
}
|
|
1078
955
|
touch(key, ttl) {
|
|
1079
956
|
return this.server(key).touch(key, ttl);
|
|
@@ -1122,8 +999,8 @@ var ClusterAdapter = class {
|
|
|
1122
999
|
};
|
|
1123
1000
|
|
|
1124
1001
|
// src/client.ts
|
|
1125
|
-
var
|
|
1126
|
-
var
|
|
1002
|
+
var import_assert5 = __toESM(require("assert"));
|
|
1003
|
+
var import_util2 = require("util");
|
|
1127
1004
|
function replacer(key, value) {
|
|
1128
1005
|
if (typeof this[key] === "bigint")
|
|
1129
1006
|
return ["\0__$BIGINT$__\0", this[key].toString()];
|
|
@@ -1165,9 +1042,9 @@ function toBuffer(value, options) {
|
|
|
1165
1042
|
case "object":
|
|
1166
1043
|
break;
|
|
1167
1044
|
default:
|
|
1168
|
-
|
|
1045
|
+
import_assert5.default.fail(`Unable to store value of type "${typeof value}"`);
|
|
1169
1046
|
}
|
|
1170
|
-
if (
|
|
1047
|
+
if (import_util2.types.isTypedArray(value)) {
|
|
1171
1048
|
const flags = typedArrayFlags(value);
|
|
1172
1049
|
const buffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
1173
1050
|
return [buffer, __spreadProps(__spreadValues({}, options), { flags })];
|
|
@@ -1177,12 +1054,58 @@ function toBuffer(value, options) {
|
|
|
1177
1054
|
const json = JSON.stringify(value, replacer);
|
|
1178
1055
|
return [Buffer.from(json, "utf-8"), __spreadProps(__spreadValues({}, options), { flags: 3402235919 /* JSON */ })];
|
|
1179
1056
|
}
|
|
1057
|
+
function fromBuffer(result) {
|
|
1058
|
+
try {
|
|
1059
|
+
const { flags, value, cas } = result;
|
|
1060
|
+
switch (flags) {
|
|
1061
|
+
case 3402235904 /* BIGINT */:
|
|
1062
|
+
return { value: BigInt(value.toString("utf-8")), cas };
|
|
1063
|
+
case 3402235905 /* BOOLEAN */:
|
|
1064
|
+
return { value: !!value[0], cas };
|
|
1065
|
+
case 3402235906 /* NUMBER */:
|
|
1066
|
+
return { value: Number(value.toString("utf-8")), cas };
|
|
1067
|
+
case 3402235907 /* STRING */:
|
|
1068
|
+
return { value: value.toString("utf-8"), cas };
|
|
1069
|
+
case 3402235918 /* NULL */:
|
|
1070
|
+
return { value: null, cas };
|
|
1071
|
+
case 3402235919 /* JSON */:
|
|
1072
|
+
return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
|
|
1073
|
+
case 3402235920 /* UINT8ARRAY */:
|
|
1074
|
+
return { value: makeTypedArray(Uint8Array, value), cas };
|
|
1075
|
+
case 3402235921 /* UINT8CLAMPEDARRAY */:
|
|
1076
|
+
return { value: makeTypedArray(Uint8ClampedArray, value), cas };
|
|
1077
|
+
case 3402235922 /* UINT16ARRAY */:
|
|
1078
|
+
return { value: makeTypedArray(Uint16Array, value), cas };
|
|
1079
|
+
case 3402235923 /* UINT32ARRAY */:
|
|
1080
|
+
return { value: makeTypedArray(Uint32Array, value), cas };
|
|
1081
|
+
case 3402235924 /* INT8ARRAY */:
|
|
1082
|
+
return { value: makeTypedArray(Int8Array, value), cas };
|
|
1083
|
+
case 3402235925 /* INT16ARRAY */:
|
|
1084
|
+
return { value: makeTypedArray(Int16Array, value), cas };
|
|
1085
|
+
case 3402235926 /* INT32ARRAY */:
|
|
1086
|
+
return { value: makeTypedArray(Int32Array, value), cas };
|
|
1087
|
+
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1088
|
+
return { value: makeTypedArray(BigUint64Array, value), cas };
|
|
1089
|
+
case 3402235928 /* BIGINT64ARRAY */:
|
|
1090
|
+
return { value: makeTypedArray(BigInt64Array, value), cas };
|
|
1091
|
+
case 3402235929 /* FLOAT32ARRAY */:
|
|
1092
|
+
return { value: makeTypedArray(Float32Array, value), cas };
|
|
1093
|
+
case 3402235930 /* FLOAT64ARRAY */:
|
|
1094
|
+
return { value: makeTypedArray(Float64Array, value), cas };
|
|
1095
|
+
case 0 /* BUFFER */:
|
|
1096
|
+
default:
|
|
1097
|
+
return { value: Buffer.from(value), cas };
|
|
1098
|
+
}
|
|
1099
|
+
} finally {
|
|
1100
|
+
result.recycle();
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
1180
1103
|
function makeTypedArray(constructor, source) {
|
|
1181
1104
|
const clone = Buffer.from(source);
|
|
1182
1105
|
const { buffer, byteOffset, byteLength } = clone;
|
|
1183
1106
|
return new constructor(buffer, byteOffset, byteLength / constructor.BYTES_PER_ELEMENT);
|
|
1184
1107
|
}
|
|
1185
|
-
var
|
|
1108
|
+
var MemxClient = class {
|
|
1186
1109
|
#adapter;
|
|
1187
1110
|
#prefix;
|
|
1188
1111
|
constructor(adapterOrOptions) {
|
|
@@ -1194,7 +1117,7 @@ var Client = class {
|
|
|
1194
1117
|
this.#adapter = new ClusterAdapter(adapterOrOptions);
|
|
1195
1118
|
}
|
|
1196
1119
|
this.#prefix = "";
|
|
1197
|
-
(0,
|
|
1120
|
+
(0, import_assert5.default)(this.#adapter, "Invalid client constructor arguments");
|
|
1198
1121
|
}
|
|
1199
1122
|
get adapter() {
|
|
1200
1123
|
return this.#adapter;
|
|
@@ -1203,59 +1126,26 @@ var Client = class {
|
|
|
1203
1126
|
return this.#prefix;
|
|
1204
1127
|
}
|
|
1205
1128
|
withPrefix(prefix) {
|
|
1206
|
-
(0,
|
|
1207
|
-
const client = new
|
|
1129
|
+
(0, import_assert5.default)(prefix, "Invalid prefix");
|
|
1130
|
+
const client = new MemxClient(this.#adapter);
|
|
1208
1131
|
client.#prefix = prefix;
|
|
1209
1132
|
return client;
|
|
1210
1133
|
}
|
|
1211
|
-
async get(key
|
|
1212
|
-
const result = await this.#adapter.get(this.#prefix + key
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
case 3402235918 /* NULL */:
|
|
1227
|
-
return { value: null, cas };
|
|
1228
|
-
case 3402235919 /* JSON */:
|
|
1229
|
-
return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
|
|
1230
|
-
case 3402235920 /* UINT8ARRAY */:
|
|
1231
|
-
return { value: makeTypedArray(Uint8Array, value), cas };
|
|
1232
|
-
case 3402235921 /* UINT8CLAMPEDARRAY */:
|
|
1233
|
-
return { value: makeTypedArray(Uint8ClampedArray, value), cas };
|
|
1234
|
-
case 3402235922 /* UINT16ARRAY */:
|
|
1235
|
-
return { value: makeTypedArray(Uint16Array, value), cas };
|
|
1236
|
-
case 3402235923 /* UINT32ARRAY */:
|
|
1237
|
-
return { value: makeTypedArray(Uint32Array, value), cas };
|
|
1238
|
-
case 3402235924 /* INT8ARRAY */:
|
|
1239
|
-
return { value: makeTypedArray(Int8Array, value), cas };
|
|
1240
|
-
case 3402235925 /* INT16ARRAY */:
|
|
1241
|
-
return { value: makeTypedArray(Int16Array, value), cas };
|
|
1242
|
-
case 3402235926 /* INT32ARRAY */:
|
|
1243
|
-
return { value: makeTypedArray(Int32Array, value), cas };
|
|
1244
|
-
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1245
|
-
return { value: makeTypedArray(BigUint64Array, value), cas };
|
|
1246
|
-
case 3402235928 /* BIGINT64ARRAY */:
|
|
1247
|
-
return { value: makeTypedArray(BigInt64Array, value), cas };
|
|
1248
|
-
case 3402235929 /* FLOAT32ARRAY */:
|
|
1249
|
-
return { value: makeTypedArray(Float32Array, value), cas };
|
|
1250
|
-
case 3402235930 /* FLOAT64ARRAY */:
|
|
1251
|
-
return { value: makeTypedArray(Float64Array, value), cas };
|
|
1252
|
-
case 0 /* BUFFER */:
|
|
1253
|
-
default:
|
|
1254
|
-
return { value: Buffer.from(value), cas };
|
|
1255
|
-
}
|
|
1256
|
-
} finally {
|
|
1257
|
-
result.recycle();
|
|
1258
|
-
}
|
|
1134
|
+
async get(key) {
|
|
1135
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1136
|
+
return result && fromBuffer(result).value;
|
|
1137
|
+
}
|
|
1138
|
+
async gat(key, ttl) {
|
|
1139
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1140
|
+
return result && fromBuffer(result).value;
|
|
1141
|
+
}
|
|
1142
|
+
async getc(key) {
|
|
1143
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1144
|
+
return result && fromBuffer(result);
|
|
1145
|
+
}
|
|
1146
|
+
async gatc(key, ttl) {
|
|
1147
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1148
|
+
return result && fromBuffer(result);
|
|
1259
1149
|
}
|
|
1260
1150
|
async set(key, value, options) {
|
|
1261
1151
|
return this.#adapter.set(this.#prefix + key, ...toBuffer(value, options));
|
|
@@ -1311,23 +1201,177 @@ var Client = class {
|
|
|
1311
1201
|
}
|
|
1312
1202
|
};
|
|
1313
1203
|
|
|
1204
|
+
// src/fake.ts
|
|
1205
|
+
function toExp(ttl = 0) {
|
|
1206
|
+
if (ttl === 0)
|
|
1207
|
+
return Number.MAX_SAFE_INTEGER;
|
|
1208
|
+
return Date.now() + ttl * 1e3;
|
|
1209
|
+
}
|
|
1210
|
+
var FakeAdapter = class {
|
|
1211
|
+
#cache = /* @__PURE__ */ new Map();
|
|
1212
|
+
#cas = 1n;
|
|
1213
|
+
ttl = 0;
|
|
1214
|
+
#get(key) {
|
|
1215
|
+
if (key.length > 250)
|
|
1216
|
+
throw new TypeError(`Key too long (len=${key.length})`);
|
|
1217
|
+
const entry = this.#cache.get(key);
|
|
1218
|
+
if (!entry)
|
|
1219
|
+
return;
|
|
1220
|
+
if (Date.now() > entry.exp) {
|
|
1221
|
+
this.#cache.delete(key);
|
|
1222
|
+
return;
|
|
1223
|
+
}
|
|
1224
|
+
return entry;
|
|
1225
|
+
}
|
|
1226
|
+
#set(key, value, flags, ttl) {
|
|
1227
|
+
this.#cache.set(key, {
|
|
1228
|
+
value,
|
|
1229
|
+
flags: flags || 0,
|
|
1230
|
+
cas: ++this.#cas,
|
|
1231
|
+
exp: toExp(ttl)
|
|
1232
|
+
});
|
|
1233
|
+
return this.#cas;
|
|
1234
|
+
}
|
|
1235
|
+
async get(key) {
|
|
1236
|
+
const entry = this.#get(key);
|
|
1237
|
+
if (!entry)
|
|
1238
|
+
return;
|
|
1239
|
+
return {
|
|
1240
|
+
value: entry.value,
|
|
1241
|
+
flags: entry.flags,
|
|
1242
|
+
cas: entry.cas,
|
|
1243
|
+
recycle: () => void 0
|
|
1244
|
+
};
|
|
1245
|
+
}
|
|
1246
|
+
async gat(key, ttl) {
|
|
1247
|
+
const entry = this.#get(key);
|
|
1248
|
+
if (!entry)
|
|
1249
|
+
return;
|
|
1250
|
+
entry.exp = toExp(ttl);
|
|
1251
|
+
return {
|
|
1252
|
+
value: entry.value,
|
|
1253
|
+
flags: entry.flags,
|
|
1254
|
+
cas: entry.cas,
|
|
1255
|
+
recycle: () => void 0
|
|
1256
|
+
};
|
|
1257
|
+
}
|
|
1258
|
+
async touch(key, ttl) {
|
|
1259
|
+
const entry = this.#get(key);
|
|
1260
|
+
if (entry)
|
|
1261
|
+
entry.exp = toExp(ttl);
|
|
1262
|
+
return !!entry;
|
|
1263
|
+
}
|
|
1264
|
+
async set(key, value, options = {}) {
|
|
1265
|
+
const entry = this.#get(key);
|
|
1266
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1270
|
+
}
|
|
1271
|
+
async add(key, value, options = {}) {
|
|
1272
|
+
if (this.#get(key))
|
|
1273
|
+
return;
|
|
1274
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1275
|
+
}
|
|
1276
|
+
async replace(key, value, options = {}) {
|
|
1277
|
+
if (!this.#get(key))
|
|
1278
|
+
return;
|
|
1279
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
1280
|
+
}
|
|
1281
|
+
async append(key, value, options = {}) {
|
|
1282
|
+
const entry = this.#get(key);
|
|
1283
|
+
if (!entry)
|
|
1284
|
+
return false;
|
|
1285
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1286
|
+
return false;
|
|
1287
|
+
entry.value = Buffer.concat([entry.value, value]);
|
|
1288
|
+
return true;
|
|
1289
|
+
}
|
|
1290
|
+
async prepend(key, value, options = {}) {
|
|
1291
|
+
const entry = this.#get(key);
|
|
1292
|
+
if (!entry)
|
|
1293
|
+
return false;
|
|
1294
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1295
|
+
return false;
|
|
1296
|
+
entry.value = Buffer.concat([value, entry.value]);
|
|
1297
|
+
return true;
|
|
1298
|
+
}
|
|
1299
|
+
async #counter(key, delta, options) {
|
|
1300
|
+
const entry = this.#get(key);
|
|
1301
|
+
if (!entry) {
|
|
1302
|
+
if (options.initial !== void 0) {
|
|
1303
|
+
const value = Buffer.from(options.initial.toString());
|
|
1304
|
+
this.#set(key, value, void 0, options.ttl);
|
|
1305
|
+
return { value: BigInt(options.initial), cas: this.#cas };
|
|
1306
|
+
} else {
|
|
1307
|
+
return;
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
1311
|
+
return;
|
|
1312
|
+
try {
|
|
1313
|
+
const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
|
|
1314
|
+
this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
|
|
1315
|
+
return { value, cas: this.#cas };
|
|
1316
|
+
} catch (error) {
|
|
1317
|
+
throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
increment(key, delta = 1n, options = {}) {
|
|
1321
|
+
return this.#counter(key, delta, options);
|
|
1322
|
+
}
|
|
1323
|
+
decrement(key, delta = 1n, options = {}) {
|
|
1324
|
+
return this.#counter(key, -delta, options);
|
|
1325
|
+
}
|
|
1326
|
+
async delete(key, options = {}) {
|
|
1327
|
+
const entry = this.#get(key);
|
|
1328
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
1329
|
+
return false;
|
|
1330
|
+
}
|
|
1331
|
+
return this.#cache.delete(key);
|
|
1332
|
+
}
|
|
1333
|
+
async flush(ttl) {
|
|
1334
|
+
if (!ttl)
|
|
1335
|
+
return this.#cache.clear();
|
|
1336
|
+
const wait = toExp(ttl) - Date.now();
|
|
1337
|
+
setTimeout(() => this.#cache.clear(), wait);
|
|
1338
|
+
}
|
|
1339
|
+
async noop() {
|
|
1340
|
+
}
|
|
1341
|
+
async quit() {
|
|
1342
|
+
}
|
|
1343
|
+
async version() {
|
|
1344
|
+
return { fake: "0.0.0-fake" };
|
|
1345
|
+
}
|
|
1346
|
+
async stats() {
|
|
1347
|
+
return { fake: { version: "0.0.0-fake" } };
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
var MemxFakeClient = class extends MemxClient {
|
|
1351
|
+
constructor() {
|
|
1352
|
+
super(new FakeAdapter());
|
|
1353
|
+
}
|
|
1354
|
+
};
|
|
1355
|
+
|
|
1314
1356
|
// src/utils.ts
|
|
1315
|
-
var
|
|
1357
|
+
var import_assert6 = __toESM(require("assert"));
|
|
1316
1358
|
var Factory = class {
|
|
1317
1359
|
#factory;
|
|
1318
1360
|
#client;
|
|
1319
1361
|
#ttl;
|
|
1320
1362
|
constructor(client, factory, ttl) {
|
|
1321
|
-
(0,
|
|
1322
|
-
(0,
|
|
1363
|
+
(0, import_assert6.default)(typeof factory === "function", "Invalid or no factory specified");
|
|
1364
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1323
1365
|
this.#factory = factory;
|
|
1324
1366
|
this.#client = client;
|
|
1325
1367
|
this.#ttl = ttl;
|
|
1326
1368
|
}
|
|
1327
1369
|
async get(key) {
|
|
1328
|
-
const cached = await this.#client.
|
|
1329
|
-
if (cached)
|
|
1370
|
+
const cached = await this.#client.getc(key);
|
|
1371
|
+
if (cached) {
|
|
1372
|
+
void logPromiseError(this.#client.touch(key), `Factory error touching key "${this.#client.prefix}${key}"`);
|
|
1330
1373
|
return cached.value;
|
|
1374
|
+
}
|
|
1331
1375
|
const created = await this.#factory(key);
|
|
1332
1376
|
if (created) {
|
|
1333
1377
|
void logPromiseError(this.#client.set(key, created, { ttl: this.#ttl }), `Factory error setting key "${this.#client.prefix}${key}"`);
|
|
@@ -1340,8 +1384,8 @@ var Bundle = class {
|
|
|
1340
1384
|
#name;
|
|
1341
1385
|
#ttl;
|
|
1342
1386
|
constructor(client, name, ttl) {
|
|
1343
|
-
(0,
|
|
1344
|
-
(0,
|
|
1387
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1388
|
+
(0, import_assert6.default)(name, "No bundle name specified");
|
|
1345
1389
|
this.#client = client;
|
|
1346
1390
|
this.#name = name;
|
|
1347
1391
|
this.#ttl = ttl || 0;
|
|
@@ -1357,7 +1401,7 @@ var Bundle = class {
|
|
|
1357
1401
|
}
|
|
1358
1402
|
async #removeKey(key) {
|
|
1359
1403
|
await logPromiseError((async () => {
|
|
1360
|
-
const result = await this.#client.
|
|
1404
|
+
const result = await this.#client.getc(this.#name);
|
|
1361
1405
|
if (!result)
|
|
1362
1406
|
return;
|
|
1363
1407
|
const keys = result.value.split("\0").filter((k) => k !== key).join("\0");
|
|
@@ -1369,7 +1413,7 @@ var Bundle = class {
|
|
|
1369
1413
|
await this.#appendKey(key);
|
|
1370
1414
|
}
|
|
1371
1415
|
async get(key) {
|
|
1372
|
-
const result = await this.#client.
|
|
1416
|
+
const result = await this.#client.getc(`${this.#name}:${key}`);
|
|
1373
1417
|
if (result)
|
|
1374
1418
|
return result.value;
|
|
1375
1419
|
await this.#removeKey(key);
|
|
@@ -1379,13 +1423,13 @@ var Bundle = class {
|
|
|
1379
1423
|
await this.#removeKey(key);
|
|
1380
1424
|
}
|
|
1381
1425
|
async list() {
|
|
1382
|
-
const result = await this.#client.
|
|
1426
|
+
const result = await this.#client.getc(this.#name);
|
|
1383
1427
|
if (!result)
|
|
1384
1428
|
return {};
|
|
1385
1429
|
const results = {};
|
|
1386
1430
|
const promises = [];
|
|
1387
1431
|
for (const key of new Set(result.value.split("\0"))) {
|
|
1388
|
-
promises.push(this.#client.
|
|
1432
|
+
promises.push(this.#client.getc(`${this.#name}:${key}`).then((result2) => {
|
|
1389
1433
|
if (result2)
|
|
1390
1434
|
results[key] = result2.value;
|
|
1391
1435
|
}));
|
|
@@ -1399,8 +1443,8 @@ var PoorManLock = class {
|
|
|
1399
1443
|
#client;
|
|
1400
1444
|
#name;
|
|
1401
1445
|
constructor(client, name) {
|
|
1402
|
-
(0,
|
|
1403
|
-
(0,
|
|
1446
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1447
|
+
(0, import_assert6.default)(name, "No lock name specified");
|
|
1404
1448
|
this.#client = client;
|
|
1405
1449
|
this.#name = name;
|
|
1406
1450
|
}
|
|
@@ -1415,14 +1459,14 @@ var PoorManLock = class {
|
|
|
1415
1459
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1416
1460
|
} while (Date.now() < end);
|
|
1417
1461
|
if (cas === void 0) {
|
|
1418
|
-
const other = await this.#client.
|
|
1462
|
+
const other = await this.#client.getc(this.#name);
|
|
1419
1463
|
const owner2 = other && other.value ? `"${other.value}"` : "anonymous";
|
|
1420
1464
|
throw new Error(`Lock "${this.#client.prefix}${this.#name}" timeout (owner=${owner2})`);
|
|
1421
1465
|
}
|
|
1422
1466
|
const interval = setInterval(() => {
|
|
1423
1467
|
void logPromiseError((async () => {
|
|
1424
1468
|
const replaced = await this.#client.replace(this.#name, owner, { ttl: 2, cas });
|
|
1425
|
-
(0,
|
|
1469
|
+
(0, import_assert6.default)(replaced !== void 0, `Lock "${this.#client.prefix}${this.#name}" not replaced`);
|
|
1426
1470
|
cas = replaced;
|
|
1427
1471
|
})(), `Error extending lock "${this.#client.prefix}${this.#name}"`);
|
|
1428
1472
|
}, 100);
|
|
@@ -1437,10 +1481,11 @@ var PoorManLock = class {
|
|
|
1437
1481
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1438
1482
|
0 && (module.exports = {
|
|
1439
1483
|
Bundle,
|
|
1440
|
-
Client,
|
|
1441
1484
|
ClusterAdapter,
|
|
1442
1485
|
Factory,
|
|
1443
1486
|
FakeAdapter,
|
|
1487
|
+
MemxClient,
|
|
1488
|
+
MemxFakeClient,
|
|
1444
1489
|
PoorManLock,
|
|
1445
1490
|
ServerAdapter,
|
|
1446
1491
|
connection,
|