@voltro/cache 0.86.0 → 0.87.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/CHANGELOG.md +5321 -0
- package/THIRD-PARTY-NOTICES.md +864 -1
- package/dist/Cache.js +136 -30
- package/dist/CacheStore.js +3 -2
- package/dist/backendMemory.js +102 -41
- package/dist/backendRedis.js +165 -49
- package/dist/index.d.ts +135 -24
- package/dist/index.js +8 -8
- package/dist/layer.js +15 -15
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { CACHE_FENCE_RETENTION_MS } from '@voltro/kv/connection';
|
|
1
2
|
import { Config } from 'effect';
|
|
2
3
|
import { Context } from 'effect';
|
|
3
4
|
import { Effect } from 'effect';
|
|
4
5
|
import { Layer } from 'effect';
|
|
5
6
|
import { Option } from 'effect';
|
|
7
|
+
import { RedisConnections } from '@voltro/kv/connection';
|
|
8
|
+
import { RespClient } from '@voltro/kv/connection';
|
|
9
|
+
import { RespConnections } from '@voltro/kv/connection';
|
|
6
10
|
import { Schema } from 'effect';
|
|
7
11
|
import { Scope } from 'effect';
|
|
8
12
|
import { Stream } from 'effect';
|
|
@@ -21,13 +25,26 @@ declare const Cache_base: Context.ServiceClass<Cache, "@voltro/Cache", {
|
|
|
21
25
|
/** Write-through with the SAME storage shape `wrap` uses (incl. the
|
|
22
26
|
* SWR envelope) — so a value written here is read back identically
|
|
23
27
|
* by a later `wrap`. The dispatcher uses this to keep cached
|
|
24
|
-
* snapshots warm from its live recompute.
|
|
25
|
-
|
|
28
|
+
* snapshots warm from its live recompute. Pass the `fence()` observed
|
|
29
|
+
* before the value was read, so an earlier, slower read can never
|
|
30
|
+
* overwrite a later one. Resolves `false` when the fence voided it. */
|
|
31
|
+
readonly put: <A>(key: string, options: WrapOptions, value: A, fence?: CacheFence) => Effect.Effect<boolean, CacheError>;
|
|
32
|
+
/** The store's invalidation position — observe it before reading the
|
|
33
|
+
* value you will `put`. */
|
|
34
|
+
readonly fence: () => Effect.Effect<CacheFence, CacheError>;
|
|
26
35
|
readonly remove: (key: string) => Effect.Effect<boolean, CacheError>;
|
|
27
36
|
readonly has: (key: string) => Effect.Effect<boolean, CacheError>;
|
|
28
37
|
readonly clear: () => Effect.Effect<void, CacheError>;
|
|
29
38
|
readonly invalidateTag: (tag: string) => Effect.Effect<number, CacheError>;
|
|
30
39
|
readonly wrap: <A, E, R>(key: string, options: WrapOptions, compute: Effect.Effect<A, E, R>) => Effect.Effect<A, E | CacheError, R>;
|
|
40
|
+
/** Cache-aside whose store decision the compute makes — see the
|
|
41
|
+
* `wrapDynamic` note above. Best-effort: never fails on the cache. */
|
|
42
|
+
readonly wrapDynamic: <A, E, R>(key: string, options: DynamicWrapOptions, compute: Effect.Effect<DynamicComputed<A>, E, R>, read: (stored: unknown) => Effect.Effect<Option.Option<A>>) => Effect.Effect<{
|
|
43
|
+
readonly value: A;
|
|
44
|
+
readonly served: DynamicServed;
|
|
45
|
+
}, E, R>;
|
|
46
|
+
/** Per-label counters kept by `wrapDynamic`. */
|
|
47
|
+
readonly queryStats: () => Effect.Effect<Readonly<Record<string, DynamicLabelStats>>>;
|
|
31
48
|
/** A named, key-prefixed partition with its own default ttl/swr/tags.
|
|
32
49
|
* Keys become `<name>:<key>`; per-call options override the defaults;
|
|
33
50
|
* tags stay global (unprefixed) so bus invalidation still reaches
|
|
@@ -39,6 +56,7 @@ declare const Cache_base: Context.ServiceClass<Cache, "@voltro/Cache", {
|
|
|
39
56
|
hits: number;
|
|
40
57
|
misses: number;
|
|
41
58
|
hitRate: number;
|
|
59
|
+
voided: number;
|
|
42
60
|
}>;
|
|
43
61
|
}> & {
|
|
44
62
|
readonly make: Effect.Effect<{
|
|
@@ -49,13 +67,26 @@ declare const Cache_base: Context.ServiceClass<Cache, "@voltro/Cache", {
|
|
|
49
67
|
/** Write-through with the SAME storage shape `wrap` uses (incl. the
|
|
50
68
|
* SWR envelope) — so a value written here is read back identically
|
|
51
69
|
* by a later `wrap`. The dispatcher uses this to keep cached
|
|
52
|
-
* snapshots warm from its live recompute.
|
|
53
|
-
|
|
70
|
+
* snapshots warm from its live recompute. Pass the `fence()` observed
|
|
71
|
+
* before the value was read, so an earlier, slower read can never
|
|
72
|
+
* overwrite a later one. Resolves `false` when the fence voided it. */
|
|
73
|
+
readonly put: <A>(key: string, options: WrapOptions, value: A, fence?: CacheFence) => Effect.Effect<boolean, CacheError>;
|
|
74
|
+
/** The store's invalidation position — observe it before reading the
|
|
75
|
+
* value you will `put`. */
|
|
76
|
+
readonly fence: () => Effect.Effect<CacheFence, CacheError>;
|
|
54
77
|
readonly remove: (key: string) => Effect.Effect<boolean, CacheError>;
|
|
55
78
|
readonly has: (key: string) => Effect.Effect<boolean, CacheError>;
|
|
56
79
|
readonly clear: () => Effect.Effect<void, CacheError>;
|
|
57
80
|
readonly invalidateTag: (tag: string) => Effect.Effect<number, CacheError>;
|
|
58
81
|
readonly wrap: <A, E, R>(key: string, options: WrapOptions, compute: Effect.Effect<A, E, R>) => Effect.Effect<A, E | CacheError, R>;
|
|
82
|
+
/** Cache-aside whose store decision the compute makes — see the
|
|
83
|
+
* `wrapDynamic` note above. Best-effort: never fails on the cache. */
|
|
84
|
+
readonly wrapDynamic: <A, E, R>(key: string, options: DynamicWrapOptions, compute: Effect.Effect<DynamicComputed<A>, E, R>, read: (stored: unknown) => Effect.Effect<Option.Option<A>>) => Effect.Effect<{
|
|
85
|
+
readonly value: A;
|
|
86
|
+
readonly served: DynamicServed;
|
|
87
|
+
}, E, R>;
|
|
88
|
+
/** Per-label counters kept by `wrapDynamic`. */
|
|
89
|
+
readonly queryStats: () => Effect.Effect<Readonly<Record<string, DynamicLabelStats>>>;
|
|
59
90
|
/** A named, key-prefixed partition with its own default ttl/swr/tags.
|
|
60
91
|
* Keys become `<name>:<key>`; per-call options override the defaults;
|
|
61
92
|
* tags stay global (unprefixed) so bus invalidation still reaches
|
|
@@ -67,10 +98,13 @@ declare const Cache_base: Context.ServiceClass<Cache, "@voltro/Cache", {
|
|
|
67
98
|
hits: number;
|
|
68
99
|
misses: number;
|
|
69
100
|
hitRate: number;
|
|
101
|
+
voided: number;
|
|
70
102
|
}>;
|
|
71
103
|
}, never, CacheStore>;
|
|
72
104
|
};
|
|
73
105
|
|
|
106
|
+
export { CACHE_FENCE_RETENTION_MS }
|
|
107
|
+
|
|
74
108
|
export declare class CacheError extends CacheError_base {
|
|
75
109
|
}
|
|
76
110
|
|
|
@@ -84,8 +118,18 @@ declare const CacheError_base: Schema.Class<CacheError, Schema.TaggedStruct<"Cac
|
|
|
84
118
|
readonly cause: Schema.String;
|
|
85
119
|
}>, YieldableError>;
|
|
86
120
|
|
|
121
|
+
/**
|
|
122
|
+
* The store's invalidation position, observed before a compute. Opaque: only
|
|
123
|
+
* hand it back to `setWithTags`. A fence older than
|
|
124
|
+
* `CACHE_FENCE_RETENTION_MS` proves nothing; `Cache.wrap` does not store such
|
|
125
|
+
* a compute.
|
|
126
|
+
*/
|
|
127
|
+
export declare type CacheFence = number;
|
|
128
|
+
|
|
87
129
|
export declare namespace CacheLayer {
|
|
88
130
|
export {
|
|
131
|
+
CacheStoreLayerOptions,
|
|
132
|
+
makeStoreLayer,
|
|
89
133
|
storeLayer,
|
|
90
134
|
layer
|
|
91
135
|
}
|
|
@@ -126,6 +170,10 @@ export declare interface CacheSetWithTagsOptions extends CacheSetOptions {
|
|
|
126
170
|
/** Tags this entry belongs to. `invalidateTag(tag)` drops every entry
|
|
127
171
|
* carrying that tag. */
|
|
128
172
|
readonly tags?: ReadonlyArray<string>;
|
|
173
|
+
/** A `fence()` observed BEFORE the value was computed. When any of `tags`
|
|
174
|
+
* was invalidated since — anywhere that shares this store — the write is
|
|
175
|
+
* void: the value may predate the write behind that invalidation. */
|
|
176
|
+
readonly fence?: CacheFence;
|
|
129
177
|
}
|
|
130
178
|
|
|
131
179
|
export declare class CacheStore extends CacheStore_base {
|
|
@@ -133,6 +181,13 @@ export declare class CacheStore extends CacheStore_base {
|
|
|
133
181
|
|
|
134
182
|
declare const CacheStore_base: Context.ServiceClass<CacheStore, "@voltro/CacheStore", CacheStoreShape>;
|
|
135
183
|
|
|
184
|
+
declare interface CacheStoreLayerOptions {
|
|
185
|
+
readonly backend?: 'memory' | 'redis';
|
|
186
|
+
readonly connectionName?: string;
|
|
187
|
+
readonly keyPrefix?: string;
|
|
188
|
+
readonly connections?: RespConnections;
|
|
189
|
+
}
|
|
190
|
+
|
|
136
191
|
export declare interface CacheStoreShape {
|
|
137
192
|
/** Read a value. `None` on miss OR expiry (expired entries are lazily
|
|
138
193
|
* evicted on read). */
|
|
@@ -140,8 +195,15 @@ export declare interface CacheStoreShape {
|
|
|
140
195
|
/** Write a value with an optional ms TTL. Overwrites any existing entry
|
|
141
196
|
* (clearing its old tag memberships). */
|
|
142
197
|
readonly set: (key: string, value: unknown, options?: CacheSetOptions) => Effect.Effect<void, CacheError>;
|
|
143
|
-
/** Write a value AND register it under the given tags.
|
|
144
|
-
|
|
198
|
+
/** Write a value AND register it under the given tags. Resolves `false`
|
|
199
|
+
* when `options.fence` voided the write (nothing was stored). */
|
|
200
|
+
readonly setWithTags: (key: string, value: unknown, options: CacheSetWithTagsOptions) => Effect.Effect<boolean, CacheError>;
|
|
201
|
+
/** Current invalidation position — see {@link CacheFence}. Every
|
|
202
|
+
* `invalidateTag` advances it, for every participant sharing the store. */
|
|
203
|
+
readonly fence: () => Effect.Effect<CacheFence, CacheError>;
|
|
204
|
+
/** Claim `key` for `ttlMs` if nobody holds it — the cluster single-flight
|
|
205
|
+
* lease. Optional: a process-local store has nothing to coordinate. */
|
|
206
|
+
readonly claim?: (key: string, ttlMs: number) => Effect.Effect<boolean, CacheError>;
|
|
145
207
|
/** Delete one key (and its tag memberships). Resolves `true` if it existed. */
|
|
146
208
|
readonly remove: (key: string) => Effect.Effect<boolean, CacheError>;
|
|
147
209
|
/** Existence check honouring expiry, without deserializing the value. */
|
|
@@ -149,8 +211,9 @@ export declare interface CacheStoreShape {
|
|
|
149
211
|
/** Drop every entry in this cache's namespace. Scoped to the backend's
|
|
150
212
|
* key-prefix — never a global flush on a shared server. */
|
|
151
213
|
readonly clear: () => Effect.Effect<void, CacheError>;
|
|
152
|
-
/** Delete every key registered under `tag`, then drop the tag index
|
|
153
|
-
*
|
|
214
|
+
/** Delete every key registered under `tag`, then drop the tag index, and
|
|
215
|
+
* advance the fence for `tag` (also when nothing carried it). Resolves the
|
|
216
|
+
* count of keys removed. `clear` does not reset the fence. */
|
|
154
217
|
readonly invalidateTag: (tag: string) => Effect.Effect<number, CacheError>;
|
|
155
218
|
}
|
|
156
219
|
|
|
@@ -187,6 +250,52 @@ export declare const cosineSimilarity: (a: ReadonlyArray<number>, b: ReadonlyArr
|
|
|
187
250
|
*/
|
|
188
251
|
export declare const depsForChange: (c: ChangeSignal) => ReadonlyArray<string>;
|
|
189
252
|
|
|
253
|
+
/** A `wrapDynamic` compute's result: the value for THIS caller, and whether
|
|
254
|
+
* (and how) it may be stored for the next. */
|
|
255
|
+
export declare interface DynamicComputed<A> {
|
|
256
|
+
readonly value: A;
|
|
257
|
+
readonly store?: DynamicStore | undefined;
|
|
258
|
+
/** The compute found the call is not a candidate for this cache at all (a
|
|
259
|
+
* query whose handler returned a descriptor): nothing stored, and not
|
|
260
|
+
* counted as a result the cache refused to keep. */
|
|
261
|
+
readonly notApplicable?: boolean | undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
export declare type DynamicEvent = keyof DynamicLabelStats;
|
|
265
|
+
|
|
266
|
+
/** Per-label counters — `queryStats()`, the dashboard Cache panel and the
|
|
267
|
+
* `voltro_query_cache_events_total{query,event}` series. */
|
|
268
|
+
export declare interface DynamicLabelStats {
|
|
269
|
+
readonly hits: number;
|
|
270
|
+
readonly stale: number;
|
|
271
|
+
readonly misses: number;
|
|
272
|
+
readonly stored: number;
|
|
273
|
+
readonly voided: number;
|
|
274
|
+
readonly decodeMisses: number;
|
|
275
|
+
readonly uncacheable: number;
|
|
276
|
+
readonly oversized: number;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export declare type DynamicServed = 'hit' | 'stale' | 'miss';
|
|
280
|
+
|
|
281
|
+
/** What a `wrapDynamic` compute stores, decided AFTER it ran: the encoded
|
|
282
|
+
* value and the tags it actually depends on. Absent ⇒ not stored. */
|
|
283
|
+
export declare interface DynamicStore {
|
|
284
|
+
readonly stored: unknown;
|
|
285
|
+
readonly tags: ReadonlyArray<string>;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export declare interface DynamicWrapOptions {
|
|
289
|
+
readonly ttlMs: number;
|
|
290
|
+
readonly swrMs?: number | undefined;
|
|
291
|
+
/** Cluster single-flight: on a miss, claim the key for this long on a
|
|
292
|
+
* store that can (`CacheStore.claim`); other participants wait for the
|
|
293
|
+
* claimant's value instead of computing it too, up to this bound. */
|
|
294
|
+
readonly leaseMs?: number | undefined;
|
|
295
|
+
/** Bounded label the per-label counters are kept under (a query name). */
|
|
296
|
+
readonly label: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
190
299
|
export declare class InvalidationBus extends InvalidationBus_base {
|
|
191
300
|
/** The bus with its own scope: sinks live as long as the layer. */
|
|
192
301
|
static readonly layer: Layer.Layer<InvalidationBus, never, never>;
|
|
@@ -214,7 +323,10 @@ declare const layer: Layer.Layer<Cache, Config.ConfigError | CacheError>;
|
|
|
214
323
|
export declare const layerMemory: (options?: MemoryCacheOptions) => Layer.Layer<CacheStore>;
|
|
215
324
|
|
|
216
325
|
/** `Layer<CacheStore>` backed by a RESP server (Redis/Valkey/KeyDB/Dragonfly/Upstash). */
|
|
217
|
-
export declare const layerRedis: (options
|
|
326
|
+
export declare const layerRedis: (options?: RedisCacheOptions) => Layer.Layer<CacheStore, CacheError, RedisConnections>;
|
|
327
|
+
|
|
328
|
+
/** Cache semantics over a registry-owned client; never closes its socket. */
|
|
329
|
+
export declare const makeRedisCacheStore: (client: RespClient, prefix?: string) => CacheStoreShape;
|
|
218
330
|
|
|
219
331
|
/**
|
|
220
332
|
* Build a {@link SemanticCacheShape} over a resolved {@link CacheStoreShape}.
|
|
@@ -225,8 +337,19 @@ export declare const layerRedis: (options: RedisCacheOptions) => Layer.Layer<Cac
|
|
|
225
337
|
*/
|
|
226
338
|
export declare const makeSemanticCache: (store: CacheStoreShape, _options?: SemanticCacheOptions) => Effect.Effect<SemanticCacheShape>;
|
|
227
339
|
|
|
340
|
+
/**
|
|
341
|
+
* `Layer<CacheStore>` whose backend (memory | redis) + connection are chosen
|
|
342
|
+
* from the environment. This is the STORE — value/TTL/tag storage — one level
|
|
343
|
+
* below `Cache`. Exposed so a caller can build MORE than one service on ONE
|
|
344
|
+
* store instance: `Layer.provide(storeLayer)` on a merged layer memoises a
|
|
345
|
+
* SINGLE `CacheStore`, shared by every consumer in it (that is how the query
|
|
346
|
+
* `Cache` and a `SemanticCache` end up over the same backend — see
|
|
347
|
+
* `cli/src/cacheFacade.ts`).
|
|
348
|
+
*/
|
|
349
|
+
declare const makeStoreLayer: (options?: CacheStoreLayerOptions) => Layer.Layer<CacheStore, Config.ConfigError | CacheError>;
|
|
350
|
+
|
|
228
351
|
export declare interface MemoryCacheOptions {
|
|
229
|
-
/** Hard cap on live entry count. When exceeded,
|
|
352
|
+
/** Hard cap on live entry count. When exceeded, least-recently-used
|
|
230
353
|
* entries are evicted — the backstop for entries that expired but were
|
|
231
354
|
* never read (lazy eviction never fired). Omit for unbounded. */
|
|
232
355
|
readonly maxEntries?: number;
|
|
@@ -247,11 +370,8 @@ export declare interface PartitionDefaults {
|
|
|
247
370
|
}
|
|
248
371
|
|
|
249
372
|
export declare interface RedisCacheOptions {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
readonly url: string;
|
|
253
|
-
/** Auth token — http (Upstash REST) driver only. */
|
|
254
|
-
readonly token?: string;
|
|
373
|
+
/** Named pooled connection; defaults to cache's environment convention. */
|
|
374
|
+
readonly connectionName?: string;
|
|
255
375
|
readonly keyPrefix?: string;
|
|
256
376
|
}
|
|
257
377
|
|
|
@@ -340,15 +460,6 @@ export declare interface SemanticPutOptions {
|
|
|
340
460
|
readonly key?: string;
|
|
341
461
|
}
|
|
342
462
|
|
|
343
|
-
/**
|
|
344
|
-
* `Layer<CacheStore>` whose backend (memory | redis) + connection are chosen
|
|
345
|
-
* from the environment. This is the STORE — value/TTL/tag storage — one level
|
|
346
|
-
* below `Cache`. Exposed so a caller can build MORE than one service on ONE
|
|
347
|
-
* store instance: `Layer.provide(storeLayer)` on a merged layer memoises a
|
|
348
|
-
* SINGLE `CacheStore`, shared by every consumer in it (that is how the query
|
|
349
|
-
* `Cache` and a `SemanticCache` end up over the same backend — see
|
|
350
|
-
* `cli/src/cacheFacade.ts`).
|
|
351
|
-
*/
|
|
352
463
|
declare const storeLayer: Layer.Layer<CacheStore, Config.ConfigError | CacheError>;
|
|
353
464
|
|
|
354
465
|
/** The dependency tag for a whole table. Coarser than {@link rowDep}: it also
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CacheError as e } from "./errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import { layerMemory as
|
|
4
|
-
import { layerRedis as
|
|
5
|
-
import { Cache as
|
|
6
|
-
import { SemanticCache as
|
|
7
|
-
import { InvalidationBus as
|
|
8
|
-
import { layer_exports as
|
|
9
|
-
export {
|
|
2
|
+
import { CACHE_FENCE_RETENTION_MS as t, CacheStore as n } from "./CacheStore.js";
|
|
3
|
+
import { layerMemory as r } from "./backendMemory.js";
|
|
4
|
+
import { layerRedis as i, makeRedisCacheStore as a } from "./backendRedis.js";
|
|
5
|
+
import { Cache as o } from "./Cache.js";
|
|
6
|
+
import { SemanticCache as s, cosineSimilarity as c, depsForChange as l, makeSemanticCache as u, rowDep as d, tableDep as f } from "./semantic.js";
|
|
7
|
+
import { InvalidationBus as p } from "./invalidationBus.js";
|
|
8
|
+
import { layer_exports as m } from "./layer.js";
|
|
9
|
+
export { t as CACHE_FENCE_RETENTION_MS, o as Cache, e as CacheError, m as CacheLayer, n as CacheStore, p as InvalidationBus, s as SemanticCache, c as cosineSimilarity, l as depsForChange, r as layerMemory, i as layerRedis, a as makeRedisCacheStore, u as makeSemanticCache, d as rowDep, f as tableDep };
|
package/dist/layer.js
CHANGED
|
@@ -3,23 +3,23 @@ import { layerMemory as t } from "./backendMemory.js";
|
|
|
3
3
|
import { layerRedis as n } from "./backendRedis.js";
|
|
4
4
|
import { Cache as r } from "./Cache.js";
|
|
5
5
|
import { Config as i, Effect as a, Layer as o, Option as s } from "effect";
|
|
6
|
+
import { RedisConnections as c, layerConnections as l } from "@voltro/kv/connection";
|
|
6
7
|
//#region src/layer.ts
|
|
7
|
-
var
|
|
8
|
-
layer: () =>
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
var u = /* @__PURE__ */ e({
|
|
9
|
+
layer: () => h,
|
|
10
|
+
makeStoreLayer: () => p,
|
|
11
|
+
storeLayer: () => m
|
|
12
|
+
}), d = a.gen(function* () {
|
|
11
13
|
let e = yield* i.Int("CACHE_MAX_ENTRIES").pipe(i.option), n = s.isSome(e) ? { maxEntries: e.value } : {};
|
|
12
14
|
return t(n);
|
|
13
|
-
}),
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
...s.isSome(r) ? { token: r.value } : {},
|
|
18
|
-
...s.isSome(a) ? { keyPrefix: a.value } : {}
|
|
15
|
+
}), f = (e) => a.gen(function* () {
|
|
16
|
+
let t = yield* i.String("CACHE_KEY_PREFIX").pipe(i.option), r = {
|
|
17
|
+
...e.connectionName === void 0 ? {} : { connectionName: e.connectionName },
|
|
18
|
+
...s.isSome(t) ? { keyPrefix: t.value } : e.keyPrefix === void 0 ? {} : { keyPrefix: e.keyPrefix }
|
|
19
19
|
};
|
|
20
|
-
return n(o);
|
|
21
|
-
}),
|
|
22
|
-
return (yield* i.Literals(["memory", "redis"], "CACHE_BACKEND").pipe(i.withDefault("memory"))) === "redis" ? yield*
|
|
23
|
-
})),
|
|
20
|
+
return n(r).pipe(o.provide(e.connections === void 0 ? l : o.succeed(c, e.connections)));
|
|
21
|
+
}), p = (e = {}) => o.unwrap(a.gen(function* () {
|
|
22
|
+
return (yield* i.Literals(["memory", "redis"], "CACHE_BACKEND").pipe(i.withDefault(e.backend ?? "memory"))) === "redis" ? yield* f(e) : yield* d;
|
|
23
|
+
})), m = p(), h = r.layer.pipe(o.provide(m));
|
|
24
24
|
//#endregion
|
|
25
|
-
export {
|
|
25
|
+
export { h as layer, u as layer_exports, p as makeStoreLayer, m as storeLayer };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voltro/cache",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.87.0",
|
|
4
4
|
"description": "Effect-native cache primitive — memory + RESP (Redis/Valkey/KeyDB/Dragonfly/Upstash) backends, tag invalidation, single-flight wrap.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"voltro",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"node": ">=24.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@voltro/kv": "0.
|
|
36
|
+
"@voltro/kv": "0.87.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"effect": "4.0.1"
|