@devindex/api-kit 0.3.0 → 0.3.1
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 +64 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -9,8 +9,8 @@ driver from the environment.
|
|
|
9
9
|
npm install @devindex/api-kit
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
Node `>=22`. The memory drivers need no external service.
|
|
13
|
-
only on first use:
|
|
12
|
+
Node `>=22`. The memory drivers need no external service. The Redis-backed drivers load their
|
|
13
|
+
optional peers only on first use:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
npm install bullmq ioredis
|
|
@@ -474,6 +474,68 @@ Every Redis replica upserts the same scheduler and starts an equivalent Worker.
|
|
|
474
474
|
leader; BullMQ coordinates which Worker receives each occurrence. A new occurrence is produced when
|
|
475
475
|
the previous one starts, so global concurrency serializes slow runs rather than overlapping them.
|
|
476
476
|
|
|
477
|
+
## `./cache`
|
|
478
|
+
|
|
479
|
+
Key/value cache with one contract over two stores:
|
|
480
|
+
|
|
481
|
+
```js
|
|
482
|
+
import { createCache } from '@devindex/api-kit/cache';
|
|
483
|
+
|
|
484
|
+
const cache = createCache({
|
|
485
|
+
driver: 'redis',
|
|
486
|
+
redisUrl,
|
|
487
|
+
prefix: 'billing',
|
|
488
|
+
ttl: 300_000,
|
|
489
|
+
logger,
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
await cache.start();
|
|
493
|
+
|
|
494
|
+
const plan = await cache.wrap(`plan:${planId}`, () => plans.findById(planId));
|
|
495
|
+
|
|
496
|
+
await cache.set(`quote:${userId}`, quote, { ttl: 60_000 });
|
|
497
|
+
const quote = await cache.get(`quote:${userId}`);
|
|
498
|
+
const known = await cache.has(`quote:${userId}`);
|
|
499
|
+
|
|
500
|
+
await plans.update(planId, changes);
|
|
501
|
+
await cache.delete(`plan:${planId}`);
|
|
502
|
+
|
|
503
|
+
await cache.stop();
|
|
504
|
+
```
|
|
505
|
+
|
|
506
|
+
Every key is namespaced by `prefix`, so `plan:42` is stored as `billing:plan:42`. `ttl` is in
|
|
507
|
+
milliseconds and `0` never expires; the cache default is overridable on each write.
|
|
508
|
+
|
|
509
|
+
Values must be JSON-serializable. `undefined` reports a miss and is never stored — writing it
|
|
510
|
+
throws — while `null` is a value like any other, so `get()` returns `null` and `has()` returns
|
|
511
|
+
`true` for it. Both drivers keep the serialized form, so the object the memory driver returns can
|
|
512
|
+
be mutated without corrupting what is cached.
|
|
513
|
+
|
|
514
|
+
`wrap()` returns the cached value or runs the loader once, stores the result and returns it; a
|
|
515
|
+
loader that resolves `undefined` is not cached. Concurrent misses on the same key run one loader
|
|
516
|
+
each — the cache does not collapse them.
|
|
517
|
+
|
|
518
|
+
### Failures
|
|
519
|
+
|
|
520
|
+
A cache read or write is an optimization and never fails a request: with the store unreachable,
|
|
521
|
+
`get()` and `has()` report a miss and `set()` logs a warning, so the caller falls back to its
|
|
522
|
+
source. `delete()` is the exception and rejects. An invalidation that did not happen keeps serving
|
|
523
|
+
stale data until the TTL expires, which only the caller can weigh — `.catch(() => {})` says so
|
|
524
|
+
explicitly.
|
|
525
|
+
|
|
526
|
+
### Driver guarantees
|
|
527
|
+
|
|
528
|
+
| | `memory` | `redis` |
|
|
529
|
+
|---|---|---|
|
|
530
|
+
| External service | None | Redis |
|
|
531
|
+
| Scope | One private cache per replica | One cache shared by every replica |
|
|
532
|
+
| Survives restart | No | Yes |
|
|
533
|
+
| Expiration | On read | Owned by Redis |
|
|
534
|
+
| Size bound | None | Redis eviction policy |
|
|
535
|
+
|
|
536
|
+
The memory driver frees an entry only when it is read after expiring, so a key written and never
|
|
537
|
+
read again occupies memory until `stop()`. Keep it for development, tests and small derived values.
|
|
538
|
+
|
|
477
539
|
## `./env`
|
|
478
540
|
|
|
479
541
|
`createEnvReader()` reads `process.env` and **collects** what is wrong instead of failing on the
|