valkyries 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/bloom-filter/batching.d.mts +3 -0
- package/dist/bloom-filter/batching.d.mts.map +1 -0
- package/dist/bloom-filter/batching.mjs +18 -0
- package/dist/bloom-filter/batching.mjs.map +1 -0
- package/dist/bloom-filter/lookups.d.mts +6 -0
- package/dist/bloom-filter/lookups.d.mts.map +1 -0
- package/dist/bloom-filter/lookups.mjs +101 -0
- package/dist/bloom-filter/lookups.mjs.map +1 -0
- package/dist/bloom-filter/rebuilds.d.mts +9 -0
- package/dist/bloom-filter/rebuilds.d.mts.map +1 -0
- package/dist/bloom-filter/rebuilds.mjs +66 -0
- package/dist/bloom-filter/rebuilds.mjs.map +1 -0
- package/dist/bloom-filter/results.d.mts +3 -0
- package/dist/bloom-filter/results.d.mts.map +1 -0
- package/dist/bloom-filter/results.mjs +23 -0
- package/dist/bloom-filter/results.mjs.map +1 -0
- package/dist/bloom-filter/scripts.d.mts +9 -0
- package/dist/bloom-filter/scripts.d.mts.map +1 -0
- package/dist/bloom-filter/scripts.mjs +10 -0
- package/dist/bloom-filter/scripts.mjs.map +1 -0
- package/dist/bloom-filter/types.d.mts +12 -0
- package/dist/bloom-filter/types.d.mts.map +1 -0
- package/dist/bloom-filter/types.mjs +2 -0
- package/dist/bloom-filter/types.mjs.map +1 -0
- package/dist/bloom-filter/writes.d.mts +5 -0
- package/dist/bloom-filter/writes.d.mts.map +1 -0
- package/dist/bloom-filter/writes.mjs +54 -0
- package/dist/bloom-filter/writes.mjs.map +1 -0
- package/dist/bloom-filter.d.mts +90 -0
- package/dist/bloom-filter.d.mts.map +1 -0
- package/dist/bloom-filter.mjs +154 -0
- package/dist/bloom-filter.mjs.map +1 -0
- package/dist/cache/batch-read.d.mts +7 -0
- package/dist/cache/batch-read.d.mts.map +1 -0
- package/dist/cache/batch-read.mjs +142 -0
- package/dist/cache/batch-read.mjs.map +1 -0
- package/dist/cache/constants.d.mts +7 -0
- package/dist/cache/constants.d.mts.map +1 -0
- package/dist/cache/constants.mjs +8 -0
- package/dist/cache/constants.mjs.map +1 -0
- package/dist/cache/core.d.mts +38 -0
- package/dist/cache/core.d.mts.map +1 -0
- package/dist/cache/core.mjs +171 -0
- package/dist/cache/core.mjs.map +1 -0
- package/dist/cache/deletes.d.mts +8 -0
- package/dist/cache/deletes.d.mts.map +1 -0
- package/dist/cache/deletes.mjs +44 -0
- package/dist/cache/deletes.mjs.map +1 -0
- package/dist/cache/mutations.d.mts +25 -0
- package/dist/cache/mutations.d.mts.map +1 -0
- package/dist/cache/mutations.mjs +181 -0
- package/dist/cache/mutations.mjs.map +1 -0
- package/dist/cache/set-if-not-invalidated-events.d.mts +4 -0
- package/dist/cache/set-if-not-invalidated-events.d.mts.map +1 -0
- package/dist/cache/set-if-not-invalidated-events.mjs +21 -0
- package/dist/cache/set-if-not-invalidated-events.mjs.map +1 -0
- package/dist/cache/single-read.d.mts +11 -0
- package/dist/cache/single-read.d.mts.map +1 -0
- package/dist/cache/single-read.mjs +73 -0
- package/dist/cache/single-read.mjs.map +1 -0
- package/dist/cache/stale-refresh.d.mts +15 -0
- package/dist/cache/stale-refresh.d.mts.map +1 -0
- package/dist/cache/stale-refresh.mjs +70 -0
- package/dist/cache/stale-refresh.mjs.map +1 -0
- package/dist/cache-metrics.d.mts +10 -0
- package/dist/cache-metrics.d.mts.map +1 -0
- package/dist/cache-metrics.mjs +12 -0
- package/dist/cache-metrics.mjs.map +1 -0
- package/dist/cache-utils.d.mts +20 -0
- package/dist/cache-utils.d.mts.map +1 -0
- package/dist/cache-utils.mjs +67 -0
- package/dist/cache-utils.mjs.map +1 -0
- package/dist/cache.d.mts +4 -0
- package/dist/cache.d.mts.map +1 -0
- package/dist/cache.mjs +4 -0
- package/dist/cache.mjs.map +1 -0
- package/dist/clients.d.mts +51 -0
- package/dist/clients.d.mts.map +1 -0
- package/dist/clients.mjs +95 -0
- package/dist/clients.mjs.map +1 -0
- package/dist/config.d.mts +6 -0
- package/dist/config.d.mts.map +1 -0
- package/dist/config.mjs +10 -0
- package/dist/config.mjs.map +1 -0
- package/dist/delete.d.mts +3 -0
- package/dist/delete.d.mts.map +1 -0
- package/dist/delete.mjs +23 -0
- package/dist/delete.mjs.map +1 -0
- package/dist/dynamic-config/fields.d.mts +6 -0
- package/dist/dynamic-config/fields.d.mts.map +1 -0
- package/dist/dynamic-config/fields.mjs +50 -0
- package/dist/dynamic-config/fields.mjs.map +1 -0
- package/dist/dynamic-config/storage.d.mts +33 -0
- package/dist/dynamic-config/storage.d.mts.map +1 -0
- package/dist/dynamic-config/storage.mjs +55 -0
- package/dist/dynamic-config/storage.mjs.map +1 -0
- package/dist/dynamic-config.d.mts +34 -0
- package/dist/dynamic-config.d.mts.map +1 -0
- package/dist/dynamic-config.mjs +173 -0
- package/dist/dynamic-config.mjs.map +1 -0
- package/dist/errors.d.mts +4 -0
- package/dist/errors.d.mts.map +1 -0
- package/dist/errors.mjs +15 -0
- package/dist/errors.mjs.map +1 -0
- package/dist/events.d.mts +84 -0
- package/dist/events.d.mts.map +1 -0
- package/dist/events.mjs +18 -0
- package/dist/events.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +13 -0
- package/dist/index.mjs.map +1 -0
- package/dist/key-normalization.d.mts +2 -0
- package/dist/key-normalization.d.mts.map +1 -0
- package/dist/key-normalization.mjs +4 -0
- package/dist/key-normalization.mjs.map +1 -0
- package/dist/rate-limiter.d.mts +40 -0
- package/dist/rate-limiter.d.mts.map +1 -0
- package/dist/rate-limiter.mjs +123 -0
- package/dist/rate-limiter.mjs.map +1 -0
- package/dist/scripts/bloom-filter-add.lua +26 -0
- package/dist/scripts/bloom-filter-ensure-exists.lua +13 -0
- package/dist/scripts/bloom-filter-exists-if-ready.lua +14 -0
- package/dist/scripts/bloom-filter-exists.lua +14 -0
- package/dist/scripts/bloom-filter-mexists-if-ready.lua +19 -0
- package/dist/scripts/bloom-filter-mexists.lua +17 -0
- package/dist/scripts/bloom-filter-reserve.lua +11 -0
- package/dist/scripts/cache-delete-with-invalidation.lua +29 -0
- package/dist/scripts/cache-set-if-not-invalidated.lua +47 -0
- package/dist/scripts/dynamic-config-set-fields.lua +23 -0
- package/dist/scripts/get-value-with-ttl.lua +35 -0
- package/dist/scripts/get-values-with-ttl.lua +81 -0
- package/dist/scripts/rate-limiter-add-and-check.lua +34 -0
- package/dist/scripts/rate-limiter-add.lua +26 -0
- package/dist/scripts/rate-limiter-get.lua +22 -0
- package/dist/scripts.d.mts +4 -0
- package/dist/scripts.d.mts.map +1 -0
- package/dist/scripts.mjs +31 -0
- package/dist/scripts.mjs.map +1 -0
- package/dist/shutdown.d.mts +3 -0
- package/dist/shutdown.d.mts.map +1 -0
- package/dist/shutdown.mjs +27 -0
- package/dist/shutdown.mjs.map +1 -0
- package/dist/types.d.mts +76 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +2 -0
- package/dist/types.mjs.map +1 -0
- package/dist/utils.d.mts +16 -0
- package/dist/utils.d.mts.map +1 -0
- package/dist/utils.mjs +35 -0
- package/dist/utils.mjs.map +1 -0
- package/docs/bloom-filters.md +12 -0
- package/docs/cache.md +19 -0
- package/docs/clients.md +13 -0
- package/docs/configuration.md +16 -0
- package/docs/dynamic-config.md +13 -0
- package/docs/events-and-metrics.md +15 -0
- package/docs/lua-scripts.md +7 -0
- package/docs/migration.md +74 -0
- package/docs/rate-limiter.md +17 -0
- package/docs/testing-and-ci.md +21 -0
- package/package.json +80 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { cacheValkeyClient } from "../clients.mjs";
|
|
2
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
3
|
+
import { deleteKeysWithPrefix } from "../delete.mjs";
|
|
4
|
+
import { normalizeCountResult } from "../utils.mjs";
|
|
5
|
+
import { CACHE_NAMESPACE, INVALIDATION_MARKER_TTL_SECONDS, cacheDeleteWithInvalidationScript, } from "./constants.mjs";
|
|
6
|
+
import { ValkeyCacheMutations } from "./mutations.mjs";
|
|
7
|
+
export class ValkeyCacheDeletes extends ValkeyCacheMutations {
|
|
8
|
+
async delete(...keys) {
|
|
9
|
+
const serializedKeys = [];
|
|
10
|
+
const keyArray = keys.flatMap((key) => {
|
|
11
|
+
const serialized = this.toSerializedKey(key);
|
|
12
|
+
if (serialized === null)
|
|
13
|
+
return [];
|
|
14
|
+
serializedKeys.push(serialized);
|
|
15
|
+
return [this.getSerializedCacheKey(serialized)];
|
|
16
|
+
});
|
|
17
|
+
if (keyArray.length === 0)
|
|
18
|
+
return 0;
|
|
19
|
+
const invalidationKeys = serializedKeys.map((key) => this.getSerializedInvalidationKey(key));
|
|
20
|
+
const result = await this.client.invokeScript(cacheDeleteWithInvalidationScript, {
|
|
21
|
+
keys: [...keyArray, ...invalidationKeys],
|
|
22
|
+
args: [String(keyArray.length), String(INVALIDATION_MARKER_TTL_SECONDS)],
|
|
23
|
+
});
|
|
24
|
+
const count = normalizeCountResult(result);
|
|
25
|
+
emitValkeyEvent("cache:delete", { cacheName: this.prefix, keys: serializedKeys });
|
|
26
|
+
return count;
|
|
27
|
+
}
|
|
28
|
+
async deleteBySerializedKey(...serializedKeys) {
|
|
29
|
+
const keyArray = serializedKeys.map((key) => this.getSerializedCacheKey(key));
|
|
30
|
+
if (keyArray.length === 0)
|
|
31
|
+
return 0;
|
|
32
|
+
const count = await this.client.unlink(keyArray);
|
|
33
|
+
emitValkeyEvent("cache:delete", { cacheName: this.prefix, keys: serializedKeys });
|
|
34
|
+
return count;
|
|
35
|
+
}
|
|
36
|
+
invalidate() {
|
|
37
|
+
return ValkeyCacheDeletes.invalidate(this.prefix, this.client);
|
|
38
|
+
}
|
|
39
|
+
static async invalidate(prefix, client = cacheValkeyClient) {
|
|
40
|
+
await deleteKeysWithPrefix(client, prefix ? `${CACHE_NAMESPACE}:${prefix}:*` : `${CACHE_NAMESPACE}:*`);
|
|
41
|
+
emitValkeyEvent("cache:invalidate", { cacheName: prefix });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=deletes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deletes.mjs","sourceRoot":"","sources":["../../cache/deletes.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EACL,eAAe,EACf,+BAA+B,EAC/B,iCAAiC,GAClC,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,OAAO,kBAA+B,SAAQ,oBAAuB;IACzE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAS;QACvB,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACpC,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;YAC7C,IAAI,UAAU,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YACnC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,UAAU,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACpC,MAAM,gBAAgB,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,iCAAiC,EAAE;YAC/E,IAAI,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,gBAAgB,CAAC;YACxC,IAAI,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,+BAA+B,CAAC,CAAC;SACzE,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAC3C,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAES,KAAK,CAAC,qBAAqB,CAAC,GAAG,cAAwB;QAC/D,MAAM,QAAQ,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC;QAC9E,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjD,eAAe,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QAClF,OAAO,KAAK,CAAC;IACf,CAAC;IAED,UAAU;QACR,OAAO,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,MAAM,GAAG,iBAAiB;QAChE,MAAM,oBAAoB,CACxB,MAAM,EACN,MAAM,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,MAAM,IAAI,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,CACnE,CAAC;QACF,eAAe,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ValkeyCacheBatchRead } from "./batch-read.mts";
|
|
2
|
+
export declare abstract class ValkeyCacheMutations<K = string> extends ValkeyCacheBatchRead<K> {
|
|
3
|
+
refreshById<T>(aliases: K[], fetchByKey: (key: K) => Promise<T | null | undefined>): Promise<T | null>;
|
|
4
|
+
set(key: K, value: unknown, ttl?: number): Promise<void>;
|
|
5
|
+
setBatch(entries: Array<{
|
|
6
|
+
key: K;
|
|
7
|
+
value: unknown;
|
|
8
|
+
ttl?: number;
|
|
9
|
+
}>): Promise<void>;
|
|
10
|
+
protected setBySerializedKey(serializedKey: string, value: unknown, ttl?: number): Promise<void>;
|
|
11
|
+
protected setBySerializedKeyIfNotInvalidated(serializedKey: string, value: unknown, ttl?: number): Promise<void>;
|
|
12
|
+
protected setBatchIfNotInvalidated(entries: Array<{
|
|
13
|
+
key: K;
|
|
14
|
+
value: unknown;
|
|
15
|
+
ttl?: number;
|
|
16
|
+
}>): Promise<void>;
|
|
17
|
+
private setSerializedValue;
|
|
18
|
+
private setSerializedEntriesIfNotInvalidated;
|
|
19
|
+
private collectRefreshAliases;
|
|
20
|
+
private serializeRefreshResult;
|
|
21
|
+
private withSerializedKeys;
|
|
22
|
+
private entryTtl;
|
|
23
|
+
private handleSerializationFailure;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=mutations.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.d.mts","sourceRoot":"","sources":["../../cache/mutations.mts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD,8BAAsB,oBAAoB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,oBAAoB,CAAC,CAAC,CAAC;IAC9E,WAAW,CAAC,CAAC,EACjB,OAAO,EAAE,CAAC,EAAE,EACZ,UAAU,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,GACpD,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAkCpB,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM;IAMlC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;cA6BvE,kBAAkB,CAChC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;cAUA,kCAAkC,CAChD,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;cASA,wBAAwB,CACtC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACvD,OAAO,CAAC,IAAI,CAAC;IAuBhB,OAAO,CAAC,kBAAkB;YAMZ,oCAAoC;IAoBlD,OAAO,CAAC,qBAAqB;YAYf,sBAAsB;IASpC,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,0BAA0B;CAInC"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
2
|
+
import { Batch, TimeUnit } from "@valkey/valkey-glide";
|
|
3
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
4
|
+
import { ValkeyCacheTypeError, durationInMilliseconds } from "../cache-utils.mjs";
|
|
5
|
+
import { trackCacheCall } from "../cache-metrics.mjs";
|
|
6
|
+
import { cacheSetIfNotInvalidatedScript } from "./constants.mjs";
|
|
7
|
+
import { ValkeyCacheBatchRead } from "./batch-read.mjs";
|
|
8
|
+
import { emitSetIfNotInvalidatedEvents } from "./set-if-not-invalidated-events.mjs";
|
|
9
|
+
export class ValkeyCacheMutations extends ValkeyCacheBatchRead {
|
|
10
|
+
async refreshById(aliases, fetchByKey) {
|
|
11
|
+
const aliasState = this.collectRefreshAliases(aliases);
|
|
12
|
+
if (aliasState.firstValidAlias === null)
|
|
13
|
+
return null;
|
|
14
|
+
const start = process.hrtime.bigint();
|
|
15
|
+
try {
|
|
16
|
+
const result = await fetchByKey(aliasState.firstValidAlias);
|
|
17
|
+
const normalizedResult = result ?? null;
|
|
18
|
+
const serialized = await this.serializeRefreshResult(normalizedResult);
|
|
19
|
+
const ttl = normalizedResult === null ? this.nullTtl : this.ttl;
|
|
20
|
+
const batch = new Batch(false);
|
|
21
|
+
for (const key of aliasState.serializedKeys) {
|
|
22
|
+
batch.set(this.getSerializedCacheKey(key), serialized, {
|
|
23
|
+
expiry: { type: TimeUnit.Seconds, count: ttl },
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
this.client
|
|
27
|
+
.exec(batch, false)
|
|
28
|
+
.then(() => {
|
|
29
|
+
emitValkeyEvent("cache:set", { cacheName: this.prefix, keys: aliasState.serializedKeys });
|
|
30
|
+
})
|
|
31
|
+
.catch(handleValkeyError);
|
|
32
|
+
return normalizedResult;
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
trackCacheCall({
|
|
36
|
+
cacheName: this.prefix,
|
|
37
|
+
batch: false,
|
|
38
|
+
hits: 0,
|
|
39
|
+
misses: 1,
|
|
40
|
+
bloomMisses: 0,
|
|
41
|
+
duration: durationInMilliseconds(start),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
set(key, value, ttl) {
|
|
46
|
+
const serializedKey = this.toSerializedKey(key);
|
|
47
|
+
if (serializedKey === null)
|
|
48
|
+
return Promise.resolve();
|
|
49
|
+
return this.setBySerializedKey(serializedKey, value, ttl);
|
|
50
|
+
}
|
|
51
|
+
async setBatch(entries) {
|
|
52
|
+
const validEntries = this.withSerializedKeys(entries);
|
|
53
|
+
if (validEntries.length === 0)
|
|
54
|
+
return;
|
|
55
|
+
const serializationResults = await Promise.allSettled(validEntries.map((entry) => this.serializeValue(entry.value)));
|
|
56
|
+
const batch = new Batch(false);
|
|
57
|
+
const writtenKeys = [];
|
|
58
|
+
for (let i = 0; i < validEntries.length; i++) {
|
|
59
|
+
const result = serializationResults[i];
|
|
60
|
+
if (result.status === "rejected") {
|
|
61
|
+
this.handleSerializationFailure(result.reason);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
const entry = validEntries[i];
|
|
65
|
+
batch.set(this.getSerializedCacheKey(entry.serializedKey), result.value, {
|
|
66
|
+
expiry: { type: TimeUnit.Seconds, count: this.entryTtl(entry) },
|
|
67
|
+
});
|
|
68
|
+
writtenKeys.push(entry.serializedKey);
|
|
69
|
+
}
|
|
70
|
+
if (writtenKeys.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
this.client
|
|
73
|
+
.exec(batch, false)
|
|
74
|
+
.then(() => {
|
|
75
|
+
emitValkeyEvent("cache:set", { cacheName: this.prefix, keys: writtenKeys });
|
|
76
|
+
})
|
|
77
|
+
.catch(handleValkeyError);
|
|
78
|
+
}
|
|
79
|
+
async setBySerializedKey(serializedKey, value, ttl) {
|
|
80
|
+
try {
|
|
81
|
+
const serialized = await this.serializeValue(value);
|
|
82
|
+
await this.setSerializedValue(serializedKey, serialized, ttl);
|
|
83
|
+
emitValkeyEvent("cache:set", { cacheName: this.prefix, keys: [serializedKey] });
|
|
84
|
+
}
|
|
85
|
+
catch (cause) {
|
|
86
|
+
this.handleSerializationFailure(cause);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
async setBySerializedKeyIfNotInvalidated(serializedKey, value, ttl) {
|
|
90
|
+
try {
|
|
91
|
+
const serialized = await this.serializeValue(value);
|
|
92
|
+
await this.setSerializedEntriesIfNotInvalidated([{ serializedKey, value: serialized, ttl }]);
|
|
93
|
+
}
|
|
94
|
+
catch (cause) {
|
|
95
|
+
this.handleSerializationFailure(cause);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async setBatchIfNotInvalidated(entries) {
|
|
99
|
+
const validEntries = this.withSerializedKeys(entries);
|
|
100
|
+
if (validEntries.length === 0)
|
|
101
|
+
return;
|
|
102
|
+
const serializationResults = await Promise.allSettled(validEntries.map((entry) => this.serializeValue(entry.value)));
|
|
103
|
+
const setEntries = [];
|
|
104
|
+
for (let i = 0; i < validEntries.length; i++) {
|
|
105
|
+
const result = serializationResults[i];
|
|
106
|
+
if (result.status === "rejected") {
|
|
107
|
+
this.handleSerializationFailure(result.reason);
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const entry = validEntries[i];
|
|
111
|
+
setEntries.push({
|
|
112
|
+
serializedKey: entry.serializedKey,
|
|
113
|
+
value: result.value,
|
|
114
|
+
ttl: this.entryTtl(entry),
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
await this.setSerializedEntriesIfNotInvalidated(setEntries);
|
|
118
|
+
}
|
|
119
|
+
setSerializedValue(serializedKey, serialized, ttl) {
|
|
120
|
+
return this.client.set(this.getSerializedCacheKey(serializedKey), serialized, {
|
|
121
|
+
expiry: { type: TimeUnit.Seconds, count: ttl != null && ttl > 0 ? ttl : this.ttl },
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
async setSerializedEntriesIfNotInvalidated(entries) {
|
|
125
|
+
if (entries.length === 0)
|
|
126
|
+
return;
|
|
127
|
+
const keys = [
|
|
128
|
+
...entries.map((entry) => this.getSerializedCacheKey(entry.serializedKey)),
|
|
129
|
+
...entries.map((entry) => this.getSerializedInvalidationKey(entry.serializedKey)),
|
|
130
|
+
];
|
|
131
|
+
const args = [String(entries.length)];
|
|
132
|
+
for (const entry of entries) {
|
|
133
|
+
args.push(String(entry.ttl != null && entry.ttl > 0 ? entry.ttl : this.ttl));
|
|
134
|
+
args.push(entry.value);
|
|
135
|
+
}
|
|
136
|
+
const results = await this.client.invokeScript(cacheSetIfNotInvalidatedScript, {
|
|
137
|
+
keys,
|
|
138
|
+
args,
|
|
139
|
+
});
|
|
140
|
+
emitSetIfNotInvalidatedEvents(this.prefix, entries, results);
|
|
141
|
+
}
|
|
142
|
+
collectRefreshAliases(aliases) {
|
|
143
|
+
let firstValidAlias = null;
|
|
144
|
+
const serializedKeySet = new Set();
|
|
145
|
+
for (const key of aliases) {
|
|
146
|
+
const serialized = this.toSerializedKey(key);
|
|
147
|
+
if (serialized === null)
|
|
148
|
+
continue;
|
|
149
|
+
firstValidAlias ??= key;
|
|
150
|
+
serializedKeySet.add(serialized);
|
|
151
|
+
}
|
|
152
|
+
return { firstValidAlias, serializedKeys: [...serializedKeySet] };
|
|
153
|
+
}
|
|
154
|
+
async serializeRefreshResult(value) {
|
|
155
|
+
try {
|
|
156
|
+
return await this.serializeValue(value);
|
|
157
|
+
}
|
|
158
|
+
catch (cause) {
|
|
159
|
+
if (cause instanceof ValkeyCacheTypeError)
|
|
160
|
+
throw cause;
|
|
161
|
+
throw new Error("ValkeyCache: failed to stringify and/or compress value", { cause });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
withSerializedKeys(entries) {
|
|
165
|
+
return entries.flatMap((entry) => {
|
|
166
|
+
const serializedKey = this.toSerializedKey(entry.key);
|
|
167
|
+
return serializedKey !== null ? [{ ...entry, serializedKey }] : [];
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
entryTtl(entry) {
|
|
171
|
+
if (entry.ttl != null && entry.ttl > 0)
|
|
172
|
+
return entry.ttl;
|
|
173
|
+
return entry.value === null || entry.value === undefined ? this.nullTtl : this.ttl;
|
|
174
|
+
}
|
|
175
|
+
handleSerializationFailure(cause) {
|
|
176
|
+
if (cause instanceof ValkeyCacheTypeError)
|
|
177
|
+
throw cause;
|
|
178
|
+
handleValkeyError(cause instanceof Error ? cause : new Error(String(cause)));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=mutations.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.mjs","sourceRoot":"","sources":["../../cache/mutations.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-if-not-invalidated-events.d.mts","sourceRoot":"","sources":["../../cache/set-if-not-invalidated-events.mts"],"names":[],"mappings":"AAEA,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,KAAK,CAAC;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,EACzC,OAAO,EAAE,OAAO,QAoBjB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
2
|
+
export function emitSetIfNotInvalidatedEvents(prefix, entries, results) {
|
|
3
|
+
const writtenKeys = Array.isArray(results)
|
|
4
|
+
? entries.flatMap((entry, index) => {
|
|
5
|
+
const result = results[index];
|
|
6
|
+
return result === 1 || result === 1n ? [entry.serializedKey] : [];
|
|
7
|
+
})
|
|
8
|
+
: entries.map((entry) => entry.serializedKey);
|
|
9
|
+
const skippedKeys = Array.isArray(results) && results.length === entries.length
|
|
10
|
+
? entries.flatMap((entry, index) => {
|
|
11
|
+
const result = results[index];
|
|
12
|
+
return result === 0 || result === 0n ? [entry.serializedKey] : [];
|
|
13
|
+
})
|
|
14
|
+
: [];
|
|
15
|
+
if (writtenKeys.length > 0)
|
|
16
|
+
emitValkeyEvent("cache:set", { cacheName: prefix, keys: writtenKeys });
|
|
17
|
+
if (skippedKeys.length > 0) {
|
|
18
|
+
emitValkeyEvent("cache:set-skipped", { cacheName: prefix, keys: skippedKeys });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=set-if-not-invalidated-events.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"set-if-not-invalidated-events.mjs","sourceRoot":"","sources":["../../cache/set-if-not-invalidated-events.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAEhD,MAAM,UAAU,6BAA6B,CAC3C,MAAc,EACd,OAAyC,EACzC,OAAgB;IAEhB,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QACxC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,OAAO,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,CAAC,CAAC;QACJ,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IAChD,MAAM,WAAW,GACf,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;QACzD,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,OAAO,MAAM,KAAK,CAAC,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,CAAC,CAAC;QACJ,CAAC,CAAC,EAAE,CAAC;IACT,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;QACxB,eAAe,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IACzE,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,eAAe,CAAC,mBAAmB,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ValkeyCacheResponse } from "../types.mts";
|
|
2
|
+
import { ValkeyCacheStaleRefresh } from "./stale-refresh.mts";
|
|
3
|
+
export declare abstract class ValkeyCacheSingleRead<K = string> extends ValkeyCacheStaleRefresh<K> {
|
|
4
|
+
cacheGetByAny<T>(fn: (key: K) => Promise<T | null | undefined>): (key: K) => Promise<T | null>;
|
|
5
|
+
invalidateCacheGetByAny(...keys: K[]): Promise<number>;
|
|
6
|
+
getKey(key: K): string;
|
|
7
|
+
get(key: K): ValkeyCacheResponse;
|
|
8
|
+
protected trackSingleRead(start: bigint, hits: number, misses: number, bloomMisses: number, serializedKey: string): void;
|
|
9
|
+
abstract delete(...keys: K[]): Promise<number>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=single-read.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-read.d.mts","sourceRoot":"","sources":["../../cache/single-read.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAIxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,8BAAsB,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,uBAAuB,CAAC,CAAC,CAAC;IACxF,aAAa,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,IAC9C,KAAK,CAAC,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IA2C1C,uBAAuB,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE;IAIpC,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM;IAMhB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,mBAAmB;IAOtC,SAAS,CAAC,eAAe,CACvB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM;IAiBvB,QAAQ,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;CAC/C"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
2
|
+
import { durationInMilliseconds } from "../cache-utils.mjs";
|
|
3
|
+
import { trackCacheCall } from "../cache-metrics.mjs";
|
|
4
|
+
import { ValkeyCacheStaleRefresh } from "./stale-refresh.mjs";
|
|
5
|
+
export class ValkeyCacheSingleRead extends ValkeyCacheStaleRefresh {
|
|
6
|
+
cacheGetByAny(fn) {
|
|
7
|
+
return async (key) => {
|
|
8
|
+
const serializedKey = this.toSerializedKey(key);
|
|
9
|
+
if (serializedKey === null)
|
|
10
|
+
return null;
|
|
11
|
+
const start = process.hrtime.bigint();
|
|
12
|
+
let hits = 0;
|
|
13
|
+
let misses = 0;
|
|
14
|
+
let bloomMisses = 0;
|
|
15
|
+
try {
|
|
16
|
+
const { value: cached, ttlSecondsRemaining, bloomMiss, } = await this.getValueWithTtl(serializedKey);
|
|
17
|
+
if (bloomMiss) {
|
|
18
|
+
bloomMisses = 1;
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const keyExists = ttlSecondsRemaining !== null && ttlSecondsRemaining !== -2;
|
|
22
|
+
if (cached !== null && cached !== undefined) {
|
|
23
|
+
hits = 1;
|
|
24
|
+
this.refreshStaleEntry(serializedKey, ttlSecondsRemaining, () => fn(key));
|
|
25
|
+
return cached;
|
|
26
|
+
}
|
|
27
|
+
if (keyExists) {
|
|
28
|
+
hits = 1;
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
misses = 1;
|
|
32
|
+
const result = await fn(key);
|
|
33
|
+
if (result === undefined || result === null) {
|
|
34
|
+
this.setBySerializedKeyIfNotInvalidated(serializedKey, null, this.nullTtl).catch(handleValkeyError);
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
this.setBySerializedKeyIfNotInvalidated(serializedKey, result).catch(handleValkeyError);
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
finally {
|
|
41
|
+
this.trackSingleRead(start, hits, misses, bloomMisses, serializedKey);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
invalidateCacheGetByAny(...keys) {
|
|
46
|
+
return this.delete(...keys);
|
|
47
|
+
}
|
|
48
|
+
getKey(key) {
|
|
49
|
+
const serializedKey = this.toSerializedKey(key);
|
|
50
|
+
if (serializedKey === null)
|
|
51
|
+
throw new Error(`ValkeyCache: invalid key: ${String(key)}`);
|
|
52
|
+
return this.getSerializedCacheKey(serializedKey);
|
|
53
|
+
}
|
|
54
|
+
async get(key) {
|
|
55
|
+
const serializedKey = this.toSerializedKey(key);
|
|
56
|
+
if (serializedKey === null)
|
|
57
|
+
return null;
|
|
58
|
+
const { value } = await this.getValueWithTtl(serializedKey);
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
trackSingleRead(start, hits, misses, bloomMisses, serializedKey) {
|
|
62
|
+
trackCacheCall({
|
|
63
|
+
cacheName: this.prefix,
|
|
64
|
+
batch: false,
|
|
65
|
+
hits,
|
|
66
|
+
misses,
|
|
67
|
+
bloomMisses,
|
|
68
|
+
duration: durationInMilliseconds(start),
|
|
69
|
+
});
|
|
70
|
+
this.emitCacheEvents(hits > 0 ? [serializedKey] : [], misses > 0 ? [serializedKey] : [], bloomMisses > 0 ? [serializedKey] : []);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=single-read.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"single-read.mjs","sourceRoot":"","sources":["../../cache/single-read.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ValkeyCacheCore, type CacheEntry } from "./core.mts";
|
|
2
|
+
export declare abstract class ValkeyCacheStaleRefresh<K = string> extends ValkeyCacheCore<K> {
|
|
3
|
+
protected refreshStaleBatchEntries<T>(serializedKeys: string[], keys: K[], entries: CacheEntry[], batchFn: (keys: K[]) => Promise<Array<T | null | undefined>>): void;
|
|
4
|
+
protected refreshStaleEntry(serializedKey: string, ttlSecondsRemaining: number | null, fetchValue: () => Promise<unknown>): void;
|
|
5
|
+
private markRefreshesPending;
|
|
6
|
+
private refreshBatch;
|
|
7
|
+
private refreshSingle;
|
|
8
|
+
protected abstract setBatchIfNotInvalidated(entries: Array<{
|
|
9
|
+
key: K;
|
|
10
|
+
value: unknown;
|
|
11
|
+
ttl?: number;
|
|
12
|
+
}>): Promise<void>;
|
|
13
|
+
protected abstract setBySerializedKeyIfNotInvalidated(serializedKey: string, value: unknown, ttl?: number): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=stale-refresh.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-refresh.d.mts","sourceRoot":"","sources":["../../cache/stale-refresh.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE9D,8BAAsB,uBAAuB,CAAC,CAAC,GAAG,MAAM,CAAE,SAAQ,eAAe,CAAC,CAAC,CAAC;IAClF,SAAS,CAAC,wBAAwB,CAAC,CAAC,EAClC,cAAc,EAAE,MAAM,EAAE,EACxB,IAAI,EAAE,CAAC,EAAE,EACT,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IAkB9D,SAAS,CAAC,iBAAiB,CACzB,aAAa,EAAE,MAAM,EACrB,mBAAmB,EAAE,MAAM,GAAG,IAAI,EAClC,UAAU,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC;IASpC,OAAO,CAAC,oBAAoB;YAKd,YAAY;YAyBZ,aAAa;IAa3B,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CACzC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GACvD,OAAO,CAAC,IAAI,CAAC;IAEhB,SAAS,CAAC,QAAQ,CAAC,kCAAkC,CACnD,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,OAAO,EACd,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,IAAI,CAAC;CACjB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
2
|
+
import { ValkeyCacheCore } from "./core.mjs";
|
|
3
|
+
export class ValkeyCacheStaleRefresh extends ValkeyCacheCore {
|
|
4
|
+
refreshStaleBatchEntries(serializedKeys, keys, entries, batchFn) {
|
|
5
|
+
const staleSerializedKeys = [];
|
|
6
|
+
const staleKeys = [];
|
|
7
|
+
for (let i = 0; i < entries.length; i++) {
|
|
8
|
+
const entry = entries[i];
|
|
9
|
+
if (entry.value === null || entry.value === undefined)
|
|
10
|
+
continue;
|
|
11
|
+
if (!this.shouldRefreshTtl(entry.ttlSecondsRemaining))
|
|
12
|
+
continue;
|
|
13
|
+
if (this.refreshPromises.has(serializedKeys[i]))
|
|
14
|
+
continue;
|
|
15
|
+
staleSerializedKeys.push(serializedKeys[i]);
|
|
16
|
+
staleKeys.push(keys[i]);
|
|
17
|
+
}
|
|
18
|
+
if (staleSerializedKeys.length === 0)
|
|
19
|
+
return;
|
|
20
|
+
this.markRefreshesPending(staleSerializedKeys);
|
|
21
|
+
const refreshPromise = this.refreshBatch(staleSerializedKeys, staleKeys, batchFn);
|
|
22
|
+
refreshPromise.catch(handleValkeyError);
|
|
23
|
+
}
|
|
24
|
+
refreshStaleEntry(serializedKey, ttlSecondsRemaining, fetchValue) {
|
|
25
|
+
if (!this.shouldRefreshTtl(ttlSecondsRemaining))
|
|
26
|
+
return;
|
|
27
|
+
if (this.refreshPromises.has(serializedKey))
|
|
28
|
+
return;
|
|
29
|
+
this.refreshPromises.set(serializedKey, Promise.resolve());
|
|
30
|
+
const refreshPromise = this.refreshSingle(serializedKey, fetchValue);
|
|
31
|
+
refreshPromise.catch(handleValkeyError);
|
|
32
|
+
}
|
|
33
|
+
markRefreshesPending(serializedKeys) {
|
|
34
|
+
const sentinel = Promise.resolve();
|
|
35
|
+
for (const key of serializedKeys)
|
|
36
|
+
this.refreshPromises.set(key, sentinel);
|
|
37
|
+
}
|
|
38
|
+
async refreshBatch(serializedKeys, keys, batchFn) {
|
|
39
|
+
try {
|
|
40
|
+
const results = await batchFn(keys);
|
|
41
|
+
if (!Array.isArray(results) || results.length !== keys.length) {
|
|
42
|
+
handleValkeyError(new Error(`Stale batch refresh returned invalid result: expected array of ${keys.length} items, got ${Array.isArray(results) ? results.length : typeof results}`));
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const setEntries = keys.map((key, i) => {
|
|
46
|
+
const value = results[i] ?? null;
|
|
47
|
+
return { key, value, ttl: value === null ? this.nullTtl : undefined };
|
|
48
|
+
});
|
|
49
|
+
await this.setBatchIfNotInvalidated(setEntries);
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
for (const key of serializedKeys)
|
|
53
|
+
this.refreshPromises.delete(key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async refreshSingle(serializedKey, fetchValue) {
|
|
57
|
+
try {
|
|
58
|
+
const result = await fetchValue();
|
|
59
|
+
if (result === undefined || result === null) {
|
|
60
|
+
await this.setBySerializedKeyIfNotInvalidated(serializedKey, null, this.nullTtl);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await this.setBySerializedKeyIfNotInvalidated(serializedKey, result);
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
this.refreshPromises.delete(serializedKey);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=stale-refresh.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-refresh.mjs","sourceRoot":"","sources":["../../cache/stale-refresh.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type CacheCallMetric = {
|
|
2
|
+
cacheName: string;
|
|
3
|
+
batch: boolean;
|
|
4
|
+
hits: number;
|
|
5
|
+
misses: number;
|
|
6
|
+
bloomMisses: number;
|
|
7
|
+
duration: number;
|
|
8
|
+
};
|
|
9
|
+
export declare function trackCacheCall(metric: CacheCallMetric): void;
|
|
10
|
+
//# sourceMappingURL=cache-metrics.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-metrics.d.mts","sourceRoot":"","sources":["../cache-metrics.mts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAS5D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "./events.mjs";
|
|
2
|
+
export function trackCacheCall(metric) {
|
|
3
|
+
emitValkeyEvent("cache:call", {
|
|
4
|
+
cacheName: metric.cacheName,
|
|
5
|
+
batch: metric.batch,
|
|
6
|
+
hits: metric.hits,
|
|
7
|
+
misses: metric.misses,
|
|
8
|
+
bloomMisses: metric.bloomMisses,
|
|
9
|
+
durationMs: metric.duration,
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=cache-metrics.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-metrics.mjs","sourceRoot":"","sources":["../cache-metrics.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAW/C,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,eAAe,CAAC,YAAY,EAAE;QAC5B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,QAAQ;KAC5B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for Valkey cache
|
|
3
|
+
*/
|
|
4
|
+
import type { ValkeyCacheMode } from "./types.mts";
|
|
5
|
+
import type { GlideString } from "@valkey/valkey-glide";
|
|
6
|
+
export declare class ValkeyCacheTypeError extends TypeError {
|
|
7
|
+
constructor(message: string);
|
|
8
|
+
}
|
|
9
|
+
export declare const durationInMilliseconds: (start: bigint) => number;
|
|
10
|
+
/**
|
|
11
|
+
* Serialize a value for storage in Valkey cache
|
|
12
|
+
* Supports text, buffer, and JSON modes with automatic compression
|
|
13
|
+
*/
|
|
14
|
+
export declare function serializeValue(value: unknown, mode: ValkeyCacheMode): Promise<string | Buffer>;
|
|
15
|
+
/**
|
|
16
|
+
* Decode a value from Valkey cache
|
|
17
|
+
* Handles decompression and parsing based on mode
|
|
18
|
+
*/
|
|
19
|
+
export declare function decodeValue(result: GlideString | null, mode: ValkeyCacheMode): Promise<string | Buffer | Record<string, unknown> | null>;
|
|
20
|
+
//# sourceMappingURL=cache-utils.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-utils.d.mts","sourceRoot":"","sources":["../cache-utils.mts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,OAAO,EAAE,MAAM;CAI5B;AAED,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MACF,CAAC;AAMtD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAsB1B;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,GAAG,IAAI,EAC1B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAwB3D"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for Valkey cache
|
|
3
|
+
*/
|
|
4
|
+
import { gzip, gunzip } from "node:zlib";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
export class ValkeyCacheTypeError extends TypeError {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(`ValkeyCache: ${message}`);
|
|
9
|
+
this.name = "ValkeyCacheTypeError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export const durationInMilliseconds = (start) => Number(process.hrtime.bigint() - start) / 1_000_000;
|
|
13
|
+
const COMPRESSION_THRESHOLD = 2 * 1024; // 2kb
|
|
14
|
+
const gzipAsync = promisify(gzip);
|
|
15
|
+
const gunzipAsync = promisify(gunzip);
|
|
16
|
+
/**
|
|
17
|
+
* Serialize a value for storage in Valkey cache
|
|
18
|
+
* Supports text, buffer, and JSON modes with automatic compression
|
|
19
|
+
*/
|
|
20
|
+
export async function serializeValue(value, mode) {
|
|
21
|
+
let serialized;
|
|
22
|
+
if (mode === "text") {
|
|
23
|
+
if (typeof value !== "string") {
|
|
24
|
+
throw new ValkeyCacheTypeError("text mode requires a string value");
|
|
25
|
+
}
|
|
26
|
+
serialized = value;
|
|
27
|
+
}
|
|
28
|
+
else if (mode === "buffer") {
|
|
29
|
+
if (!Buffer.isBuffer(value)) {
|
|
30
|
+
throw new ValkeyCacheTypeError("buffer mode requires a Buffer value");
|
|
31
|
+
}
|
|
32
|
+
serialized = value;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
serialized = JSON.stringify(value);
|
|
36
|
+
}
|
|
37
|
+
if (Buffer.byteLength(serialized) > COMPRESSION_THRESHOLD) {
|
|
38
|
+
serialized = await gzipAsync(serialized);
|
|
39
|
+
}
|
|
40
|
+
return serialized;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Decode a value from Valkey cache
|
|
44
|
+
* Handles decompression and parsing based on mode
|
|
45
|
+
*/
|
|
46
|
+
export async function decodeValue(result, mode) {
|
|
47
|
+
if (result === null)
|
|
48
|
+
return null;
|
|
49
|
+
if (!Buffer.isBuffer(result)) {
|
|
50
|
+
throw new ValkeyCacheTypeError(`Expected Buffer, got ${typeof result}`);
|
|
51
|
+
}
|
|
52
|
+
let buffer = result;
|
|
53
|
+
// Check if buffer is gzipped by looking for gzip magic number (0x1f 0x8b)
|
|
54
|
+
const isGzipped = buffer.length >= 2 && buffer[0] === 0x1f && buffer[1] === 0x8b;
|
|
55
|
+
if (isGzipped) {
|
|
56
|
+
buffer = await gunzipAsync(buffer);
|
|
57
|
+
}
|
|
58
|
+
if (mode === "buffer") {
|
|
59
|
+
return buffer;
|
|
60
|
+
}
|
|
61
|
+
const text = buffer.toString("utf8");
|
|
62
|
+
if (mode === "text") {
|
|
63
|
+
return text;
|
|
64
|
+
}
|
|
65
|
+
return JSON.parse(text);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=cache-utils.mjs.map
|