Skip to content

Commit 8577148

Browse files
committedJan 30, 2025·
Done?
1 parent d69e267 commit 8577148

16 files changed

+390
-237
lines changed
 

‎.github/workflows/npm-publish.yml

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
on: push
2+
3+
jobs:
4+
test:
5+
runs-on: ubuntu-latest
6+
7+
strategy:
8+
matrix:
9+
node-version: [20.x, 22.x]
10+
11+
services:
12+
redis:
13+
image: redis
14+
# Set health checks to wait until redis has started
15+
options: >-
16+
--health-cmd "redis-cli ping"
17+
--health-interval 10s
18+
--health-timeout 5s
19+
--health-retries 5
20+
ports:
21+
- 6379:6379
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: actions/setup-node@v4
26+
with:
27+
node-version: ${{ matrix.node-version }}
28+
- run: npm ci
29+
- run: npm test
30+
31+
lint:
32+
runs-on: ubuntu-latest
33+
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: actions/setup-node@v4
37+
with:
38+
node-version: 20
39+
- run: npm ci
40+
- run: npm lint
41+
- run: ./scripts/example-check.sh
42+
43+
# publish:
44+
# needs: ["test", "lint"]
45+
# runs-on: ubuntu-latest
46+
47+
# steps:
48+
# - uses: actions/checkout@v4
49+
# - uses: actions/setup-node@v4
50+
# with:
51+
# node-version: 20
52+
# - run: npm ci
53+
# - uses: JS-DevTools/npm-publish@v1
54+
# with:
55+
# token: ${{ secrets.NPM_TOKEN }}

‎README.md

+28-39
Original file line numberDiff line numberDiff line change
@@ -4,67 +4,56 @@
44

55
### Basic usage
66

7-
For the most common cases you a simple 2 layer LRU + Redis cache is sufficient.
7+
For the most common cases use a simple 2 layer LRU + Redis cache is sufficient.
88

9-
```typescript
10-
import { CompositeCache, RedisCache LruCache } from '@loke/cache-kit';
9+
```ts
10+
import { Cache, LruMemoryCacheStore, RedisCacheStore } from "@loke/cache-kit";
1111
import Redis from "ioredis";
1212
import { create as createLogger } from "@loke/logger";
1313

14-
1514
const logger = createLogger();
16-
const redisClient = new Redis(process.env.REDIS_HOST);
17-
18-
19-
const cache = new CompositeCache(
20-
"users:{userId}"
21-
// Caches will be checked in order, and the first cache to return a value
22-
// will be used
23-
[
24-
new LruCache({ max: 1000 }),
25-
new RedisCache(redisClient, "tidy-api"),
26-
],
27-
logger
15+
const redisClient = new Redis();
16+
17+
const cache = new Cache(
18+
"users:{userId}",
19+
// Caches will be checked in order, and the first cache to return a value
20+
// will be used
21+
[new LruMemoryCacheStore({ max: 1000 }), new RedisCacheStore(redisClient)],
22+
logger,
2823
);
2924

30-
3125
const userId = 123;
3226

33-
const user = cache.apply(
34-
{ userId },
35-
async () => {
36-
// This function will only be called if the cache is empty
37-
const value = await fetchUser(userId);
38-
39-
// the ttl is returned as part of the result so it can vary per request
40-
return {
41-
value,
42-
ttl: 60 * 60 * 1000, // 1 hour in milliseconds
43-
};
44-
}
45-
);
27+
const user = cache.apply({ userId }, async () => {
28+
// This function will only be called if the cache is empty
29+
const value = await fetch(`http://example.com/user/${userId}`);
30+
31+
// the ttl is returned as part of the result so it can vary per request
32+
return {
33+
value,
34+
ttl: 60 * 60 * 1000, // 1 hour in milliseconds
35+
};
36+
});
4637
```
4738

4839
### Single flight cache
4940

5041
In cases where you don't want the overhead of storing the value in a cache, you
51-
can use a single flight cache. Concurrent requests will piggyback on the result
52-
of the first request.
42+
can use the cache for single flighting requests. Concurrent requests will
43+
piggyback on the result of the first request.
5344

54-
```typescript
55-
import { CompositeCache } from '@loke/cache-kit';
45+
```ts
46+
import { Cache } from "@loke/cache-kit";
5647
import { create as createLogger } from "@loke/logger";
5748

58-
5949
const logger = createLogger();
6050

61-
62-
const cache = new CompositeCache(
63-
"users:{userId}"
51+
const cache = new Cache(
52+
"users:{userId}",
6453
// An empty list of caches will result in a single flight only cache, where
6554
// the value is only cached for the duration of the request
6655
[],
67-
logger
56+
logger,
6857
);
6958
```
7059

‎package-lock.json

+24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
"scripts": {
1818
"test": "tsx --test",
1919
"lint": "eslint . && prettier --check .",
20-
"build": "pkgroll --sourcemap"
20+
"build": "pkgroll --sourcemap",
21+
"prepare": "npm run build"
2122
},
2223
"author": "",
2324
"license": "ISC",
2425
"description": "",
2526
"devDependencies": {
2627
"@eslint/js": "^9.18.0",
28+
"@loke/logger": "^3.4.0",
2729
"@tsconfig/node20": "^20.1.4",
2830
"@types/node": "^22.10.8",
2931
"eslint": "^9.18.0",

‎scripts/example-check.sh

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
# Extracts code blocks from README.md and checks them with TypeScript compiler
4+
5+
awk '/^```/{
6+
if (p) {
7+
p=0;
8+
close(file)
9+
} else {
10+
p=1;
11+
count++;
12+
lang=$0;
13+
sub(/^```/, "", lang);
14+
if (lang == "") lang="txt";
15+
file=sprintf("readme_example_%d.%s", count, lang)
16+
next
17+
}
18+
}
19+
p{print > file}' README.md
20+
21+
echo "Checking typescript examples"
22+
npx tsc --noEmit --module node16 readme_example_*.ts
23+
24+
rm readme_example_*

‎src/composite.test.ts ‎src/cache.test.ts

+14-13
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import test from "node:test";
22
import crypto from "crypto";
33
import Redis from "ioredis";
44
import assert from "assert/strict";
5+
import { nullLogger } from "@loke/logger";
56

6-
import { CompositeCache, LruMemoryCache, RedisCache } from ".";
7+
import { Cache, LruMemoryCacheStore, RedisCacheStore } from ".";
78

89
const randomId = () => crypto.randomBytes(16).toString("hex");
910

@@ -15,10 +16,10 @@ test("apply - should be able to apply caching to a function", async (t) => {
1516
const redisClient = new Redis(REDIS_HOST);
1617
t.after(() => redisClient.quit());
1718

18-
const cache = new CompositeCache(
19+
const cache = new Cache(
1920
"test:{id}",
20-
[new LruMemoryCache({ max: 10 }), new RedisCache(redisClient)],
21-
console,
21+
[new LruMemoryCacheStore({ max: 10 }), new RedisCacheStore(redisClient)],
22+
nullLogger,
2223
);
2324

2425
let callCount = 0;
@@ -40,10 +41,10 @@ test("apply - number keys should be valid", async (t) => {
4041
const redisClient = new Redis(REDIS_HOST);
4142
t.after(() => redisClient.quit());
4243

43-
const cache = new CompositeCache(
44+
const cache = new Cache(
4445
"test-number:{id}",
45-
[new LruMemoryCache({ max: 10 }), new RedisCache(redisClient)],
46-
console,
46+
[new LruMemoryCacheStore({ max: 10 }), new RedisCacheStore(redisClient)],
47+
nullLogger,
4748
);
4849

4950
let callCount = 0;
@@ -67,10 +68,10 @@ test("apply - should only need to call service once in parallel (single flight)"
6768
const redisClient = new Redis(REDIS_HOST);
6869
t.after(() => redisClient.quit());
6970

70-
const cache = new CompositeCache(
71+
const cache = new Cache(
7172
"test:{id}",
72-
[new LruMemoryCache({ max: 10 }), new RedisCache(redisClient)],
73-
console,
73+
[new LruMemoryCacheStore({ max: 10 }), new RedisCacheStore(redisClient)],
74+
nullLogger,
7475
);
7576

7677
let resolveAllApplied: (_: unknown) => void;
@@ -110,10 +111,10 @@ test("apply - should pass through errors", async (t) => {
110111
const redisClient = new Redis(REDIS_HOST);
111112
t.after(() => redisClient.quit());
112113

113-
const cache = new CompositeCache(
114+
const cache = new Cache(
114115
"test:{id}",
115-
[new LruMemoryCache({ max: 10 }), new RedisCache(redisClient)],
116-
console,
116+
[new LruMemoryCacheStore({ max: 10 }), new RedisCacheStore(redisClient)],
117+
nullLogger,
117118
);
118119

119120
const errToThrow = new Error("test error");

0 commit comments

Comments
 (0)
Please sign in to comment.