memx 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/index.js +436 -94
- package/dist/index.js.map +2 -2
- package/dist/index.mjs +421 -76
- package/dist/index.mjs.map +2 -2
- package/index.d.ts +147 -68
- package/package.json +7 -7
- package/src/buffers.ts +9 -0
- package/src/client.ts +152 -78
- package/src/cluster.ts +24 -12
- package/src/connection.ts +1 -1
- package/src/encode.ts +1 -1
- package/src/fake.ts +222 -0
- package/src/index.ts +4 -0
- package/src/internals.ts +5 -0
- package/src/server.ts +28 -17
- package/src/types.ts +15 -9
- package/src/utils.ts +161 -0
package/README.md
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
# MEMX
|
|
2
|
+
Simple and fast memcached client
|
package/dist/index.js
CHANGED
|
@@ -21,39 +21,37 @@ var __spreadValues = (a, b) => {
|
|
|
21
21
|
return a;
|
|
22
22
|
};
|
|
23
23
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
-
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
25
24
|
var __export = (target, all) => {
|
|
26
25
|
for (var name in all)
|
|
27
26
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
28
27
|
};
|
|
29
|
-
var
|
|
30
|
-
if (
|
|
31
|
-
for (let key of __getOwnPropNames(
|
|
32
|
-
if (!__hasOwnProp.call(
|
|
33
|
-
__defProp(
|
|
28
|
+
var __copyProps = (to, from, except, desc) => {
|
|
29
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
30
|
+
for (let key of __getOwnPropNames(from))
|
|
31
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
32
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
34
33
|
}
|
|
35
|
-
return
|
|
34
|
+
return to;
|
|
36
35
|
};
|
|
37
|
-
var __toESM = (
|
|
38
|
-
|
|
39
|
-
};
|
|
40
|
-
var __toCommonJS = /* @__PURE__ */ ((cache) => {
|
|
41
|
-
return (module2, temp) => {
|
|
42
|
-
return cache && cache.get(module2) || (temp = __reExport(__markAsModule({}), module2, 1), cache && cache.set(module2, temp), temp);
|
|
43
|
-
};
|
|
44
|
-
})(typeof WeakMap !== "undefined" ? /* @__PURE__ */ new WeakMap() : 0);
|
|
36
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
37
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
45
38
|
|
|
46
39
|
// src/index.ts
|
|
47
40
|
var src_exports = {};
|
|
48
41
|
__export(src_exports, {
|
|
42
|
+
Bundle: () => Bundle,
|
|
49
43
|
Client: () => Client,
|
|
50
44
|
ClusterAdapter: () => ClusterAdapter,
|
|
45
|
+
Factory: () => Factory,
|
|
46
|
+
FakeAdapter: () => FakeAdapter,
|
|
47
|
+
PoorManLock: () => PoorManLock,
|
|
51
48
|
ServerAdapter: () => ServerAdapter,
|
|
52
49
|
connection: () => connection_exports,
|
|
53
50
|
constants: () => constants_exports,
|
|
54
51
|
decode: () => decode_exports,
|
|
55
52
|
encode: () => encode_exports
|
|
56
53
|
});
|
|
54
|
+
module.exports = __toCommonJS(src_exports);
|
|
57
55
|
|
|
58
56
|
// src/decode.ts
|
|
59
57
|
var decode_exports = {};
|
|
@@ -316,6 +314,9 @@ function typedArrayFlags(value) {
|
|
|
316
314
|
const flags = (0, import_types.isUint8Array)(value) ? 3402235920 /* UINT8ARRAY */ : (0, import_types.isUint8ClampedArray)(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : (0, import_types.isUint16Array)(value) ? 3402235922 /* UINT16ARRAY */ : (0, import_types.isUint32Array)(value) ? 3402235923 /* UINT32ARRAY */ : (0, import_types.isInt8Array)(value) ? 3402235924 /* INT8ARRAY */ : (0, import_types.isInt16Array)(value) ? 3402235925 /* INT16ARRAY */ : (0, import_types.isInt32Array)(value) ? 3402235926 /* INT32ARRAY */ : (0, import_types.isBigUint64Array)(value) ? 3402235927 /* BIGUINT64ARRAY */ : (0, import_types.isBigInt64Array)(value) ? 3402235928 /* BIGINT64ARRAY */ : (0, import_types.isFloat32Array)(value) ? 3402235929 /* FLOAT32ARRAY */ : (0, import_types.isFloat64Array)(value) ? 3402235930 /* FLOAT64ARRAY */ : import_assert2.default.fail("Unsupported kind of TypedArray");
|
|
317
315
|
return flags;
|
|
318
316
|
}
|
|
317
|
+
function logPromiseError(promise, message) {
|
|
318
|
+
return promise.catch((error) => console.log(message, error)).then(() => void 0);
|
|
319
|
+
}
|
|
319
320
|
|
|
320
321
|
// src/connection.ts
|
|
321
322
|
var import_assert3 = __toESM(require("assert"));
|
|
@@ -459,6 +460,153 @@ var Connection = class {
|
|
|
459
460
|
}
|
|
460
461
|
};
|
|
461
462
|
|
|
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
|
+
ttl = 0;
|
|
473
|
+
#get(key) {
|
|
474
|
+
if (key.length > 250)
|
|
475
|
+
throw new TypeError(`Key too long (len=${key.length})`);
|
|
476
|
+
const entry = this.#cache.get(key);
|
|
477
|
+
if (!entry)
|
|
478
|
+
return;
|
|
479
|
+
if (Date.now() > entry.exp) {
|
|
480
|
+
this.#cache.delete(key);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
483
|
+
return entry;
|
|
484
|
+
}
|
|
485
|
+
#set(key, value, flags, ttl) {
|
|
486
|
+
this.#cache.set(key, {
|
|
487
|
+
value,
|
|
488
|
+
flags: flags || 0,
|
|
489
|
+
cas: ++this.#cas,
|
|
490
|
+
exp: toExp(ttl)
|
|
491
|
+
});
|
|
492
|
+
return this.#cas;
|
|
493
|
+
}
|
|
494
|
+
async get(key) {
|
|
495
|
+
const entry = this.#get(key);
|
|
496
|
+
if (!entry)
|
|
497
|
+
return;
|
|
498
|
+
return {
|
|
499
|
+
value: entry.value,
|
|
500
|
+
flags: entry.flags,
|
|
501
|
+
cas: entry.cas,
|
|
502
|
+
recycle: () => void 0
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
async gat(key, ttl) {
|
|
506
|
+
const entry = this.#get(key);
|
|
507
|
+
if (!entry)
|
|
508
|
+
return;
|
|
509
|
+
entry.exp = toExp(ttl);
|
|
510
|
+
return {
|
|
511
|
+
value: entry.value,
|
|
512
|
+
flags: entry.flags,
|
|
513
|
+
cas: entry.cas,
|
|
514
|
+
recycle: () => void 0
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
async touch(key, ttl) {
|
|
518
|
+
const entry = this.#get(key);
|
|
519
|
+
if (entry)
|
|
520
|
+
entry.exp = toExp(ttl);
|
|
521
|
+
return !!entry;
|
|
522
|
+
}
|
|
523
|
+
async set(key, value, options = {}) {
|
|
524
|
+
const entry = this.#get(key);
|
|
525
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
529
|
+
}
|
|
530
|
+
async add(key, value, options = {}) {
|
|
531
|
+
if (this.#get(key))
|
|
532
|
+
return;
|
|
533
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
534
|
+
}
|
|
535
|
+
async replace(key, value, options = {}) {
|
|
536
|
+
if (!this.#get(key))
|
|
537
|
+
return;
|
|
538
|
+
return this.#set(key, value, options.flags, options.ttl);
|
|
539
|
+
}
|
|
540
|
+
async append(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([entry.value, value]);
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
async prepend(key, value, options = {}) {
|
|
550
|
+
const entry = this.#get(key);
|
|
551
|
+
if (!entry)
|
|
552
|
+
return false;
|
|
553
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
554
|
+
return false;
|
|
555
|
+
entry.value = Buffer.concat([value, entry.value]);
|
|
556
|
+
return true;
|
|
557
|
+
}
|
|
558
|
+
async #counter(key, delta, options) {
|
|
559
|
+
const entry = this.#get(key);
|
|
560
|
+
if (!entry) {
|
|
561
|
+
if (options.initial !== void 0) {
|
|
562
|
+
const value = Buffer.from(options.initial.toString());
|
|
563
|
+
this.#set(key, value, void 0, options.ttl);
|
|
564
|
+
return { value: BigInt(options.initial), cas: this.#cas };
|
|
565
|
+
} else {
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
if (options.cas !== void 0 && options.cas !== entry.cas)
|
|
570
|
+
return;
|
|
571
|
+
try {
|
|
572
|
+
const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
|
|
573
|
+
this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
|
|
574
|
+
return { value, cas: this.#cas };
|
|
575
|
+
} catch (error) {
|
|
576
|
+
throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
increment(key, delta = 1n, options = {}) {
|
|
580
|
+
return this.#counter(key, delta, options);
|
|
581
|
+
}
|
|
582
|
+
decrement(key, delta = 1n, options = {}) {
|
|
583
|
+
return this.#counter(key, -delta, options);
|
|
584
|
+
}
|
|
585
|
+
async delete(key, options = {}) {
|
|
586
|
+
const entry = this.#get(key);
|
|
587
|
+
if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
|
|
588
|
+
return false;
|
|
589
|
+
}
|
|
590
|
+
return this.#cache.delete(key);
|
|
591
|
+
}
|
|
592
|
+
async flush(ttl) {
|
|
593
|
+
if (!ttl)
|
|
594
|
+
return this.#cache.clear();
|
|
595
|
+
const wait = toExp(ttl) - Date.now();
|
|
596
|
+
setTimeout(() => this.#cache.clear(), wait);
|
|
597
|
+
}
|
|
598
|
+
async noop() {
|
|
599
|
+
}
|
|
600
|
+
async quit() {
|
|
601
|
+
}
|
|
602
|
+
async version() {
|
|
603
|
+
return { fake: "0.0.0-fake" };
|
|
604
|
+
}
|
|
605
|
+
async stats() {
|
|
606
|
+
return { fake: { version: "0.0.0-fake" } };
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
|
|
462
610
|
// src/server.ts
|
|
463
611
|
var statsBigInt = [
|
|
464
612
|
"auth_cmds",
|
|
@@ -606,10 +754,9 @@ var ServerAdapter = class {
|
|
|
606
754
|
throw new Error(`Key too long (len=${keyLength})`);
|
|
607
755
|
return keyLength;
|
|
608
756
|
}
|
|
609
|
-
async get(key,
|
|
610
|
-
const { ttl } = options;
|
|
757
|
+
async #get(key, ttl) {
|
|
611
758
|
let keyOffset = 0;
|
|
612
|
-
if (ttl)
|
|
759
|
+
if (ttl !== void 0)
|
|
613
760
|
keyOffset = this.#buffer.writeUInt32BE(ttl);
|
|
614
761
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
615
762
|
const [response] = await this.#connection.send({
|
|
@@ -635,9 +782,15 @@ var ServerAdapter = class {
|
|
|
635
782
|
fail(response, key);
|
|
636
783
|
}
|
|
637
784
|
}
|
|
638
|
-
async
|
|
639
|
-
|
|
640
|
-
|
|
785
|
+
async get(key) {
|
|
786
|
+
return this.#get(key);
|
|
787
|
+
}
|
|
788
|
+
async gat(key, ttl) {
|
|
789
|
+
return this.#get(key, ttl || 2592e3);
|
|
790
|
+
}
|
|
791
|
+
async touch(key, ttl) {
|
|
792
|
+
const timeToLive = ttl ?? this.#ttl;
|
|
793
|
+
const keyOffset = this.#buffer.writeUInt32BE(timeToLive);
|
|
641
794
|
const keyLength = this.#writeKey(key, keyOffset);
|
|
642
795
|
const [response] = await this.#connection.send({
|
|
643
796
|
opcode: 28 /* TOUCH */,
|
|
@@ -884,6 +1037,7 @@ var ServerAdapter = class {
|
|
|
884
1037
|
};
|
|
885
1038
|
|
|
886
1039
|
// src/cluster.ts
|
|
1040
|
+
var import_assert4 = __toESM(require("assert"));
|
|
887
1041
|
function parseHosts(hosts) {
|
|
888
1042
|
const result = [];
|
|
889
1043
|
if (!hosts)
|
|
@@ -897,6 +1051,7 @@ function parseHosts(hosts) {
|
|
|
897
1051
|
}
|
|
898
1052
|
var ClusterAdapter = class {
|
|
899
1053
|
servers;
|
|
1054
|
+
ttl;
|
|
900
1055
|
constructor(serversOrOptions) {
|
|
901
1056
|
if (Array.isArray(serversOrOptions)) {
|
|
902
1057
|
this.servers = [...serversOrOptions];
|
|
@@ -924,6 +1079,10 @@ var ClusterAdapter = class {
|
|
|
924
1079
|
throw new Error("No hosts configured");
|
|
925
1080
|
if (this.servers.length === 1)
|
|
926
1081
|
this.server = () => this.servers[0];
|
|
1082
|
+
this.ttl = this.servers[0].ttl;
|
|
1083
|
+
this.servers.slice(1).forEach((server) => {
|
|
1084
|
+
import_assert4.default.equal(server.ttl, this.ttl, `TTL Mismatch (${server.ttl} != ${this.ttl})`);
|
|
1085
|
+
});
|
|
927
1086
|
Object.freeze(this.servers);
|
|
928
1087
|
}
|
|
929
1088
|
server(key) {
|
|
@@ -933,11 +1092,14 @@ var ClusterAdapter = class {
|
|
|
933
1092
|
hash = hash * 31 + key.charCodeAt(i);
|
|
934
1093
|
return this.servers[hash % this.servers.length];
|
|
935
1094
|
}
|
|
936
|
-
get(key
|
|
937
|
-
return this.server(key).get(key
|
|
1095
|
+
get(key) {
|
|
1096
|
+
return this.server(key).get(key);
|
|
938
1097
|
}
|
|
939
|
-
|
|
940
|
-
return this.server(key).
|
|
1098
|
+
gat(key, ttl) {
|
|
1099
|
+
return this.server(key).gat(key, ttl);
|
|
1100
|
+
}
|
|
1101
|
+
touch(key, ttl) {
|
|
1102
|
+
return this.server(key).touch(key, ttl);
|
|
941
1103
|
}
|
|
942
1104
|
set(key, value, options) {
|
|
943
1105
|
return this.server(key).set(key, value, options);
|
|
@@ -983,8 +1145,34 @@ var ClusterAdapter = class {
|
|
|
983
1145
|
};
|
|
984
1146
|
|
|
985
1147
|
// src/client.ts
|
|
986
|
-
var
|
|
987
|
-
var
|
|
1148
|
+
var import_assert5 = __toESM(require("assert"));
|
|
1149
|
+
var import_types5 = require("util/types");
|
|
1150
|
+
function replacer(key, value) {
|
|
1151
|
+
if (typeof this[key] === "bigint")
|
|
1152
|
+
return ["\0__$BIGINT$__\0", this[key].toString()];
|
|
1153
|
+
if (this[key] instanceof Date)
|
|
1154
|
+
return ["\0__$DATE$__\0", this[key].toISOString()];
|
|
1155
|
+
if (this[key] instanceof Set)
|
|
1156
|
+
return ["\0__$SET$__\0", ...value];
|
|
1157
|
+
if (this[key] instanceof Map)
|
|
1158
|
+
return ["\0__$MAP$__\0", ...value.entries()];
|
|
1159
|
+
return value;
|
|
1160
|
+
}
|
|
1161
|
+
function reviver(key, value) {
|
|
1162
|
+
if (Array.isArray(value)) {
|
|
1163
|
+
switch (value[0]) {
|
|
1164
|
+
case "\0__$BIGINT$__\0":
|
|
1165
|
+
return BigInt(value[1]);
|
|
1166
|
+
case "\0__$DATE$__\0":
|
|
1167
|
+
return new Date(value[1]);
|
|
1168
|
+
case "\0__$SET$__\0":
|
|
1169
|
+
return new Set(value.slice(1));
|
|
1170
|
+
case "\0__$MAP$__\0":
|
|
1171
|
+
return new Map(value.slice(1));
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
return value;
|
|
1175
|
+
}
|
|
988
1176
|
function toBuffer(value, options) {
|
|
989
1177
|
if (Buffer.isBuffer(value))
|
|
990
1178
|
return [value, __spreadProps(__spreadValues({}, options), { flags: 0 /* BUFFER */ })];
|
|
@@ -1000,24 +1188,72 @@ function toBuffer(value, options) {
|
|
|
1000
1188
|
case "object":
|
|
1001
1189
|
break;
|
|
1002
1190
|
default:
|
|
1003
|
-
|
|
1191
|
+
import_assert5.default.fail(`Unable to store value of type "${typeof value}"`);
|
|
1004
1192
|
}
|
|
1005
|
-
if ((0,
|
|
1193
|
+
if ((0, import_types5.isTypedArray)(value)) {
|
|
1006
1194
|
const flags = typedArrayFlags(value);
|
|
1007
1195
|
const buffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
|
|
1008
1196
|
return [buffer, __spreadProps(__spreadValues({}, options), { flags })];
|
|
1009
1197
|
}
|
|
1010
1198
|
if (value === null)
|
|
1011
1199
|
return [EMPTY_BUFFER, __spreadProps(__spreadValues({}, options), { flags: 3402235918 /* NULL */ })];
|
|
1012
|
-
|
|
1200
|
+
const json = JSON.stringify(value, replacer);
|
|
1201
|
+
return [Buffer.from(json, "utf-8"), __spreadProps(__spreadValues({}, options), { flags: 3402235919 /* JSON */ })];
|
|
1013
1202
|
}
|
|
1014
|
-
function
|
|
1203
|
+
function fromBuffer(result) {
|
|
1204
|
+
try {
|
|
1205
|
+
const { flags, value, cas } = result;
|
|
1206
|
+
switch (flags) {
|
|
1207
|
+
case 3402235904 /* BIGINT */:
|
|
1208
|
+
return { value: BigInt(value.toString("utf-8")), cas };
|
|
1209
|
+
case 3402235905 /* BOOLEAN */:
|
|
1210
|
+
return { value: !!value[0], cas };
|
|
1211
|
+
case 3402235906 /* NUMBER */:
|
|
1212
|
+
return { value: Number(value.toString("utf-8")), cas };
|
|
1213
|
+
case 3402235907 /* STRING */:
|
|
1214
|
+
return { value: value.toString("utf-8"), cas };
|
|
1215
|
+
case 3402235918 /* NULL */:
|
|
1216
|
+
return { value: null, cas };
|
|
1217
|
+
case 3402235919 /* JSON */:
|
|
1218
|
+
return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
|
|
1219
|
+
case 3402235920 /* UINT8ARRAY */:
|
|
1220
|
+
return { value: makeTypedArray(Uint8Array, value), cas };
|
|
1221
|
+
case 3402235921 /* UINT8CLAMPEDARRAY */:
|
|
1222
|
+
return { value: makeTypedArray(Uint8ClampedArray, value), cas };
|
|
1223
|
+
case 3402235922 /* UINT16ARRAY */:
|
|
1224
|
+
return { value: makeTypedArray(Uint16Array, value), cas };
|
|
1225
|
+
case 3402235923 /* UINT32ARRAY */:
|
|
1226
|
+
return { value: makeTypedArray(Uint32Array, value), cas };
|
|
1227
|
+
case 3402235924 /* INT8ARRAY */:
|
|
1228
|
+
return { value: makeTypedArray(Int8Array, value), cas };
|
|
1229
|
+
case 3402235925 /* INT16ARRAY */:
|
|
1230
|
+
return { value: makeTypedArray(Int16Array, value), cas };
|
|
1231
|
+
case 3402235926 /* INT32ARRAY */:
|
|
1232
|
+
return { value: makeTypedArray(Int32Array, value), cas };
|
|
1233
|
+
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1234
|
+
return { value: makeTypedArray(BigUint64Array, value), cas };
|
|
1235
|
+
case 3402235928 /* BIGINT64ARRAY */:
|
|
1236
|
+
return { value: makeTypedArray(BigInt64Array, value), cas };
|
|
1237
|
+
case 3402235929 /* FLOAT32ARRAY */:
|
|
1238
|
+
return { value: makeTypedArray(Float32Array, value), cas };
|
|
1239
|
+
case 3402235930 /* FLOAT64ARRAY */:
|
|
1240
|
+
return { value: makeTypedArray(Float64Array, value), cas };
|
|
1241
|
+
case 0 /* BUFFER */:
|
|
1242
|
+
default:
|
|
1243
|
+
return { value: Buffer.from(value), cas };
|
|
1244
|
+
}
|
|
1245
|
+
} finally {
|
|
1246
|
+
result.recycle();
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
function makeTypedArray(constructor, source) {
|
|
1015
1250
|
const clone = Buffer.from(source);
|
|
1016
1251
|
const { buffer, byteOffset, byteLength } = clone;
|
|
1017
|
-
return new constructor(buffer, byteOffset, byteLength /
|
|
1252
|
+
return new constructor(buffer, byteOffset, byteLength / constructor.BYTES_PER_ELEMENT);
|
|
1018
1253
|
}
|
|
1019
1254
|
var Client = class {
|
|
1020
1255
|
#adapter;
|
|
1256
|
+
#prefix;
|
|
1021
1257
|
constructor(adapterOrOptions) {
|
|
1022
1258
|
if (!adapterOrOptions) {
|
|
1023
1259
|
this.#adapter = new ClusterAdapter();
|
|
@@ -1026,96 +1262,73 @@ var Client = class {
|
|
|
1026
1262
|
} else if ("hosts" in adapterOrOptions) {
|
|
1027
1263
|
this.#adapter = new ClusterAdapter(adapterOrOptions);
|
|
1028
1264
|
}
|
|
1029
|
-
|
|
1265
|
+
this.#prefix = "";
|
|
1266
|
+
(0, import_assert5.default)(this.#adapter, "Invalid client constructor arguments");
|
|
1030
1267
|
}
|
|
1031
1268
|
get adapter() {
|
|
1032
1269
|
return this.#adapter;
|
|
1033
1270
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
return { value: makeTypedArray(Uint16Array, value, 2), cas };
|
|
1059
|
-
case 3402235923 /* UINT32ARRAY */:
|
|
1060
|
-
return { value: makeTypedArray(Uint32Array, value, 4), cas };
|
|
1061
|
-
case 3402235924 /* INT8ARRAY */:
|
|
1062
|
-
return { value: makeTypedArray(Int8Array, value, 1), cas };
|
|
1063
|
-
case 3402235925 /* INT16ARRAY */:
|
|
1064
|
-
return { value: makeTypedArray(Int16Array, value, 2), cas };
|
|
1065
|
-
case 3402235926 /* INT32ARRAY */:
|
|
1066
|
-
return { value: makeTypedArray(Int32Array, value, 4), cas };
|
|
1067
|
-
case 3402235927 /* BIGUINT64ARRAY */:
|
|
1068
|
-
return { value: makeTypedArray(BigUint64Array, value, 8), cas };
|
|
1069
|
-
case 3402235928 /* BIGINT64ARRAY */:
|
|
1070
|
-
return { value: makeTypedArray(BigInt64Array, value, 8), cas };
|
|
1071
|
-
case 3402235929 /* FLOAT32ARRAY */:
|
|
1072
|
-
return { value: makeTypedArray(Float32Array, value, 4), cas };
|
|
1073
|
-
case 3402235930 /* FLOAT64ARRAY */:
|
|
1074
|
-
return { value: makeTypedArray(Float64Array, value, 8), cas };
|
|
1075
|
-
case 0 /* BUFFER */:
|
|
1076
|
-
default:
|
|
1077
|
-
return { value: Buffer.from(value), cas };
|
|
1078
|
-
}
|
|
1079
|
-
} finally {
|
|
1080
|
-
result.recycle();
|
|
1081
|
-
}
|
|
1271
|
+
get prefix() {
|
|
1272
|
+
return this.#prefix;
|
|
1273
|
+
}
|
|
1274
|
+
withPrefix(prefix) {
|
|
1275
|
+
(0, import_assert5.default)(prefix, "Invalid prefix");
|
|
1276
|
+
const client = new Client(this.#adapter);
|
|
1277
|
+
client.#prefix = prefix;
|
|
1278
|
+
return client;
|
|
1279
|
+
}
|
|
1280
|
+
async get(key) {
|
|
1281
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1282
|
+
return result && fromBuffer(result).value;
|
|
1283
|
+
}
|
|
1284
|
+
async gat(key, ttl) {
|
|
1285
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1286
|
+
return result && fromBuffer(result).value;
|
|
1287
|
+
}
|
|
1288
|
+
async getc(key) {
|
|
1289
|
+
const result = await this.#adapter.get(this.#prefix + key);
|
|
1290
|
+
return result && fromBuffer(result);
|
|
1291
|
+
}
|
|
1292
|
+
async gatc(key, ttl) {
|
|
1293
|
+
const result = await this.#adapter.gat(this.#prefix + key, ttl);
|
|
1294
|
+
return result && fromBuffer(result);
|
|
1082
1295
|
}
|
|
1083
1296
|
async set(key, value, options) {
|
|
1084
|
-
return this.#adapter.set(key, ...toBuffer(value, options));
|
|
1297
|
+
return this.#adapter.set(this.#prefix + key, ...toBuffer(value, options));
|
|
1085
1298
|
}
|
|
1086
1299
|
async add(key, value, options) {
|
|
1087
|
-
return this.#adapter.add(key, ...toBuffer(value, options));
|
|
1300
|
+
return this.#adapter.add(this.#prefix + key, ...toBuffer(value, options));
|
|
1088
1301
|
}
|
|
1089
1302
|
async replace(key, value, options) {
|
|
1090
|
-
return this.#adapter.replace(key, ...toBuffer(value, options));
|
|
1303
|
+
return this.#adapter.replace(this.#prefix + key, ...toBuffer(value, options));
|
|
1091
1304
|
}
|
|
1092
1305
|
append(key, value, options) {
|
|
1093
|
-
return this.#adapter.append(key, ...toBuffer(value, options));
|
|
1306
|
+
return this.#adapter.append(this.#prefix + key, ...toBuffer(value, options));
|
|
1094
1307
|
}
|
|
1095
1308
|
prepend(key, value, options) {
|
|
1096
|
-
return this.#adapter.prepend(key, ...toBuffer(value, options));
|
|
1309
|
+
return this.#adapter.prepend(this.#prefix + key, ...toBuffer(value, options));
|
|
1097
1310
|
}
|
|
1098
1311
|
async increment(key, delta, options) {
|
|
1099
|
-
const counter = await this.#adapter.increment(key, delta, options);
|
|
1100
|
-
if (
|
|
1312
|
+
const counter = await this.#adapter.increment(this.#prefix + key, delta, options);
|
|
1313
|
+
if ((options == null ? void 0 : options.initial) !== void 0 && (counter == null ? void 0 : counter.value) === BigInt(options.initial)) {
|
|
1101
1314
|
const cas = await this.replace(key, counter.value, { cas: counter.cas, ttl: options.ttl });
|
|
1102
1315
|
counter.cas = cas ?? counter.cas;
|
|
1103
1316
|
}
|
|
1104
1317
|
return counter;
|
|
1105
1318
|
}
|
|
1106
1319
|
async decrement(key, delta, options) {
|
|
1107
|
-
const counter = await this.#adapter.decrement(key, delta, options);
|
|
1108
|
-
if (
|
|
1320
|
+
const counter = await this.#adapter.decrement(this.#prefix + key, delta, options);
|
|
1321
|
+
if ((options == null ? void 0 : options.initial) !== void 0 && (counter == null ? void 0 : counter.value) === BigInt(options.initial)) {
|
|
1109
1322
|
const cas = await this.replace(key, counter.value, { cas: counter.cas, ttl: options.ttl });
|
|
1110
1323
|
counter.cas = cas ?? counter.cas;
|
|
1111
1324
|
}
|
|
1112
1325
|
return counter;
|
|
1113
1326
|
}
|
|
1114
|
-
touch(key,
|
|
1115
|
-
return this.#adapter.touch(key,
|
|
1327
|
+
touch(key, ttl) {
|
|
1328
|
+
return this.#adapter.touch(this.#prefix + key, ttl);
|
|
1116
1329
|
}
|
|
1117
1330
|
delete(key, options) {
|
|
1118
|
-
return this.#adapter.delete(key, options);
|
|
1331
|
+
return this.#adapter.delete(this.#prefix + key, options);
|
|
1119
1332
|
}
|
|
1120
1333
|
flush(ttl) {
|
|
1121
1334
|
return this.#adapter.flush(ttl);
|
|
@@ -1133,11 +1346,140 @@ var Client = class {
|
|
|
1133
1346
|
return this.#adapter.stats();
|
|
1134
1347
|
}
|
|
1135
1348
|
};
|
|
1136
|
-
|
|
1349
|
+
|
|
1350
|
+
// src/utils.ts
|
|
1351
|
+
var import_assert6 = __toESM(require("assert"));
|
|
1352
|
+
var Factory = class {
|
|
1353
|
+
#factory;
|
|
1354
|
+
#client;
|
|
1355
|
+
#ttl;
|
|
1356
|
+
constructor(client, factory, ttl) {
|
|
1357
|
+
(0, import_assert6.default)(typeof factory === "function", "Invalid or no factory specified");
|
|
1358
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1359
|
+
this.#factory = factory;
|
|
1360
|
+
this.#client = client;
|
|
1361
|
+
this.#ttl = ttl;
|
|
1362
|
+
}
|
|
1363
|
+
async get(key) {
|
|
1364
|
+
const cached = await this.#client.getc(key);
|
|
1365
|
+
if (cached) {
|
|
1366
|
+
void logPromiseError(this.#client.touch(key), `Factory error touching key "${this.#client.prefix}${key}"`);
|
|
1367
|
+
return cached.value;
|
|
1368
|
+
}
|
|
1369
|
+
const created = await this.#factory(key);
|
|
1370
|
+
if (created) {
|
|
1371
|
+
void logPromiseError(this.#client.set(key, created, { ttl: this.#ttl }), `Factory error setting key "${this.#client.prefix}${key}"`);
|
|
1372
|
+
}
|
|
1373
|
+
return created;
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
var Bundle = class {
|
|
1377
|
+
#client;
|
|
1378
|
+
#name;
|
|
1379
|
+
#ttl;
|
|
1380
|
+
constructor(client, name, ttl) {
|
|
1381
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1382
|
+
(0, import_assert6.default)(name, "No bundle name specified");
|
|
1383
|
+
this.#client = client;
|
|
1384
|
+
this.#name = name;
|
|
1385
|
+
this.#ttl = ttl || 0;
|
|
1386
|
+
}
|
|
1387
|
+
async #appendKey(key) {
|
|
1388
|
+
await logPromiseError((async () => {
|
|
1389
|
+
const added = await this.#client.add(this.#name, key, { ttl: this.#ttl });
|
|
1390
|
+
if (!added) {
|
|
1391
|
+
await this.#client.append(this.#name, `\0${key}`);
|
|
1392
|
+
await this.#client.touch(this.#name, this.#ttl);
|
|
1393
|
+
}
|
|
1394
|
+
})(), `Bundle "${this.#client.prefix}${this.#name}" error recording key "${key}"`);
|
|
1395
|
+
}
|
|
1396
|
+
async #removeKey(key) {
|
|
1397
|
+
await logPromiseError((async () => {
|
|
1398
|
+
const result = await this.#client.getc(this.#name);
|
|
1399
|
+
if (!result)
|
|
1400
|
+
return;
|
|
1401
|
+
const keys = result.value.split("\0").filter((k) => k !== key).join("\0");
|
|
1402
|
+
await this.#client.set(this.#name, keys, { cas: result.cas, ttl: this.#ttl });
|
|
1403
|
+
})(), `Bundle "${this.#client.prefix}${this.#name}" error clearing key "${key}"`);
|
|
1404
|
+
}
|
|
1405
|
+
async add(key, value) {
|
|
1406
|
+
await this.#client.set(`${this.#name}:${key}`, value, { ttl: this.#ttl });
|
|
1407
|
+
await this.#appendKey(key);
|
|
1408
|
+
}
|
|
1409
|
+
async get(key) {
|
|
1410
|
+
const result = await this.#client.getc(`${this.#name}:${key}`);
|
|
1411
|
+
if (result)
|
|
1412
|
+
return result.value;
|
|
1413
|
+
await this.#removeKey(key);
|
|
1414
|
+
}
|
|
1415
|
+
async delete(key) {
|
|
1416
|
+
await this.#client.delete(`${this.#name}:${key}`);
|
|
1417
|
+
await this.#removeKey(key);
|
|
1418
|
+
}
|
|
1419
|
+
async list() {
|
|
1420
|
+
const result = await this.#client.getc(this.#name);
|
|
1421
|
+
if (!result)
|
|
1422
|
+
return {};
|
|
1423
|
+
const results = {};
|
|
1424
|
+
const promises = [];
|
|
1425
|
+
for (const key of new Set(result.value.split("\0"))) {
|
|
1426
|
+
promises.push(this.#client.getc(`${this.#name}:${key}`).then((result2) => {
|
|
1427
|
+
if (result2)
|
|
1428
|
+
results[key] = result2.value;
|
|
1429
|
+
}));
|
|
1430
|
+
}
|
|
1431
|
+
await Promise.all(promises);
|
|
1432
|
+
await logPromiseError(this.#client.set(this.#name, Object.keys(results).join("\0"), { cas: result.cas, ttl: this.#ttl }), `Bundle "${this.#client.prefix}${this.#name}" error compacting keys`);
|
|
1433
|
+
return results;
|
|
1434
|
+
}
|
|
1435
|
+
};
|
|
1436
|
+
var PoorManLock = class {
|
|
1437
|
+
#client;
|
|
1438
|
+
#name;
|
|
1439
|
+
constructor(client, name) {
|
|
1440
|
+
(0, import_assert6.default)(client, "No client specified");
|
|
1441
|
+
(0, import_assert6.default)(name, "No lock name specified");
|
|
1442
|
+
this.#client = client;
|
|
1443
|
+
this.#name = name;
|
|
1444
|
+
}
|
|
1445
|
+
async execute(executor, options) {
|
|
1446
|
+
const { timeout = 5e3, owner = false } = options || {};
|
|
1447
|
+
const end = Date.now() + timeout;
|
|
1448
|
+
let cas;
|
|
1449
|
+
do {
|
|
1450
|
+
cas = await this.#client.add(this.#name, owner, { ttl: 2 });
|
|
1451
|
+
if (cas !== void 0)
|
|
1452
|
+
break;
|
|
1453
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1454
|
+
} while (Date.now() < end);
|
|
1455
|
+
if (cas === void 0) {
|
|
1456
|
+
const other = await this.#client.getc(this.#name);
|
|
1457
|
+
const owner2 = other && other.value ? `"${other.value}"` : "anonymous";
|
|
1458
|
+
throw new Error(`Lock "${this.#client.prefix}${this.#name}" timeout (owner=${owner2})`);
|
|
1459
|
+
}
|
|
1460
|
+
const interval = setInterval(() => {
|
|
1461
|
+
void logPromiseError((async () => {
|
|
1462
|
+
const replaced = await this.#client.replace(this.#name, owner, { ttl: 2, cas });
|
|
1463
|
+
(0, import_assert6.default)(replaced !== void 0, `Lock "${this.#client.prefix}${this.#name}" not replaced`);
|
|
1464
|
+
cas = replaced;
|
|
1465
|
+
})(), `Error extending lock "${this.#client.prefix}${this.#name}"`);
|
|
1466
|
+
}, 100);
|
|
1467
|
+
try {
|
|
1468
|
+
return await executor();
|
|
1469
|
+
} finally {
|
|
1470
|
+
clearInterval(interval);
|
|
1471
|
+
await logPromiseError(this.#client.delete(this.#name, { cas }), `Error deleting lock "${this.#client.prefix}${this.#name}"`);
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1474
|
+
};
|
|
1137
1475
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1138
1476
|
0 && (module.exports = {
|
|
1477
|
+
Bundle,
|
|
1139
1478
|
Client,
|
|
1140
1479
|
ClusterAdapter,
|
|
1480
|
+
Factory,
|
|
1481
|
+
FakeAdapter,
|
|
1482
|
+
PoorManLock,
|
|
1141
1483
|
ServerAdapter,
|
|
1142
1484
|
connection,
|
|
1143
1485
|
constants,
|