@c9up/echo 0.1.11 → 0.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -1
- package/dist/EchoProvider.d.ts +7 -0
- package/dist/EchoProvider.d.ts.map +1 -1
- package/dist/EchoProvider.js +23 -3
- package/dist/EchoProvider.js.map +1 -1
- package/dist/StoreManager.d.ts +33 -1
- package/dist/StoreManager.d.ts.map +1 -1
- package/dist/StoreManager.js +67 -2
- package/dist/StoreManager.js.map +1 -1
- package/dist/configure.d.ts +18 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +36 -0
- package/dist/configure.js.map +1 -0
- package/dist/drivers/TieredDriver.d.ts.map +1 -1
- package/dist/drivers/TieredDriver.js +21 -3
- package/dist/drivers/TieredDriver.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/services/main.d.ts +5 -0
- package/dist/services/main.d.ts.map +1 -1
- package/dist/services/main.js +7 -0
- package/dist/services/main.js.map +1 -1
- package/package.json +5 -1
- package/src/EchoProvider.ts +22 -3
- package/src/StoreManager.ts +85 -3
- package/src/configure.ts +50 -0
- package/src/drivers/TieredDriver.ts +26 -2
- package/src/index.ts +2 -0
- package/src/services/main.ts +8 -0
package/README.md
CHANGED
|
@@ -11,9 +11,12 @@ pnpm add @c9up/echo
|
|
|
11
11
|
ream configure @c9up/echo
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
+
`ream add @c9up/echo` installs it, registers the provider and writes
|
|
15
|
+
`config/cache.ts`. The rest of this page assumes that has run.
|
|
16
|
+
|
|
14
17
|
## Usage
|
|
15
18
|
|
|
16
|
-
Register the provider
|
|
19
|
+
Register the provider, then name the cache stores in `config/cache.ts`:
|
|
17
20
|
|
|
18
21
|
```ts
|
|
19
22
|
// reamrc.ts
|
|
@@ -22,6 +25,42 @@ providers: [
|
|
|
22
25
|
]
|
|
23
26
|
```
|
|
24
27
|
|
|
28
|
+
```ts
|
|
29
|
+
// config/cache.ts
|
|
30
|
+
import { defineConfig, drivers, store } from '@c9up/echo'
|
|
31
|
+
import env from '#start/env'
|
|
32
|
+
|
|
33
|
+
export default defineConfig({
|
|
34
|
+
default: env.get('CACHE_STORE'),
|
|
35
|
+
stores: {
|
|
36
|
+
memory: store().useL1Layer(drivers.memory()),
|
|
37
|
+
|
|
38
|
+
tiered: store({ ttl: 60 })
|
|
39
|
+
.useL1Layer(drivers.memory())
|
|
40
|
+
.useL2Layer(drivers.redis({ connection: 'main' })),
|
|
41
|
+
},
|
|
42
|
+
})
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
import cache from '@c9up/echo/services/main'
|
|
47
|
+
|
|
48
|
+
await cache.set({ key: 'user:1', value: user })
|
|
49
|
+
await cache.use('tiered').get({ key: 'user:1' })
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
A store is described a layer at a time: **L1** is the fast one (memory), **L2**
|
|
53
|
+
the shared one (Redis) — what makes the cache survive a restart. With both, a
|
|
54
|
+
read hits L1, a miss falls to L2, and a write reaches both. `useBus()` keeps
|
|
55
|
+
each instance's L1 in step after a write, and needs two layers to mean
|
|
56
|
+
anything.
|
|
57
|
+
|
|
58
|
+
Stores are built on first use, so naming a Redis store in an environment that
|
|
59
|
+
runs on memory opens no connection.
|
|
60
|
+
|
|
61
|
+
The plain `{ driver: drivers.memory(), ttl: 60 }` form is still accepted for
|
|
62
|
+
configs written against it.
|
|
63
|
+
|
|
25
64
|
## Entry points
|
|
26
65
|
|
|
27
66
|
- `@c9up/echo` — main API
|
package/dist/EchoProvider.d.ts
CHANGED
|
@@ -52,6 +52,13 @@ export default class EchoProvider {
|
|
|
52
52
|
constructor(app: EchoAppContext);
|
|
53
53
|
register(): void;
|
|
54
54
|
boot(): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Release the cache the app booted.
|
|
57
|
+
*
|
|
58
|
+
* The memory driver runs a sweep on a timer and the redis driver holds a
|
|
59
|
+
* connection. Neither is released on its own, so across a dev reload or a
|
|
60
|
+
* test run each cycle leaves another one behind.
|
|
61
|
+
*/
|
|
55
62
|
shutdown(): Promise<void>;
|
|
56
63
|
}
|
|
57
64
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EchoProvider.d.ts","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAMnE;;;;GAIG;AACH,UAAU,aAAa;IACtB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,eAAe;IACxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACtD;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CAClB;AAmBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;;IACpB,SAAS,CAAC,GAAG,EAAE,cAAc;gBAAnB,GAAG,EAAE,cAAc;IAYzC,QAAQ,IAAI,IAAI;
|
|
1
|
+
{"version":3,"file":"EchoProvider.d.ts","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,WAAW,EAAgB,MAAM,mBAAmB,CAAC;AAMnE;;;;GAIG;AACH,UAAU,aAAa;IACtB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,GAAG,IAAI,CAAC;IACxD,OAAO,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AACD,UAAU,eAAe;IACxB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;CAC7C;AACD,MAAM,WAAW,cAAc;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,EAAE,eAAe,CAAC;CACxB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACtD;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,QAAQ,CAAC;CAClB;AAmBD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;;IACpB,SAAS,CAAC,GAAG,EAAE,cAAc;gBAAnB,GAAG,EAAE,cAAc;IAYzC,QAAQ,IAAI,IAAI;IA6BV,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
|
package/dist/EchoProvider.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CacheManager } from "./CacheManager.js";
|
|
2
2
|
import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
3
3
|
import { CacheStoreManager } from "./StoreManager.js";
|
|
4
|
-
import { setCache } from "./services/main.js";
|
|
4
|
+
import { clearCache, getCache, setCache } from "./services/main.js";
|
|
5
5
|
function isEmitter(value) {
|
|
6
6
|
return (typeof value === "object" &&
|
|
7
7
|
value !== null &&
|
|
@@ -67,9 +67,29 @@ export default class EchoProvider {
|
|
|
67
67
|
});
|
|
68
68
|
this.app.container.singleton("cache", () => this.app.container.resolve(CacheManager));
|
|
69
69
|
}
|
|
70
|
+
/** The cache THIS provider booted — not whatever the module singleton holds. */
|
|
71
|
+
#cache;
|
|
70
72
|
async boot() {
|
|
71
|
-
|
|
73
|
+
this.#cache = await this.app.container.resolve(CacheManager);
|
|
74
|
+
setCache(this.#cache);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Release the cache the app booted.
|
|
78
|
+
*
|
|
79
|
+
* The memory driver runs a sweep on a timer and the redis driver holds a
|
|
80
|
+
* connection. Neither is released on its own, so across a dev reload or a
|
|
81
|
+
* test run each cycle leaves another one behind.
|
|
82
|
+
*/
|
|
83
|
+
async shutdown() {
|
|
84
|
+
if (!this.#cache)
|
|
85
|
+
return;
|
|
86
|
+
await this.#cache.disconnect();
|
|
87
|
+
// Two applications can share a process — parallel tests, a hot reload.
|
|
88
|
+
// The module singleton holds whichever booted last, so it is only ours
|
|
89
|
+
// to clear while it still points at the cache this provider booted.
|
|
90
|
+
if (getCache() === this.#cache)
|
|
91
|
+
clearCache();
|
|
92
|
+
this.#cache = undefined;
|
|
72
93
|
}
|
|
73
|
-
async shutdown() { }
|
|
74
94
|
}
|
|
75
95
|
//# sourceMappingURL=EchoProvider.js.map
|
package/dist/EchoProvider.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EchoProvider.js","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAyB,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"EchoProvider.js","sourceRoot":"","sources":["../src/EchoProvider.ts"],"names":[],"mappings":"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"}
|
package/dist/StoreManager.d.ts
CHANGED
|
@@ -33,10 +33,42 @@ export interface StoreConfig {
|
|
|
33
33
|
}
|
|
34
34
|
export interface MultiStoreConfig {
|
|
35
35
|
default: string;
|
|
36
|
-
|
|
36
|
+
/**
|
|
37
|
+
* The stores this application can use, by name. Each is a {@link store}
|
|
38
|
+
* builder — the shape a cache config takes — or the plain
|
|
39
|
+
* `{ driver, …options }` form kept for configs written against it.
|
|
40
|
+
*/
|
|
41
|
+
stores: Record<string, StoreConfig | Store>;
|
|
37
42
|
/** Shared emitter for all stores' events. */
|
|
38
43
|
emitter?: CacheEmitter;
|
|
39
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* A store, described the way a cache config describes one: a layer at a time.
|
|
47
|
+
*
|
|
48
|
+
* stores: {
|
|
49
|
+
* memoryOnly: store().useL1Layer(drivers.memory()),
|
|
50
|
+
* default: store({ ttl: 60 })
|
|
51
|
+
* .useL1Layer(drivers.memory())
|
|
52
|
+
* .useL2Layer(drivers.redis({ connection: "main" })),
|
|
53
|
+
* }
|
|
54
|
+
*
|
|
55
|
+
* One layer is that driver; two are a tiered driver over both, which is what
|
|
56
|
+
* the layering means — reads hit L1, misses fall to L2, and writes go to both.
|
|
57
|
+
*/
|
|
58
|
+
export declare class Store {
|
|
59
|
+
#private;
|
|
60
|
+
constructor(options?: Omit<StoreConfig, "driver">);
|
|
61
|
+
/** The fast layer, usually memory. */
|
|
62
|
+
useL1Layer(driver: DriverFactory): this;
|
|
63
|
+
/** The shared layer, usually Redis — what makes the cache survive a restart. */
|
|
64
|
+
useL2Layer(driver: DriverFactory): this;
|
|
65
|
+
/** The bus that keeps every instance's L1 in step after a write. */
|
|
66
|
+
useBus(bus: CacheBus): this;
|
|
67
|
+
/** The `{ driver, …options }` the manager consumes. */
|
|
68
|
+
entry(): StoreConfig;
|
|
69
|
+
}
|
|
70
|
+
/** Start describing a store — AdonisJS's `store()`. */
|
|
71
|
+
export declare function store(options?: Omit<StoreConfig, "driver">): Store;
|
|
40
72
|
/** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
|
|
41
73
|
export declare const drivers: {
|
|
42
74
|
memory(options?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreManager.d.ts","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,KAAK,WAAW,EAAe,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,KAAK,QAAQ,EAAgB,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3E,2EAA2E;AAC3E,MAAM,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC3B,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,WAAW,CAAC,EAAE,QAAQ,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"StoreManager.d.ts","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"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"}
|
package/dist/StoreManager.js
CHANGED
|
@@ -19,6 +19,70 @@ import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
|
19
19
|
import { RedisDriver } from "./drivers/RedisDriver.js";
|
|
20
20
|
import { TieredDriver } from "./drivers/TieredDriver.js";
|
|
21
21
|
import { quasarConnection } from "./quasar.js";
|
|
22
|
+
/**
|
|
23
|
+
* A store, described the way a cache config describes one: a layer at a time.
|
|
24
|
+
*
|
|
25
|
+
* stores: {
|
|
26
|
+
* memoryOnly: store().useL1Layer(drivers.memory()),
|
|
27
|
+
* default: store({ ttl: 60 })
|
|
28
|
+
* .useL1Layer(drivers.memory())
|
|
29
|
+
* .useL2Layer(drivers.redis({ connection: "main" })),
|
|
30
|
+
* }
|
|
31
|
+
*
|
|
32
|
+
* One layer is that driver; two are a tiered driver over both, which is what
|
|
33
|
+
* the layering means — reads hit L1, misses fall to L2, and writes go to both.
|
|
34
|
+
*/
|
|
35
|
+
export class Store {
|
|
36
|
+
#options;
|
|
37
|
+
#l1;
|
|
38
|
+
#l2;
|
|
39
|
+
#bus;
|
|
40
|
+
constructor(options = {}) {
|
|
41
|
+
this.#options = options;
|
|
42
|
+
}
|
|
43
|
+
/** The fast layer, usually memory. */
|
|
44
|
+
useL1Layer(driver) {
|
|
45
|
+
this.#l1 = driver;
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
/** The shared layer, usually Redis — what makes the cache survive a restart. */
|
|
49
|
+
useL2Layer(driver) {
|
|
50
|
+
this.#l2 = driver;
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/** The bus that keeps every instance's L1 in step after a write. */
|
|
54
|
+
useBus(bus) {
|
|
55
|
+
this.#bus = bus;
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/** The `{ driver, …options }` the manager consumes. */
|
|
59
|
+
entry() {
|
|
60
|
+
const l1 = this.#l1;
|
|
61
|
+
const l2 = this.#l2;
|
|
62
|
+
if (!l1 && !l2) {
|
|
63
|
+
throw new Error("Echo: a store needs a layer — call useL1Layer() or useL2Layer() on it.");
|
|
64
|
+
}
|
|
65
|
+
if (l1 && l2) {
|
|
66
|
+
return {
|
|
67
|
+
...this.#options,
|
|
68
|
+
driver: drivers.tiered({ l1, l2, bus: this.#bus }),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const only = (l1 ?? l2);
|
|
72
|
+
if (this.#bus) {
|
|
73
|
+
throw new Error("Echo: a bus only means something with two layers — it keeps each instance's L1 in step. Add useL2Layer(), or drop useBus().");
|
|
74
|
+
}
|
|
75
|
+
return { ...this.#options, driver: only };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Start describing a store — AdonisJS's `store()`. */
|
|
79
|
+
export function store(options) {
|
|
80
|
+
return new Store(options);
|
|
81
|
+
}
|
|
82
|
+
/** Normalise either accepted form to the one the manager reads. */
|
|
83
|
+
function entryOf(config) {
|
|
84
|
+
return config instanceof Store ? config.entry() : config;
|
|
85
|
+
}
|
|
22
86
|
/** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
|
|
23
87
|
export const drivers = {
|
|
24
88
|
memory(options) {
|
|
@@ -68,10 +132,11 @@ export class CacheStoreManager {
|
|
|
68
132
|
const existing = this.#built.get(store);
|
|
69
133
|
if (existing)
|
|
70
134
|
return existing;
|
|
71
|
-
const
|
|
72
|
-
if (!
|
|
135
|
+
const declared = this.#config.stores[store];
|
|
136
|
+
if (!declared) {
|
|
73
137
|
throw new Error(`Echo: unknown cache store "${store}"`);
|
|
74
138
|
}
|
|
139
|
+
const cfg = entryOf(declared);
|
|
75
140
|
const manager = new CacheManager(cfg.driver(), {
|
|
76
141
|
prefix: cfg.prefix,
|
|
77
142
|
ttl: cfg.ttl,
|
package/dist/StoreManager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StoreManager.js","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAoB,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAiB,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"StoreManager.js","sourceRoot":"","sources":["../src/StoreManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/echo` — wire the cache in one command.
|
|
3
|
+
*
|
|
4
|
+
* The provider alone is not enough: it reads `config/cache.ts`, and a package
|
|
5
|
+
* registered without one falls back to a default that is rarely the one an
|
|
6
|
+
* application wants. Writing both together is what makes `ream add` mean
|
|
7
|
+
* installed AND working.
|
|
8
|
+
*/
|
|
9
|
+
interface Codemods {
|
|
10
|
+
addProvider(importPath: string): Promise<void>;
|
|
11
|
+
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
12
|
+
writeFile(filePath: string, content: string, options?: {
|
|
13
|
+
force?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
export declare function configure(codemods: Codemods): Promise<void>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=configure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,UAAU,QAAQ;IACjB,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,SAAS,CACR,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;CACjB;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BjE"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/echo` — wire the cache in one command.
|
|
3
|
+
*
|
|
4
|
+
* The provider alone is not enough: it reads `config/cache.ts`, and a package
|
|
5
|
+
* registered without one falls back to a default that is rarely the one an
|
|
6
|
+
* application wants. Writing both together is what makes `ream add` mean
|
|
7
|
+
* installed AND working.
|
|
8
|
+
*/
|
|
9
|
+
export async function configure(codemods) {
|
|
10
|
+
// The config below reads these, so they are declared here. Writing the file
|
|
11
|
+
// without them leaves an application whose config asks the environment for
|
|
12
|
+
// something nothing ever put there.
|
|
13
|
+
await codemods.addEnvVars({
|
|
14
|
+
CACHE_STORE: "memory",
|
|
15
|
+
});
|
|
16
|
+
await codemods.addProvider("@c9up/echo/provider");
|
|
17
|
+
await codemods.writeFile("config/cache.ts", `import { defineConfig, drivers, store } from '@c9up/echo'
|
|
18
|
+
import env from '#start/env'
|
|
19
|
+
|
|
20
|
+
export default defineConfig({
|
|
21
|
+
default: env.get('CACHE_STORE', 'memory'),
|
|
22
|
+
|
|
23
|
+
stores: {
|
|
24
|
+
// One layer, in this process.
|
|
25
|
+
memory: store().useL1Layer(drivers.memory({ maxItems: 1000 })),
|
|
26
|
+
|
|
27
|
+
// Two layers: memory in front of Redis, with a bus so every instance
|
|
28
|
+
// drops its own L1 entry when another writes.
|
|
29
|
+
tiered: store()
|
|
30
|
+
.useL1Layer(drivers.memory({ maxItems: 1000 }))
|
|
31
|
+
.useL2Layer(drivers.redis({ connection: 'main' }))
|
|
32
|
+
.useBus(drivers.redisBus({ connection: 'main' })),
|
|
33
|
+
},
|
|
34
|
+
})`);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=configure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAYH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,QAAkB;IACjD,4EAA4E;IAC5E,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,QAAQ,CAAC,UAAU,CAAC;QACzB,WAAW,EAAE,QAAQ;KACrB,CAAC,CAAC;IAEH,MAAM,QAAQ,CAAC,WAAW,CAAC,qBAAqB,CAAC,CAAC;IAClD,MAAM,QAAQ,CAAC,SAAS,CACvB,iBAAiB,EACjB;;;;;;;;;;;;;;;;;GAiBC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TieredDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/TieredDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,MAAM,aAAa,CAAC;AAErB,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAED,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACxB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,WAAW,CAAC;IAChB,EAAE,EAAE,WAAW,CAAC;IAChB,GAAG,CAAC,EAAE,QAAQ,CAAC;CACf;AAqCD,qBAAa,YAAa,YAAW,cAAc;;gBAKtC,OAAO,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"TieredDriver.d.ts","sourceRoot":"","sources":["../../src/drivers/TieredDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,MAAM,aAAa,CAAC;AAErB,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,EAAE,CAAC;CACf;AAED,sFAAsF;AACtF,MAAM,WAAW,QAAQ;IACxB,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,SAAS,CAAC,OAAO,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,GAAG,IAAI,CAAC;CACxD;AAED,MAAM,WAAW,mBAAmB;IACnC,EAAE,EAAE,WAAW,CAAC;IAChB,EAAE,EAAE,WAAW,CAAC;IAChB,GAAG,CAAC,EAAE,QAAQ,CAAC;CACf;AAqCD,qBAAa,YAAa,YAAW,cAAc;;gBAKtC,OAAO,EAAE,mBAAmB;IAsClC,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IA+BjE,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAMhD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpE,QAAQ,CACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,gBAAgB,GACvB,OAAO,CAAC,IAAI,CAAC;IAMV,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlC,WAAW,CAChB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,MAAM,EAAE,EACd,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC;IAIV,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAehD,gDAAgD;IAC1C,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAG9C,8CAA8C;IACxC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B,qDAAqD;IAC/C,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAIjC"}
|
|
@@ -41,11 +41,29 @@ export class TieredDriver {
|
|
|
41
41
|
this.#bus?.subscribe((message) => {
|
|
42
42
|
// Peer invalidation: only the local L1 needs clearing (L2 is shared).
|
|
43
43
|
if (message.type === "clear") {
|
|
44
|
-
|
|
44
|
+
this.#invalidate("flush", () => this.#l1.flush());
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
for (const key of message.keys)
|
|
48
|
-
|
|
47
|
+
for (const key of message.keys) {
|
|
48
|
+
this.#invalidate(key, () => this.#l1.delete(key));
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Apply one peer invalidation to L1, reporting rather than escaping.
|
|
54
|
+
*
|
|
55
|
+
* This runs inside a bus callback, so nobody awaits it: an L1 that rejects
|
|
56
|
+
* — a Redis L1 whose socket just dropped, a driver mid-shutdown — was an
|
|
57
|
+
* unhandled rejection, which on a default Node ends the process. A cache
|
|
58
|
+
* layer failing to forget a key must not do that.
|
|
59
|
+
*
|
|
60
|
+
* It is reported and not retried: the entry keeps its own TTL, so the worst
|
|
61
|
+
* case is one stale read window on this instance, and a retry loop against
|
|
62
|
+
* a driver that is already failing buys nothing.
|
|
63
|
+
*/
|
|
64
|
+
#invalidate(what, run) {
|
|
65
|
+
void (async () => run())().catch((error) => {
|
|
66
|
+
process.stderr.write(`[echo] tiered L1 invalidation of '${what}' failed; the local copy may be stale until it expires: ${error instanceof Error ? error.message : String(error)}\n`);
|
|
49
67
|
});
|
|
50
68
|
}
|
|
51
69
|
async getEntry(key) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TieredDriver.js","sourceRoot":"","sources":["../../src/drivers/TieredDriver.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AA2BH,SAAS,UAAU,CAAC,MAAmB;IACtC,MAAM,SAAS,GAA4B,MAAM,CAAC;IAClD,OAAO,CACN,OAAO,SAAS,CAAC,WAAW,KAAK,UAAU;QAC3C,CAAC,OAAO,SAAS,CAAC,WAAW,KAAK,UAAU;YAC3C,OAAO,SAAS,CAAC,SAAS,KAAK,UAAU,CAAC,CAC3C,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CACvB,MAAmB,EACnB,GAAW;IAEX,IAAI,MAAM,CAAC,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAI,GAAG,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,GAAG,CAAI,GAAG,CAAC,CAAC;IACvC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,UAAU,CACxB,MAAmB,EACnB,GAAW,EACX,KAAc,EACd,OAAyB;IAEzB,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAC3C,OAAO;IACR,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACvE,OAAO;IACR,CAAC;IACD,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,OAAO,YAAY;IACxB,GAAG,CAAc;IACjB,GAAG,CAAc;IACjB,IAAI,CAAuB;IAE3B,YAAY,OAA4B;QACvC,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC;QACtB,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC;QACxB,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,OAAO,EAAE,EAAE;YAChC,sEAAsE;YACtE,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC9B,
|
|
1
|
+
{"version":3,"file":"TieredDriver.js","sourceRoot":"","sources":["../../src/drivers/TieredDriver.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type { Duration } from "./duration.js";
|
|
|
19
19
|
export { parseDuration, resolveTtlSeconds } from "./duration.js";
|
|
20
20
|
export type { EchoProviderConfig } from "./EchoProvider.js";
|
|
21
21
|
export { FactoryError, TimeoutError } from "./errors.js";
|
|
22
|
-
export { CacheStoreManager, type DriverFactory, drivers, type MultiStoreConfig, type StoreConfig, } from "./StoreManager.js";
|
|
22
|
+
export { CacheStoreManager, type DriverFactory, drivers, type MultiStoreConfig, Store, type StoreConfig, store, } from "./StoreManager.js";
|
|
23
23
|
export type { CacheEmitter, CacheEntry, CacheEventMap, DefaultValue, DeleteByTagOptions, DeleteManyOptions, DeleteOptions, ExpireOptions, Factory, GetOptions, GetOrSetForeverOptions, GetOrSetOptions, HasOptions, SetOptions, TaggableDriver, } from "./types.js";
|
|
24
24
|
import type { EchoProviderConfig } from "./EchoProvider.js";
|
|
25
25
|
import type { MultiStoreConfig } from "./StoreManager.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EACX,UAAU,EACV,QAAQ,EACR,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EACjB,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,YAAY,EACX,UAAU,EACV,QAAQ,EACR,mBAAmB,GACnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,YAAY,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACjE,YAAY,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EACjB,KAAK,aAAa,EAClB,OAAO,EACP,KAAK,gBAAgB,EACrB,KAAK,EACL,KAAK,WAAW,EAChB,KAAK,GACL,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACX,YAAY,EACZ,UAAU,EACV,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,OAAO,EACP,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,UAAU,EACV,UAAU,EACV,cAAc,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,kBAAkB,GAAG,gBAAgB,EAC3E,MAAM,EAAE,CAAC,GACP,CAAC,CAEH"}
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ export { RedisDriver } from "./drivers/RedisDriver.js";
|
|
|
14
14
|
export { TieredDriver } from "./drivers/TieredDriver.js";
|
|
15
15
|
export { parseDuration, resolveTtlSeconds } from "./duration.js";
|
|
16
16
|
export { FactoryError, TimeoutError } from "./errors.js";
|
|
17
|
-
export { CacheStoreManager, drivers, } from "./StoreManager.js";
|
|
17
|
+
export { CacheStoreManager, drivers, Store, store, } from "./StoreManager.js";
|
|
18
18
|
/**
|
|
19
19
|
* Author-time config helper for `config/cache.ts` — AdonisJS cache `defineConfig`
|
|
20
20
|
* parity. Identity at runtime; the generic preserves literal types for inference.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EAEjB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAMvD,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACN,iBAAiB,EAEjB,OAAO,EAEP,KAAK,EAEL,KAAK,GACL,MAAM,mBAAmB,CAAC;AAsB3B;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC3B,MAAS;IAET,OAAO,MAAM,CAAC;AACf,CAAC"}
|
package/dist/services/main.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ import type { CacheManager } from "../CacheManager.js";
|
|
|
15
15
|
export declare function setCache(value: CacheManager): void;
|
|
16
16
|
/** @internal Read the singleton (or `undefined` pre-boot). */
|
|
17
17
|
export declare function getCache(): CacheManager | undefined;
|
|
18
|
+
/**
|
|
19
|
+
* @internal Release the singleton, so a shut-down application does not leave a
|
|
20
|
+
* disconnected cache reachable through `services/main`.
|
|
21
|
+
*/
|
|
22
|
+
export declare function clearCache(): void;
|
|
18
23
|
declare const cache: CacheManager;
|
|
19
24
|
export default cache;
|
|
20
25
|
//# sourceMappingURL=main.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAElD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEnD;AAED,QAAA,MAAM,KAAK,EAAE,YAoBX,CAAC;AAEH,eAAe,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIvD,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAElD;AAED,8DAA8D;AAC9D,wBAAgB,QAAQ,IAAI,YAAY,GAAG,SAAS,CAEnD;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,QAAA,MAAM,KAAK,EAAE,YAoBX,CAAC;AAEH,eAAe,KAAK,CAAC"}
|
package/dist/services/main.js
CHANGED
|
@@ -19,6 +19,13 @@ export function setCache(value) {
|
|
|
19
19
|
export function getCache() {
|
|
20
20
|
return instance;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* @internal Release the singleton, so a shut-down application does not leave a
|
|
24
|
+
* disconnected cache reachable through `services/main`.
|
|
25
|
+
*/
|
|
26
|
+
export function clearCache() {
|
|
27
|
+
instance = undefined;
|
|
28
|
+
}
|
|
22
29
|
const cache = new Proxy({}, {
|
|
23
30
|
get(_target, prop) {
|
|
24
31
|
// A module loader inspects what it imports before anyone uses it: it reads
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,IAAI,QAAkC,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC3C,QAAQ,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,QAAQ;IACvB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED,MAAM,KAAK,GAAiB,IAAI,KAAK,CAAC,EAAkB,EAAE;IACzD,GAAG,CAAC,OAAO,EAAE,IAAI;QAChB,2EAA2E;QAC3E,0EAA0E;QAC1E,8DAA8D;QAC9D,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACd,wEAAwE;gBACvE,4DAA4D,CAC7D,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;CACD,CAAC,CAAC;AAEH,eAAe,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/services/main.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,IAAI,QAAkC,CAAC;AAEvC,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAmB;IAC3C,QAAQ,GAAG,KAAK,CAAC;AAClB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,QAAQ;IACvB,OAAO,QAAQ,CAAC;AACjB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACzB,QAAQ,GAAG,SAAS,CAAC;AACtB,CAAC;AAED,MAAM,KAAK,GAAiB,IAAI,KAAK,CAAC,EAAkB,EAAE;IACzD,GAAG,CAAC,OAAO,EAAE,IAAI;QAChB,2EAA2E;QAC3E,0EAA0E;QAC1E,8DAA8D;QAC9D,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACjD,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACd,wEAAwE;gBACvE,4DAA4D,CAC7D,CAAC;QACH,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACpD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;CACD,CAAC,CAAC;AAEH,eAAe,KAAK,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@c9up/echo",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"description": "Cache — pluggable cache contract with memory + Redis drivers for the Ream framework",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -15,6 +15,10 @@
|
|
|
15
15
|
"types": "./dist/EchoProvider.d.ts",
|
|
16
16
|
"import": "./dist/EchoProvider.js"
|
|
17
17
|
},
|
|
18
|
+
"./configure": {
|
|
19
|
+
"types": "./dist/configure.d.ts",
|
|
20
|
+
"import": "./dist/configure.js"
|
|
21
|
+
},
|
|
18
22
|
"./services/main": {
|
|
19
23
|
"types": "./dist/services/main.d.ts",
|
|
20
24
|
"import": "./dist/services/main.js"
|
package/src/EchoProvider.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type CacheConfig, CacheManager } from "./CacheManager.js";
|
|
2
2
|
import { MemoryDriver } from "./drivers/MemoryDriver.js";
|
|
3
3
|
import { CacheStoreManager, type MultiStoreConfig } from "./StoreManager.js";
|
|
4
|
-
import { setCache } from "./services/main.js";
|
|
4
|
+
import { clearCache, getCache, setCache } from "./services/main.js";
|
|
5
5
|
import type { CacheEmitter } from "./types.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -109,9 +109,28 @@ export default class EchoProvider {
|
|
|
109
109
|
);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
/** The cache THIS provider booted — not whatever the module singleton holds. */
|
|
113
|
+
#cache: CacheManager | undefined;
|
|
114
|
+
|
|
112
115
|
async boot(): Promise<void> {
|
|
113
|
-
|
|
116
|
+
this.#cache = await this.app.container.resolve<CacheManager>(CacheManager);
|
|
117
|
+
setCache(this.#cache);
|
|
114
118
|
}
|
|
115
119
|
|
|
116
|
-
|
|
120
|
+
/**
|
|
121
|
+
* Release the cache the app booted.
|
|
122
|
+
*
|
|
123
|
+
* The memory driver runs a sweep on a timer and the redis driver holds a
|
|
124
|
+
* connection. Neither is released on its own, so across a dev reload or a
|
|
125
|
+
* test run each cycle leaves another one behind.
|
|
126
|
+
*/
|
|
127
|
+
async shutdown(): Promise<void> {
|
|
128
|
+
if (!this.#cache) return;
|
|
129
|
+
await this.#cache.disconnect();
|
|
130
|
+
// Two applications can share a process — parallel tests, a hot reload.
|
|
131
|
+
// The module singleton holds whichever booted last, so it is only ours
|
|
132
|
+
// to clear while it still points at the cache this provider booted.
|
|
133
|
+
if (getCache() === this.#cache) clearCache();
|
|
134
|
+
this.#cache = undefined;
|
|
135
|
+
}
|
|
117
136
|
}
|
package/src/StoreManager.ts
CHANGED
|
@@ -39,11 +39,92 @@ export interface StoreConfig {
|
|
|
39
39
|
|
|
40
40
|
export interface MultiStoreConfig {
|
|
41
41
|
default: string;
|
|
42
|
-
|
|
42
|
+
/**
|
|
43
|
+
* The stores this application can use, by name. Each is a {@link store}
|
|
44
|
+
* builder — the shape a cache config takes — or the plain
|
|
45
|
+
* `{ driver, …options }` form kept for configs written against it.
|
|
46
|
+
*/
|
|
47
|
+
stores: Record<string, StoreConfig | Store>;
|
|
43
48
|
/** Shared emitter for all stores' events. */
|
|
44
49
|
emitter?: CacheEmitter;
|
|
45
50
|
}
|
|
46
51
|
|
|
52
|
+
/**
|
|
53
|
+
* A store, described the way a cache config describes one: a layer at a time.
|
|
54
|
+
*
|
|
55
|
+
* stores: {
|
|
56
|
+
* memoryOnly: store().useL1Layer(drivers.memory()),
|
|
57
|
+
* default: store({ ttl: 60 })
|
|
58
|
+
* .useL1Layer(drivers.memory())
|
|
59
|
+
* .useL2Layer(drivers.redis({ connection: "main" })),
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* One layer is that driver; two are a tiered driver over both, which is what
|
|
63
|
+
* the layering means — reads hit L1, misses fall to L2, and writes go to both.
|
|
64
|
+
*/
|
|
65
|
+
export class Store {
|
|
66
|
+
readonly #options: Omit<StoreConfig, "driver">;
|
|
67
|
+
#l1: DriverFactory | undefined;
|
|
68
|
+
#l2: DriverFactory | undefined;
|
|
69
|
+
#bus: CacheBus | undefined;
|
|
70
|
+
|
|
71
|
+
constructor(options: Omit<StoreConfig, "driver"> = {}) {
|
|
72
|
+
this.#options = options;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** The fast layer, usually memory. */
|
|
76
|
+
useL1Layer(driver: DriverFactory): this {
|
|
77
|
+
this.#l1 = driver;
|
|
78
|
+
return this;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** The shared layer, usually Redis — what makes the cache survive a restart. */
|
|
82
|
+
useL2Layer(driver: DriverFactory): this {
|
|
83
|
+
this.#l2 = driver;
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** The bus that keeps every instance's L1 in step after a write. */
|
|
88
|
+
useBus(bus: CacheBus): this {
|
|
89
|
+
this.#bus = bus;
|
|
90
|
+
return this;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** The `{ driver, …options }` the manager consumes. */
|
|
94
|
+
entry(): StoreConfig {
|
|
95
|
+
const l1 = this.#l1;
|
|
96
|
+
const l2 = this.#l2;
|
|
97
|
+
if (!l1 && !l2) {
|
|
98
|
+
throw new Error(
|
|
99
|
+
"Echo: a store needs a layer — call useL1Layer() or useL2Layer() on it.",
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
if (l1 && l2) {
|
|
103
|
+
return {
|
|
104
|
+
...this.#options,
|
|
105
|
+
driver: drivers.tiered({ l1, l2, bus: this.#bus }),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const only = (l1 ?? l2) as DriverFactory;
|
|
109
|
+
if (this.#bus) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
"Echo: a bus only means something with two layers — it keeps each instance's L1 in step. Add useL2Layer(), or drop useBus().",
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return { ...this.#options, driver: only };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Start describing a store — AdonisJS's `store()`. */
|
|
119
|
+
export function store(options?: Omit<StoreConfig, "driver">): Store {
|
|
120
|
+
return new Store(options);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Normalise either accepted form to the one the manager reads. */
|
|
124
|
+
function entryOf(config: StoreConfig | Store): StoreConfig {
|
|
125
|
+
return config instanceof Store ? config.entry() : config;
|
|
126
|
+
}
|
|
127
|
+
|
|
47
128
|
/** Driver factory helpers (bento `drivers.memory` / `drivers.redis`). */
|
|
48
129
|
export const drivers = {
|
|
49
130
|
memory(options?: { sweepIntervalMs?: number }): DriverFactory {
|
|
@@ -110,10 +191,11 @@ export class CacheStoreManager {
|
|
|
110
191
|
const existing = this.#built.get(store);
|
|
111
192
|
if (existing) return existing;
|
|
112
193
|
|
|
113
|
-
const
|
|
114
|
-
if (!
|
|
194
|
+
const declared = this.#config.stores[store];
|
|
195
|
+
if (!declared) {
|
|
115
196
|
throw new Error(`Echo: unknown cache store "${store}"`);
|
|
116
197
|
}
|
|
198
|
+
const cfg = entryOf(declared);
|
|
117
199
|
const manager = new CacheManager(cfg.driver(), {
|
|
118
200
|
prefix: cfg.prefix,
|
|
119
201
|
ttl: cfg.ttl,
|
package/src/configure.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ream configure @c9up/echo` — wire the cache in one command.
|
|
3
|
+
*
|
|
4
|
+
* The provider alone is not enough: it reads `config/cache.ts`, and a package
|
|
5
|
+
* registered without one falls back to a default that is rarely the one an
|
|
6
|
+
* application wants. Writing both together is what makes `ream add` mean
|
|
7
|
+
* installed AND working.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
interface Codemods {
|
|
11
|
+
addProvider(importPath: string): Promise<void>;
|
|
12
|
+
addEnvVars(vars: Record<string, string>): Promise<void>;
|
|
13
|
+
writeFile(
|
|
14
|
+
filePath: string,
|
|
15
|
+
content: string,
|
|
16
|
+
options?: { force?: boolean },
|
|
17
|
+
): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function configure(codemods: Codemods): Promise<void> {
|
|
21
|
+
// The config below reads these, so they are declared here. Writing the file
|
|
22
|
+
// without them leaves an application whose config asks the environment for
|
|
23
|
+
// something nothing ever put there.
|
|
24
|
+
await codemods.addEnvVars({
|
|
25
|
+
CACHE_STORE: "memory",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
await codemods.addProvider("@c9up/echo/provider");
|
|
29
|
+
await codemods.writeFile(
|
|
30
|
+
"config/cache.ts",
|
|
31
|
+
`import { defineConfig, drivers, store } from '@c9up/echo'
|
|
32
|
+
import env from '#start/env'
|
|
33
|
+
|
|
34
|
+
export default defineConfig({
|
|
35
|
+
default: env.get('CACHE_STORE', 'memory'),
|
|
36
|
+
|
|
37
|
+
stores: {
|
|
38
|
+
// One layer, in this process.
|
|
39
|
+
memory: store().useL1Layer(drivers.memory({ maxItems: 1000 })),
|
|
40
|
+
|
|
41
|
+
// Two layers: memory in front of Redis, with a bus so every instance
|
|
42
|
+
// drops its own L1 entry when another writes.
|
|
43
|
+
tiered: store()
|
|
44
|
+
.useL1Layer(drivers.memory({ maxItems: 1000 }))
|
|
45
|
+
.useL2Layer(drivers.redis({ connection: 'main' }))
|
|
46
|
+
.useBus(drivers.redisBus({ connection: 'main' })),
|
|
47
|
+
},
|
|
48
|
+
})`,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
@@ -80,10 +80,34 @@ export class TieredDriver implements TaggableDriver {
|
|
|
80
80
|
this.#bus?.subscribe((message) => {
|
|
81
81
|
// Peer invalidation: only the local L1 needs clearing (L2 is shared).
|
|
82
82
|
if (message.type === "clear") {
|
|
83
|
-
|
|
83
|
+
this.#invalidate("flush", () => this.#l1.flush());
|
|
84
84
|
return;
|
|
85
85
|
}
|
|
86
|
-
for (const key of message.keys)
|
|
86
|
+
for (const key of message.keys) {
|
|
87
|
+
this.#invalidate(key, () => this.#l1.delete(key));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Apply one peer invalidation to L1, reporting rather than escaping.
|
|
94
|
+
*
|
|
95
|
+
* This runs inside a bus callback, so nobody awaits it: an L1 that rejects
|
|
96
|
+
* — a Redis L1 whose socket just dropped, a driver mid-shutdown — was an
|
|
97
|
+
* unhandled rejection, which on a default Node ends the process. A cache
|
|
98
|
+
* layer failing to forget a key must not do that.
|
|
99
|
+
*
|
|
100
|
+
* It is reported and not retried: the entry keeps its own TTL, so the worst
|
|
101
|
+
* case is one stale read window on this instance, and a retry loop against
|
|
102
|
+
* a driver that is already failing buys nothing.
|
|
103
|
+
*/
|
|
104
|
+
#invalidate(what: string, run: () => Promise<unknown>): void {
|
|
105
|
+
void (async () => run())().catch((error: unknown) => {
|
|
106
|
+
process.stderr.write(
|
|
107
|
+
`[echo] tiered L1 invalidation of '${what}' failed; the local copy may be stale until it expires: ${
|
|
108
|
+
error instanceof Error ? error.message : String(error)
|
|
109
|
+
}\n`,
|
|
110
|
+
);
|
|
87
111
|
});
|
|
88
112
|
}
|
|
89
113
|
|
package/src/index.ts
CHANGED
package/src/services/main.ts
CHANGED
|
@@ -25,6 +25,14 @@ export function getCache(): CacheManager | undefined {
|
|
|
25
25
|
return instance;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* @internal Release the singleton, so a shut-down application does not leave a
|
|
30
|
+
* disconnected cache reachable through `services/main`.
|
|
31
|
+
*/
|
|
32
|
+
export function clearCache(): void {
|
|
33
|
+
instance = undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
28
36
|
const cache: CacheManager = new Proxy({} as CacheManager, {
|
|
29
37
|
get(_target, prop) {
|
|
30
38
|
// A module loader inspects what it imports before anyone uses it: it reads
|