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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# valkyries
|
|
2
|
+
|
|
3
|
+
Valkey utilities for Node.js services: cache helpers, Bloom filters, dynamic configuration, and sliding-window rate limiting.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
pnpm add valkyries @valkey/valkey-glide
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
`valkyries` is ESM-only and requires Node.js 24 or newer.
|
|
12
|
+
|
|
13
|
+
## Valkey
|
|
14
|
+
|
|
15
|
+
By default the package reads `VALKEY_URL`, falling back to `redis://localhost:6379`.
|
|
16
|
+
|
|
17
|
+
Specialized URLs can split traffic by data type:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
VALKEY_CACHE_URL=redis://localhost:6379
|
|
21
|
+
VALKEY_RATE_LIMITER_URL=redis://localhost:6379
|
|
22
|
+
VALKEY_DYNAMIC_CONFIG_URL=redis://localhost:6379
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Bloom filters require Valkey with the Bloom module. For local development and CI, use Valkey Bundle:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
docker run --rm -p 6379:6379 valkey/valkey-bundle:latest
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Cache
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { ValkeyCache } from "valkyries";
|
|
35
|
+
|
|
36
|
+
const cache = new ValkeyCache({ prefix: "users", ttlSeconds: 300 });
|
|
37
|
+
|
|
38
|
+
const getUser = cache.cacheGetByAny(async (id) => {
|
|
39
|
+
return await loadUserFromDatabase(id);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const user = await getUser("user_123");
|
|
43
|
+
await cache.invalidateCacheGetByAny("user_123");
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Cache keys are normalized with `trim().toLowerCase()`. Use `keySerializer` for composite keys.
|
|
47
|
+
|
|
48
|
+
## Bloom Filters
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { ValkeyBloomFilter } from "valkyries";
|
|
52
|
+
|
|
53
|
+
const filter = new ValkeyBloomFilter({
|
|
54
|
+
name: "users",
|
|
55
|
+
capacity: 1_000_000,
|
|
56
|
+
errorRate: 0.01,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await filter.ensureExists();
|
|
60
|
+
await filter.add(["user_123"]);
|
|
61
|
+
|
|
62
|
+
const maybeExists = await filter.existsIfReady("users:ready", "user_123");
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`null` means the filter is missing or not ready and callers should fall back to the authoritative store.
|
|
66
|
+
|
|
67
|
+
## Dynamic Config
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { DynamicConfig } from "valkyries";
|
|
71
|
+
|
|
72
|
+
const flags = new DynamicConfig({
|
|
73
|
+
key: "feature-flags",
|
|
74
|
+
fieldTypes: { enabled: "boolean", sampleRate: "number" },
|
|
75
|
+
defaultFields: { enabled: false, sampleRate: 0 },
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
await flags.waitForInitialization();
|
|
79
|
+
await flags.setField("enabled", true);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Dynamic config stores fields in a Valkey hash and publishes changes over pub/sub.
|
|
83
|
+
|
|
84
|
+
## Rate Limiter
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { RateLimiter } from "valkyries";
|
|
88
|
+
|
|
89
|
+
const limiter = new RateLimiter({ prefix: "login", ttlSeconds: 60 });
|
|
90
|
+
const { limited, counts } = await limiter.addAndCheck(["ip:127.0.0.1"], 10);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`addAndCheck()` increments first and blocks when any post-add count is greater than or equal to the threshold.
|
|
94
|
+
|
|
95
|
+
## Client Injection
|
|
96
|
+
|
|
97
|
+
Every class accepts an optional `GlideClient` for tests or custom connection management:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { GlideClient } from "@valkey/valkey-glide";
|
|
101
|
+
import { ValkeyCache, glideConfigFromUrl } from "valkyries";
|
|
102
|
+
|
|
103
|
+
const client = await GlideClient.createClient(glideConfigFromUrl("redis://localhost:6379"));
|
|
104
|
+
const cache = new ValkeyCache({ prefix: "custom", ttlSeconds: 60, client });
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Call `closeValkeyClients()` to close package-managed clients.
|
|
108
|
+
|
|
109
|
+
## Documentation
|
|
110
|
+
|
|
111
|
+
- [Configuration](docs/configuration.md)
|
|
112
|
+
- [Clients](docs/clients.md)
|
|
113
|
+
- [Cache](docs/cache.md)
|
|
114
|
+
- [Bloom filters](docs/bloom-filters.md)
|
|
115
|
+
- [Dynamic config](docs/dynamic-config.md)
|
|
116
|
+
- [Rate limiter](docs/rate-limiter.md)
|
|
117
|
+
- [Events and metrics](docs/events-and-metrics.md)
|
|
118
|
+
- [Lua scripts](docs/lua-scripts.md)
|
|
119
|
+
- [Testing and CI](docs/testing-and-ci.md)
|
|
120
|
+
- [Migration guide](docs/migration.md)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batching.d.mts","sourceRoot":"","sources":["../../bloom-filter/batching.mts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAiB,UAAU,CACzB,KAAK,EAAE,MAAM,EAAE,EACf,SAAS,GAAE,MAAmC,GAC7C,SAAS,CAAC,MAAM,EAAE,CAAC,CAUrB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LUA_UNPACK_BATCH_SIZE } from "./scripts.mjs";
|
|
2
|
+
export function luaBatchSize(batchSize) {
|
|
3
|
+
return Math.min(batchSize, LUA_UNPACK_BATCH_SIZE);
|
|
4
|
+
}
|
|
5
|
+
export function* chunkItems(items, batchSize = luaBatchSize(items.length)) {
|
|
6
|
+
if (items.length === 0)
|
|
7
|
+
return;
|
|
8
|
+
if (items.length <= batchSize) {
|
|
9
|
+
yield items;
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
13
|
+
const chunk = items.slice(i, i + batchSize);
|
|
14
|
+
if (chunk.length > 0)
|
|
15
|
+
yield chunk;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=batching.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batching.mjs","sourceRoot":"","sources":["../../bloom-filter/batching.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC5C,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,SAAS,CAAC,CAAC,UAAU,CACzB,KAAe,EACf,YAAoB,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC;IAE9C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC/B,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,KAAK,CAAC;QACZ,OAAO;IACT,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,SAAS,EAAE,CAAC;QACjD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,KAAK,CAAC;IACpC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { BloomFilterState } from "./types.mts";
|
|
2
|
+
export declare function exists(state: BloomFilterState, item: string): Promise<boolean | null>;
|
|
3
|
+
export declare function mexists(state: BloomFilterState, items: string[]): Promise<(boolean | null)[]>;
|
|
4
|
+
export declare function existsIfReady(state: BloomFilterState, readyKey: string, item: string): Promise<boolean | null>;
|
|
5
|
+
export declare function mexistsIfReady(state: BloomFilterState, readyKey: string, items: string[]): Promise<(boolean | null)[]>;
|
|
6
|
+
//# sourceMappingURL=lookups.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookups.d.mts","sourceRoot":"","sources":["../../bloom-filter/lookups.mts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,wBAAsB,MAAM,CAAC,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAiB3F;AAED,wBAAsB,OAAO,CAC3B,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAmB7B;AAED,wBAAsB,aAAa,CACjC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAazB;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EAAE,GACd,OAAO,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,EAAE,CAAC,CAuB7B"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
2
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
3
|
+
import { luaBatchSize } from "./batching.mjs";
|
|
4
|
+
import { bloomFilterExistsIfReadyScript, bloomFilterExistsScript, bloomFilterMexistsIfReadyScript, bloomFilterMexistsScript, } from "./scripts.mjs";
|
|
5
|
+
import { normalizeBloomCheckResult } from "./results.mjs";
|
|
6
|
+
export async function exists(state, item) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await state.client.invokeScript(bloomFilterExistsScript, {
|
|
9
|
+
keys: [state.liveKey],
|
|
10
|
+
args: [item],
|
|
11
|
+
});
|
|
12
|
+
if (result === -1 || result === -1n) {
|
|
13
|
+
emitValkeyEvent("bloom-filter:exists", { name: state.name, item, result: null });
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
const boolResult = result === 1 || result === 1n;
|
|
17
|
+
emitValkeyEvent("bloom-filter:exists", { name: state.name, item, result: boolResult });
|
|
18
|
+
return boolResult;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
handleValkeyError(error);
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export async function mexists(state, items) {
|
|
26
|
+
if (items.length === 0)
|
|
27
|
+
return [];
|
|
28
|
+
const batches = buildBatches(items, luaBatchSize(state.batchSize));
|
|
29
|
+
try {
|
|
30
|
+
const batchResults = await Promise.all(batches.map((batchItems) => state.client.invokeScript(bloomFilterMexistsScript, {
|
|
31
|
+
keys: [state.liveKey],
|
|
32
|
+
args: batchItems,
|
|
33
|
+
})));
|
|
34
|
+
const boolResults = normalizeBatchedResults(batches, batchResults);
|
|
35
|
+
emitValkeyEvent("bloom-filter:mexists", { name: state.name, items, results: boolResults });
|
|
36
|
+
return boolResults;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
handleValkeyError(error);
|
|
40
|
+
return items.map(() => null);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function existsIfReady(state, readyKey, item) {
|
|
44
|
+
try {
|
|
45
|
+
const result = await state.client.invokeScript(bloomFilterExistsIfReadyScript, {
|
|
46
|
+
keys: [readyKey, state.liveKey],
|
|
47
|
+
args: [item],
|
|
48
|
+
});
|
|
49
|
+
const normalized = normalizeBloomCheckResult(result);
|
|
50
|
+
emitValkeyEvent("bloom-filter:exists", { name: state.name, item, result: normalized });
|
|
51
|
+
return normalized;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
handleValkeyError(error);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function mexistsIfReady(state, readyKey, items) {
|
|
59
|
+
if (items.length === 0)
|
|
60
|
+
return [];
|
|
61
|
+
const batches = buildBatches(items, luaBatchSize(state.batchSize));
|
|
62
|
+
try {
|
|
63
|
+
const batchResults = await Promise.all(batches.map((batchItems) => state.client.invokeScript(bloomFilterMexistsIfReadyScript, {
|
|
64
|
+
keys: [readyKey, state.liveKey],
|
|
65
|
+
args: batchItems,
|
|
66
|
+
})));
|
|
67
|
+
const normalizedResults = normalizeBatchedResults(batches, batchResults);
|
|
68
|
+
emitValkeyEvent("bloom-filter:mexists", {
|
|
69
|
+
name: state.name,
|
|
70
|
+
items,
|
|
71
|
+
results: normalizedResults,
|
|
72
|
+
});
|
|
73
|
+
return normalizedResults;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
handleValkeyError(error);
|
|
77
|
+
return items.map(() => null);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function buildBatches(items, batchSize) {
|
|
81
|
+
const batches = [];
|
|
82
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
83
|
+
batches.push(items.slice(i, i + batchSize));
|
|
84
|
+
}
|
|
85
|
+
return batches;
|
|
86
|
+
}
|
|
87
|
+
function normalizeBatchedResults(batches, batchResults) {
|
|
88
|
+
const boolResults = [];
|
|
89
|
+
for (let i = 0; i < batches.length; i++) {
|
|
90
|
+
const batchItems = batches[i];
|
|
91
|
+
const results = batchResults[i];
|
|
92
|
+
if (!Array.isArray(results)) {
|
|
93
|
+
boolResults.push(...batchItems.map(() => null));
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
boolResults.push(...results.map(normalizeBloomCheckResult));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return boolResults;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=lookups.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lookups.mjs","sourceRoot":"","sources":["../../bloom-filter/lookups.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { BloomFilterState } from "./types.mts";
|
|
2
|
+
export declare function rebuild(state: BloomFilterState, items: string[]): Promise<void>;
|
|
3
|
+
export declare function rebuildFromStream(state: BloomFilterState, batches: AsyncIterable<string[]>, capacityOverride?: number): Promise<void>;
|
|
4
|
+
export declare function deleteBloomFilter(state: BloomFilterState): Promise<void>;
|
|
5
|
+
export declare function deleteWithAdditionalKeys(state: BloomFilterState, additionalKeys: string[]): Promise<void>;
|
|
6
|
+
export declare function keyExists(state: BloomFilterState): Promise<boolean>;
|
|
7
|
+
export declare function isReady(state: BloomFilterState, readyKey: string): Promise<boolean>;
|
|
8
|
+
export declare function ensureExists(state: BloomFilterState, capacity?: number): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=rebuilds.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuilds.d.mts","sourceRoot":"","sources":["../../bloom-filter/rebuilds.mts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,wBAAsB,OAAO,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAUrF;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,EAChC,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAED,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAED,wBAAsB,wBAAwB,CAC5C,KAAK,EAAE,gBAAgB,EACvB,cAAc,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,IAAI,CAAC,CAEf;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,CAGzE;AAED,wBAAsB,OAAO,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAGzF;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,gBAAgB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5F"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
2
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
3
|
+
import { chunkItems } from "./batching.mjs";
|
|
4
|
+
import { bloomFilterEnsureExistsScript, bloomFilterReserveScript } from "./scripts.mjs";
|
|
5
|
+
export async function rebuild(state, items) {
|
|
6
|
+
const { batchSize } = state;
|
|
7
|
+
await rebuildFromStream(state, (async function* () {
|
|
8
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
9
|
+
yield items.slice(i, i + batchSize);
|
|
10
|
+
}
|
|
11
|
+
})());
|
|
12
|
+
}
|
|
13
|
+
export async function rebuildFromStream(state, batches, capacityOverride) {
|
|
14
|
+
const capacityToUse = capacityOverride ?? state.capacity;
|
|
15
|
+
await state.client.invokeScript(bloomFilterReserveScript, {
|
|
16
|
+
keys: [state.buildingKey],
|
|
17
|
+
args: [state.errorRate.toString(), capacityToUse.toString(), state.expansionRate.toString()],
|
|
18
|
+
});
|
|
19
|
+
try {
|
|
20
|
+
for await (const batch of batches) {
|
|
21
|
+
let previous = Promise.resolve();
|
|
22
|
+
for (const chunk of chunkItems(batch, state.batchSize)) {
|
|
23
|
+
previous = previous.then(async () => {
|
|
24
|
+
await state.client.customCommand(["BF.MADD", state.buildingKey, ...chunk]);
|
|
25
|
+
emitValkeyEvent("bloom-filter:add", { name: state.name, items: chunk });
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
await previous;
|
|
29
|
+
}
|
|
30
|
+
await state.client.rename(state.buildingKey, state.liveKey);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
await cleanupBuildingKey(state);
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export async function deleteBloomFilter(state) {
|
|
38
|
+
await state.client.unlink([state.liveKey, state.buildingKey]);
|
|
39
|
+
}
|
|
40
|
+
export async function deleteWithAdditionalKeys(state, additionalKeys) {
|
|
41
|
+
await state.client.unlink([state.liveKey, state.buildingKey, ...additionalKeys]);
|
|
42
|
+
}
|
|
43
|
+
export async function keyExists(state) {
|
|
44
|
+
const result = await state.client.customCommand(["EXISTS", state.liveKey]);
|
|
45
|
+
return result === 1 || result === 1n;
|
|
46
|
+
}
|
|
47
|
+
export async function isReady(state, readyKey) {
|
|
48
|
+
const result = await state.client.customCommand(["EXISTS", readyKey, state.liveKey]);
|
|
49
|
+
return result === 2 || result === 2n;
|
|
50
|
+
}
|
|
51
|
+
export async function ensureExists(state, capacity) {
|
|
52
|
+
const capacityToUse = capacity ?? state.capacity;
|
|
53
|
+
await state.client.invokeScript(bloomFilterEnsureExistsScript, {
|
|
54
|
+
keys: [state.liveKey],
|
|
55
|
+
args: [state.errorRate.toString(), capacityToUse.toString(), state.expansionRate.toString()],
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
async function cleanupBuildingKey(state) {
|
|
59
|
+
try {
|
|
60
|
+
await state.client.unlink([state.buildingKey]);
|
|
61
|
+
}
|
|
62
|
+
catch (cleanupError) {
|
|
63
|
+
handleValkeyError(cleanupError);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=rebuilds.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rebuilds.mjs","sourceRoot":"","sources":["../../bloom-filter/rebuilds.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.d.mts","sourceRoot":"","sources":["../../bloom-filter/results.mts"],"names":[],"mappings":"AAAA,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAMxE;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAU9D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function normalizeBloomCheckResult(value) {
|
|
2
|
+
if (value === -1 || value === -1n)
|
|
3
|
+
return null;
|
|
4
|
+
if (value === null || value === undefined)
|
|
5
|
+
return null;
|
|
6
|
+
if (value === true || value === 1 || value === 1n)
|
|
7
|
+
return true;
|
|
8
|
+
if (value === false || value === 0 || value === 0n)
|
|
9
|
+
return false;
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
export function isBloomMissingKeyError(error) {
|
|
13
|
+
if (!(error instanceof Error))
|
|
14
|
+
return false;
|
|
15
|
+
const message = error.message.toLowerCase();
|
|
16
|
+
if (!message.includes("bf.madd"))
|
|
17
|
+
return false;
|
|
18
|
+
return (message.includes("not found") ||
|
|
19
|
+
message.includes("does not exist") ||
|
|
20
|
+
message.includes("missing") ||
|
|
21
|
+
message.includes("no such key"));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=results.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.mjs","sourceRoot":"","sources":["../../bloom-filter/results.mts"],"names":[],"mappings":"AAAA,MAAM,UAAU,yBAAyB,CAAC,KAAc;IACtD,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC/D,IAAI,KAAK,KAAK,KAAK,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,CAAC,CAAC,KAAK,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;IAC5C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,CACL,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC7B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAClC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;QAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAChC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const bloomFilterExistsScript: import("@valkey/valkey-glide").Script;
|
|
2
|
+
export declare const bloomFilterMexistsScript: import("@valkey/valkey-glide").Script;
|
|
3
|
+
export declare const bloomFilterExistsIfReadyScript: import("@valkey/valkey-glide").Script;
|
|
4
|
+
export declare const bloomFilterMexistsIfReadyScript: import("@valkey/valkey-glide").Script;
|
|
5
|
+
export declare const bloomFilterAddScript: import("@valkey/valkey-glide").Script;
|
|
6
|
+
export declare const bloomFilterReserveScript: import("@valkey/valkey-glide").Script;
|
|
7
|
+
export declare const bloomFilterEnsureExistsScript: import("@valkey/valkey-glide").Script;
|
|
8
|
+
export declare const LUA_UNPACK_BATCH_SIZE = 5000;
|
|
9
|
+
//# sourceMappingURL=scripts.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.d.mts","sourceRoot":"","sources":["../../bloom-filter/scripts.mts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,uCAEnC,CAAC;AACF,eAAO,MAAM,wBAAwB,uCAEpC,CAAC;AACF,eAAO,MAAM,8BAA8B,uCAE1C,CAAC;AACF,eAAO,MAAM,+BAA+B,uCAE3C,CAAC;AACF,eAAO,MAAM,oBAAoB,uCAEhC,CAAC;AACF,eAAO,MAAM,wBAAwB,uCAEpC,CAAC;AACF,eAAO,MAAM,6BAA6B,uCAEzC,CAAC;AAEF,eAAO,MAAM,qBAAqB,OAAQ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { loadScript, registerScript } from "../scripts.mjs";
|
|
2
|
+
export const bloomFilterExistsScript = registerScript(loadScript("bloom-filter-exists.lua", new URL("../", import.meta.url)));
|
|
3
|
+
export const bloomFilterMexistsScript = registerScript(loadScript("bloom-filter-mexists.lua", new URL("../", import.meta.url)));
|
|
4
|
+
export const bloomFilterExistsIfReadyScript = registerScript(loadScript("bloom-filter-exists-if-ready.lua", new URL("../", import.meta.url)));
|
|
5
|
+
export const bloomFilterMexistsIfReadyScript = registerScript(loadScript("bloom-filter-mexists-if-ready.lua", new URL("../", import.meta.url)));
|
|
6
|
+
export const bloomFilterAddScript = registerScript(loadScript("bloom-filter-add.lua", new URL("../", import.meta.url)));
|
|
7
|
+
export const bloomFilterReserveScript = registerScript(loadScript("bloom-filter-reserve.lua", new URL("../", import.meta.url)));
|
|
8
|
+
export const bloomFilterEnsureExistsScript = registerScript(loadScript("bloom-filter-ensure-exists.lua", new URL("../", import.meta.url)));
|
|
9
|
+
export const LUA_UNPACK_BATCH_SIZE = 5_000;
|
|
10
|
+
//# sourceMappingURL=scripts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scripts.mjs","sourceRoot":"","sources":["../../bloom-filter/scripts.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CACnD,UAAU,CAAC,yBAAyB,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACvE,CAAC;AACF,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CACpD,UAAU,CAAC,0BAA0B,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACxE,CAAC;AACF,MAAM,CAAC,MAAM,8BAA8B,GAAG,cAAc,CAC1D,UAAU,CAAC,kCAAkC,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAChF,CAAC;AACF,MAAM,CAAC,MAAM,+BAA+B,GAAG,cAAc,CAC3D,UAAU,CAAC,mCAAmC,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACjF,CAAC;AACF,MAAM,CAAC,MAAM,oBAAoB,GAAG,cAAc,CAChD,UAAU,CAAC,sBAAsB,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACpE,CAAC;AACF,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CACpD,UAAU,CAAC,0BAA0B,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CACxE,CAAC;AACF,MAAM,CAAC,MAAM,6BAA6B,GAAG,cAAc,CACzD,UAAU,CAAC,gCAAgC,EAAE,IAAI,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAC9E,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { GlideClient } from "@valkey/valkey-glide";
|
|
2
|
+
export type BloomFilterState = {
|
|
3
|
+
name: string;
|
|
4
|
+
capacity: number;
|
|
5
|
+
errorRate: number;
|
|
6
|
+
expansionRate: number;
|
|
7
|
+
batchSize: number;
|
|
8
|
+
liveKey: string;
|
|
9
|
+
buildingKey: string;
|
|
10
|
+
client: GlideClient;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","sourceRoot":"","sources":["../../bloom-filter/types.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,WAAW,CAAC;CACrB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","sourceRoot":"","sources":["../../bloom-filter/types.mts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { BloomFilterState } from "./types.mts";
|
|
2
|
+
export declare function add(state: BloomFilterState, items: string[]): Promise<void>;
|
|
3
|
+
export declare function addOrThrow(state: BloomFilterState, items: string[]): Promise<void>;
|
|
4
|
+
export declare function addStream(state: BloomFilterState, batches: AsyncIterable<string[]>): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=writes.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writes.d.mts","sourceRoot":"","sources":["../../bloom-filter/writes.mts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD,wBAAgB,GAAG,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAS3E;AAED,wBAAsB,UAAU,CAAC,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxF;AAED,wBAAsB,SAAS,CAC7B,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC,CAgBf"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { emitValkeyEvent } from "../events.mjs";
|
|
2
|
+
import { handleValkeyError } from "../errors.mjs";
|
|
3
|
+
import { chunkItems, luaBatchSize } from "./batching.mjs";
|
|
4
|
+
import { bloomFilterAddScript } from "./scripts.mjs";
|
|
5
|
+
export function add(state, items) {
|
|
6
|
+
if (items.length === 0)
|
|
7
|
+
return Promise.resolve();
|
|
8
|
+
return Promise.all(addCommands(state, items))
|
|
9
|
+
.then((results) => {
|
|
10
|
+
if (results.some(wroteFilter)) {
|
|
11
|
+
emitValkeyEvent("bloom-filter:add", { name: state.name, items });
|
|
12
|
+
}
|
|
13
|
+
})
|
|
14
|
+
.catch(handleValkeyError);
|
|
15
|
+
}
|
|
16
|
+
export async function addOrThrow(state, items) {
|
|
17
|
+
if (items.length === 0)
|
|
18
|
+
return;
|
|
19
|
+
const results = await Promise.all(addCommands(state, items));
|
|
20
|
+
if (results.some(wroteFilter)) {
|
|
21
|
+
emitValkeyEvent("bloom-filter:add", { name: state.name, items });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export async function addStream(state, batches) {
|
|
25
|
+
for await (const batch of batches) {
|
|
26
|
+
let previous = Promise.resolve();
|
|
27
|
+
for (const chunk of chunkItems(batch, luaBatchSize(state.batchSize))) {
|
|
28
|
+
previous = previous.then(async () => {
|
|
29
|
+
const result = await state.client.invokeScript(bloomFilterAddScript, {
|
|
30
|
+
keys: [state.liveKey, state.buildingKey],
|
|
31
|
+
args: chunk,
|
|
32
|
+
});
|
|
33
|
+
if (wroteFilter(result)) {
|
|
34
|
+
emitValkeyEvent("bloom-filter:add", { name: state.name, items: chunk });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
await previous;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function addCommands(state, items) {
|
|
42
|
+
const cmds = [];
|
|
43
|
+
for (const chunk of chunkItems(items, luaBatchSize(state.batchSize))) {
|
|
44
|
+
cmds.push(state.client.invokeScript(bloomFilterAddScript, {
|
|
45
|
+
keys: [state.liveKey, state.buildingKey],
|
|
46
|
+
args: chunk,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
return cmds;
|
|
50
|
+
}
|
|
51
|
+
function wroteFilter(result) {
|
|
52
|
+
return result === 1 || result === 1n;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=writes.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writes.mjs","sourceRoot":"","sources":["../../bloom-filter/writes.mts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import type { ValkeyBloomFilterOptions } from "./types.mts";
|
|
2
|
+
export { LUA_UNPACK_BATCH_SIZE } from "./bloom-filter/scripts.mts";
|
|
3
|
+
export { isBloomMissingKeyError, normalizeBloomCheckResult } from "./bloom-filter/results.mts";
|
|
4
|
+
export declare class ValkeyBloomFilter {
|
|
5
|
+
private name;
|
|
6
|
+
private capacity;
|
|
7
|
+
private errorRate;
|
|
8
|
+
private expansionRate;
|
|
9
|
+
private batchSize;
|
|
10
|
+
private liveKey;
|
|
11
|
+
private buildingKey;
|
|
12
|
+
private client;
|
|
13
|
+
constructor(options: ValkeyBloomFilterOptions);
|
|
14
|
+
/**
|
|
15
|
+
* BF.EXISTS — check if a single item may be in the filter.
|
|
16
|
+
* Returns null if filter doesn't exist (caller should fall back to DB).
|
|
17
|
+
* Single roundtrip via Lua script (EXISTS + BF.EXISTS combined).
|
|
18
|
+
*/
|
|
19
|
+
exists(item: string): Promise<boolean | null>;
|
|
20
|
+
/**
|
|
21
|
+
* BF.MEXISTS — check multiple items in the filter.
|
|
22
|
+
* Returns null per-item if filter doesn't exist (caller should fall back to DB).
|
|
23
|
+
* Single roundtrip via Lua script (EXISTS + BF.MEXISTS combined).
|
|
24
|
+
*/
|
|
25
|
+
mexists(items: string[]): Promise<(boolean | null)[]>;
|
|
26
|
+
/**
|
|
27
|
+
* BF.EXISTS guarded by a deterministic readiness key.
|
|
28
|
+
* Returns null when the ready marker or filter is absent, so callers fall back
|
|
29
|
+
* to their authoritative store instead of trusting an empty/partial filter.
|
|
30
|
+
*/
|
|
31
|
+
existsIfReady(readyKey: string, item: string): Promise<boolean | null>;
|
|
32
|
+
/**
|
|
33
|
+
* BF.MEXISTS guarded by a deterministic readiness key.
|
|
34
|
+
* Returns null per item when the ready marker or filter is absent.
|
|
35
|
+
*/
|
|
36
|
+
mexistsIfReady(readyKey: string, items: string[]): Promise<(boolean | null)[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Add items to bloom filter using BF.MADD. Returns a Promise that resolves when all
|
|
39
|
+
* batches are written (errors are logged via onError, not thrown).
|
|
40
|
+
* Items are chunked at batchSize to avoid hitting Valkey argument-count limits.
|
|
41
|
+
* Each chunk is a single Lua round-trip that also writes to buildingKey if an
|
|
42
|
+
* active rebuild is in progress, so entries are not silently dropped when
|
|
43
|
+
* rebuildFromStream renames buildingKey → liveKey.
|
|
44
|
+
*
|
|
45
|
+
* If neither the live key nor the building key exists (e.g. during the window
|
|
46
|
+
* between worker startup and backfill completion), add() is a no-op. This prevents
|
|
47
|
+
* BF.MADD from auto-creating an under-provisioned filter that would cause false
|
|
48
|
+
* negatives in cache reads. See backfill-bloom-filter.mts for the warmup design.
|
|
49
|
+
*/
|
|
50
|
+
add(items: string[]): Promise<void>;
|
|
51
|
+
/**
|
|
52
|
+
* Add items to bloom filter — same as add(), but throws on error instead of absorbing via onError.
|
|
53
|
+
* Use when the caller needs to detect failures and take corrective action (e.g. clearing readiness).
|
|
54
|
+
*/
|
|
55
|
+
addOrThrow(items: string[]): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Awaitable add — streams batches from an AsyncIterable and BF.MADDs each batch.
|
|
58
|
+
* Use for large-dataset population to avoid loading everything into memory.
|
|
59
|
+
* Unlike add(), errors are propagated (not absorbed via onError).
|
|
60
|
+
*/
|
|
61
|
+
addStream(batches: AsyncIterable<string[]>): Promise<void>;
|
|
62
|
+
/**
|
|
63
|
+
* Rebuild the filter from a complete item list. Uses building key and atomic rename.
|
|
64
|
+
* Only deletes the building key at start (not the live key).
|
|
65
|
+
*/
|
|
66
|
+
rebuild(items: string[]): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Rebuild the filter from an async iterable of item batches. Uses building key and atomic rename.
|
|
69
|
+
* Only deletes the building key at start (not the live key).
|
|
70
|
+
* @param capacityOverride - Optional capacity for this rebuild, such as 2x the current row count.
|
|
71
|
+
*/
|
|
72
|
+
rebuildFromStream(batches: AsyncIterable<string[]>, capacityOverride?: number): Promise<void>;
|
|
73
|
+
delete(): Promise<void>;
|
|
74
|
+
deleteWithAdditionalKeys(additionalKeys: string[]): Promise<void>;
|
|
75
|
+
keyExists(): Promise<boolean>;
|
|
76
|
+
isReady(readyKey: string): Promise<boolean>;
|
|
77
|
+
getKey(): string;
|
|
78
|
+
getBuildingKey(): string;
|
|
79
|
+
getConfig(): {
|
|
80
|
+
name: string;
|
|
81
|
+
capacity: number;
|
|
82
|
+
errorRate: number;
|
|
83
|
+
batchSize: number;
|
|
84
|
+
liveKey: string;
|
|
85
|
+
buildingKey: string;
|
|
86
|
+
};
|
|
87
|
+
ensureExists(capacity?: number): Promise<void>;
|
|
88
|
+
private state;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=bloom-filter.d.mts.map
|