@wfp99/async-lru-cache 1.1.1 โ 1.2.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/README.md +78 -212
- package/README.zh-TW.md +76 -211
- package/dist/index.d.ts +70 -2
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +66 -14
- package/dist/index.js.map +1 -0
- package/package.json +13 -4
package/README.md
CHANGED
|
@@ -4,29 +4,17 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
|
-
An
|
|
7
|
+
An in-memory LRU (Least Recently Used) cache for Node.js and TypeScript, with support for asynchronous loading, saving, and automatic deduplication of concurrent requests.
|
|
8
8
|
|
|
9
9
|
## Features
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
## Why Choose In-Memory Over External Cache Services?
|
|
20
|
-
|
|
21
|
-
**Simplicity & Performance**
|
|
22
|
-
- No setup required - install and use immediately
|
|
23
|
-
- Zero network latency - direct memory access
|
|
24
|
-
- Reduced infrastructure complexity
|
|
25
|
-
|
|
26
|
-
**Reliability & Development**
|
|
27
|
-
- No external dependencies or network failures
|
|
28
|
-
- Simplified testing and debugging
|
|
29
|
-
- Works without Redis, Memcached, or other cache servers
|
|
11
|
+
- Asynchronous loader (`get`) and saver (`put`) functions
|
|
12
|
+
- Concurrent `get()` calls for the same key share a single loader execution
|
|
13
|
+
- `put()` calls for the same key are serialized and execute in order
|
|
14
|
+
- LRU eviction once the configured capacity is exceeded
|
|
15
|
+
- Optional per-entry TTL (time to live), with optional periodic background cleanup
|
|
16
|
+
- Configurable error handling via `onError`, defaulting to console logging
|
|
17
|
+
- `get()` can be called without a loader for a read-only lookup, and `peek()` for a lookup that never affects LRU order
|
|
30
18
|
|
|
31
19
|
## Installation
|
|
32
20
|
|
|
@@ -40,241 +28,122 @@ npm install @wfp99/async-lru-cache
|
|
|
40
28
|
|
|
41
29
|
## Usage
|
|
42
30
|
|
|
43
|
-
### Basic
|
|
31
|
+
### Basic usage
|
|
44
32
|
|
|
45
33
|
```typescript
|
|
46
34
|
import { AsyncLRUCache } from '@wfp99/async-lru-cache';
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
const cache = new AsyncLRUCache({
|
|
50
|
-
capacity: 100
|
|
51
|
-
});
|
|
36
|
+
const cache = new AsyncLRUCache<string, User>({ capacity: 100 });
|
|
52
37
|
|
|
53
|
-
//
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return response.json();
|
|
38
|
+
// get() calls the loader on a cache miss and caches the resolved value.
|
|
39
|
+
const user = await cache.get('user:123', async () => {
|
|
40
|
+
const response = await fetch('/api/users/123');
|
|
41
|
+
return response.json();
|
|
58
42
|
});
|
|
59
43
|
|
|
60
|
-
//
|
|
44
|
+
// put() stores a value directly and optionally persists it via a saver.
|
|
61
45
|
await cache.put('user:456', userData, async (key, value) => {
|
|
62
|
-
|
|
63
|
-
await saveToDatabase(key, value);
|
|
46
|
+
await saveToDatabase(key, value);
|
|
64
47
|
});
|
|
65
48
|
```
|
|
66
49
|
|
|
67
|
-
###
|
|
50
|
+
### Read-only lookups
|
|
68
51
|
|
|
69
52
|
```typescript
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error('Cache load failed:', error);
|
|
76
|
-
// Failed items are automatically removed from cache
|
|
77
|
-
}
|
|
78
|
-
```
|
|
53
|
+
// get() without a loader performs a read-only lookup: on a hit it behaves like a
|
|
54
|
+
// normal get() (and updates LRU order); on a miss it resolves to undefined without
|
|
55
|
+
// adding anything to the cache or affecting LRU order.
|
|
56
|
+
const cached = await cache.get('user:123'); // User | undefined
|
|
79
57
|
|
|
80
|
-
|
|
58
|
+
// peek() never affects LRU order, whether it is a hit or a miss.
|
|
59
|
+
const peeked = await cache.peek('user:123'); // Promise<User> | undefined
|
|
60
|
+
```
|
|
81
61
|
|
|
82
|
-
|
|
62
|
+
### TTL (time to live)
|
|
83
63
|
|
|
84
64
|
```typescript
|
|
85
|
-
import { AsyncLRUCache } from '@wfp99/async-lru-cache';
|
|
86
|
-
|
|
87
|
-
// Create cache with TTL support
|
|
88
65
|
const cache = new AsyncLRUCache({
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
66
|
+
capacity: 100,
|
|
67
|
+
defaultTtlMs: 5000, // default TTL applied to every entry
|
|
68
|
+
cleanupIntervalMs: 10000, // periodic background cleanup of expired entries
|
|
92
69
|
});
|
|
93
70
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
return await fetchData();
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Override TTL for specific entries
|
|
100
|
-
const data2 = await cache.get('key2', async () => {
|
|
101
|
-
return await fetchCriticalData();
|
|
102
|
-
}, 30000); // 30 seconds TTL
|
|
103
|
-
|
|
104
|
-
// Put with custom TTL
|
|
105
|
-
await cache.put('key3', value, async (key, val) => {
|
|
106
|
-
await saveToDb(key, val);
|
|
107
|
-
}, 60000); // 1 minute TTL
|
|
108
|
-
|
|
109
|
-
// Manual cleanup of expired entries
|
|
110
|
-
cache.cleanupExpired();
|
|
111
|
-
|
|
112
|
-
// Check if key exists and is not expired
|
|
113
|
-
if (cache.has('key1')) {
|
|
114
|
-
console.log('Key exists and is valid');
|
|
115
|
-
}
|
|
71
|
+
// Override the default TTL for a specific entry.
|
|
72
|
+
await cache.get('key1', async () => fetchData(), 30000);
|
|
116
73
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
// Destroy cache (stops cleanup timer and clears all data)
|
|
121
|
-
cache.destroy();
|
|
74
|
+
cache.has('key1'); // false once the entry has expired
|
|
75
|
+
cache.cleanupExpired(); // manually remove expired entries
|
|
76
|
+
cache.destroy(); // stop the cleanup timer and clear all data
|
|
122
77
|
```
|
|
123
78
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
- **`defaultTtlMs`**: Default TTL for all cache entries (optional)
|
|
127
|
-
- **`cleanupIntervalMs`**: Automatic cleanup interval for expired entries (optional)
|
|
128
|
-
- Individual `get()` and `put()` methods accept TTL overrides
|
|
129
|
-
- Expired entries are automatically removed during normal operations
|
|
130
|
-
- Call `cleanupExpired()` for manual cleanup
|
|
131
|
-
- Call `destroy()` to stop timers and prevent memory leaks
|
|
132
|
-
|
|
133
|
-
### Advanced Usage
|
|
79
|
+
### Concurrency handling
|
|
134
80
|
|
|
135
81
|
```typescript
|
|
136
|
-
//
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
82
|
+
// These concurrent get() calls share a single loader execution.
|
|
83
|
+
const [a, b, c] = await Promise.all([
|
|
84
|
+
cache.get('shared-key', loader),
|
|
85
|
+
cache.get('shared-key', loader),
|
|
86
|
+
cache.get('shared-key', loader),
|
|
87
|
+
]);
|
|
143
88
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
89
|
+
// These put() calls execute sequentially, even though they are started concurrently.
|
|
90
|
+
cache.put('key', 'value1', saver1);
|
|
91
|
+
cache.put('key', 'value2', saver2);
|
|
92
|
+
cache.put('key', 'value3', saver3);
|
|
148
93
|
```
|
|
149
94
|
|
|
150
|
-
###
|
|
95
|
+
### Error handling
|
|
151
96
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
97
|
+
- If a loader (`get`) throws, the entry is removed from the cache and the rejection propagates to the caller.
|
|
98
|
+
- If a saver (`put`) throws, the entry is also removed to avoid caching an unpersisted value.
|
|
99
|
+
- A `put()` call ignores the failure of a previous, already-settled operation on the same key, so it can still proceed.
|
|
100
|
+
- By default, these failures are logged with `console.error`/`console.warn`. Provide `onError` to handle them yourself instead:
|
|
155
101
|
|
|
156
|
-
|
|
157
|
-
cache
|
|
102
|
+
```typescript
|
|
103
|
+
const cache = new AsyncLRUCache({
|
|
104
|
+
capacity: 100,
|
|
105
|
+
onError(error, { key, source }) {
|
|
106
|
+
// source is 'loader' | 'saver' | 'put-chain'
|
|
107
|
+
myLogger.error(`cache ${source} failed for ${key}`, error);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
158
110
|
```
|
|
159
111
|
|
|
160
112
|
## API Reference
|
|
161
113
|
|
|
162
114
|
### `AsyncLRUCache<K, V>`
|
|
163
115
|
|
|
164
|
-
#### Constructor
|
|
165
|
-
|
|
166
116
|
```typescript
|
|
167
|
-
constructor(option: AsyncLRUCacheOption)
|
|
117
|
+
constructor(option: AsyncLRUCacheOption<K>)
|
|
168
118
|
```
|
|
169
119
|
|
|
170
|
-
#### `AsyncLRUCacheOption
|
|
120
|
+
#### `AsyncLRUCacheOption<K>`
|
|
171
121
|
|
|
172
122
|
| Property | Type | Required | Description |
|
|
173
|
-
|
|
174
|
-
| `capacity` | `number` | Yes | Maximum number of items allowed in cache. Must be
|
|
175
|
-
| `defaultTtlMs` | `number` | No | Default TTL
|
|
176
|
-
| `cleanupIntervalMs` | `number` | No |
|
|
123
|
+
|---|---|---|---|
|
|
124
|
+
| `capacity` | `number` | Yes | Maximum number of items allowed in the cache. Must be at least 10. |
|
|
125
|
+
| `defaultTtlMs` | `number` | No | Default TTL applied to entries that don't specify their own. |
|
|
126
|
+
| `cleanupIntervalMs` | `number` | No | Interval for automatic background cleanup of expired entries. |
|
|
127
|
+
| `onError` | `(error: unknown, context: { key: K; source: 'loader' \| 'saver' \| 'put-chain' }) => void` | No | Callback for loader/saver failures. Replaces the default console logging when provided. |
|
|
177
128
|
|
|
178
129
|
#### Methods
|
|
179
130
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- **key**: Cache key
|
|
194
|
-
- **value**: Value to cache
|
|
195
|
-
- **saver**: Optional asynchronous saver function
|
|
196
|
-
- **ttlMs**: Optional TTL override for this entry
|
|
197
|
-
- **Returns**: Promise that resolves to the latest value after saver operation completes
|
|
198
|
-
|
|
199
|
-
##### `invalidate(key: K): void`
|
|
131
|
+
| Method | Description |
|
|
132
|
+
|---|---|
|
|
133
|
+
| `get(key, loader, ttlMs?)` | Returns the cached value, or calls `loader()` on a miss and caches the result. |
|
|
134
|
+
| `get(key)` | Read-only lookup without a loader. On a hit, behaves like the overload above (updates LRU order). On a miss, resolves to `undefined` without touching the cache. |
|
|
135
|
+
| `peek(key)` | Returns the cached value's `Promise<V>`, or `undefined` if missing/expired. Never affects LRU order, even on a hit. |
|
|
136
|
+
| `put(key, value, saver?, ttlMs?)` | Stores `value` and optionally awaits `saver(key, value)` to persist it. |
|
|
137
|
+
| `invalidate(key)` | Removes the entry for `key`, if present. |
|
|
138
|
+
| `clear()` | Removes all entries. |
|
|
139
|
+
| `has(key)` | Returns whether `key` exists and has not expired. Expired entries are evicted as a side effect of this check; it does not affect LRU order. |
|
|
140
|
+
| `size()` | Returns the current number of entries. |
|
|
141
|
+
| `cleanupExpired()` | Immediately removes all expired entries. |
|
|
142
|
+
| `destroy()` | Stops the cleanup timer (if any) and clears all data. |
|
|
200
143
|
|
|
201
|
-
|
|
144
|
+
## TypeScript
|
|
202
145
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
##### `clear(): void`
|
|
206
|
-
|
|
207
|
-
Clears all cache entries. This method removes all items from cache and manually clears node links to prevent potential memory leaks.
|
|
208
|
-
|
|
209
|
-
##### `has(key: K): boolean`
|
|
210
|
-
|
|
211
|
-
Checks if a key exists in cache and is not expired.
|
|
212
|
-
|
|
213
|
-
- **key**: Cache key to check
|
|
214
|
-
- **Returns**: True if key exists and is valid
|
|
215
|
-
|
|
216
|
-
##### `size(): number`
|
|
217
|
-
|
|
218
|
-
Returns the current number of items in cache.
|
|
219
|
-
|
|
220
|
-
- **Returns**: Number of cached items
|
|
221
|
-
|
|
222
|
-
##### `cleanupExpired(): void`
|
|
223
|
-
|
|
224
|
-
Manually removes expired entries from cache.
|
|
225
|
-
|
|
226
|
-
##### `destroy(): void`
|
|
227
|
-
|
|
228
|
-
Destroys the cache, stops cleanup timers and clears all data.
|
|
229
|
-
|
|
230
|
-
## Concurrency Handling
|
|
231
|
-
|
|
232
|
-
AsyncLRUCache automatically handles concurrent operations:
|
|
233
|
-
|
|
234
|
-
- **GET Request Merging**: Multiple concurrent requests for the same key share a single loader execution
|
|
235
|
-
- **PUT Operation Serialization**: Multiple PUT operations for the same key are serialized to ensure they execute in order
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
// These three concurrent requests will share the same loader execution
|
|
239
|
-
const [data1, data2, data3] = await Promise.all([
|
|
240
|
-
cache.get('shared-key', loader),
|
|
241
|
-
cache.get('shared-key', loader),
|
|
242
|
-
cache.get('shared-key', loader)
|
|
243
|
-
]);
|
|
244
|
-
|
|
245
|
-
// These operations will execute sequentially, even if started concurrently
|
|
246
|
-
cache.put('key', 'value1', saver1);
|
|
247
|
-
cache.put('key', 'value2', saver2);
|
|
248
|
-
cache.put('key', 'value3', saver3);
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## TypeScript Support
|
|
252
|
-
|
|
253
|
-
This package is fully written in TypeScript and provides complete type support:
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
interface User {
|
|
257
|
-
id: string;
|
|
258
|
-
name: string;
|
|
259
|
-
email: string;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const userCache = new AsyncLRUCache<string, User>({
|
|
263
|
-
capacity: 1000
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const user: User = await userCache.get('user:123', async () => {
|
|
267
|
-
// Loader must return User type
|
|
268
|
-
return fetchUserFromAPI('123');
|
|
269
|
-
});
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## Error Handling
|
|
273
|
-
|
|
274
|
-
- **Loader Failures**: If loader function throws an exception, corresponding cache entry is automatically removed
|
|
275
|
-
- **Saver Failures**: If saver function fails, cache entry is also removed to ensure data consistency
|
|
276
|
-
- **Operation Chain Errors**: PUT operations ignore previous operation errors, allowing new operations to proceed
|
|
277
|
-
- **Error Logging**: All errors are automatically logged to console for debugging
|
|
146
|
+
This package is written in TypeScript and ships with type declarations; no separate `@types` package is required.
|
|
278
147
|
|
|
279
148
|
## License
|
|
280
149
|
|
|
@@ -284,6 +153,3 @@ MIT
|
|
|
284
153
|
|
|
285
154
|
Issues and pull requests are welcome on [GitHub](https://github.com/wfp99/async-lru-cache).
|
|
286
155
|
|
|
287
|
-
## Author
|
|
288
|
-
|
|
289
|
-
Wang Feng Ping
|
package/README.zh-TW.md
CHANGED
|
@@ -4,29 +4,17 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
ไธๅๆฏๆด้ๅๆญฅ่ผๅ
ฅ่ไฟๅญๆไฝใไธฆ่ชๅ่็ไธฆ็ผ่ซๆฑ็ LRU๏ผLeast Recently Used๏ผ่จๆถ้ซๅฟซๅ๏ผ้ฉ็จๆผ Node.js ่ TypeScriptใ
|
|
8
8
|
|
|
9
9
|
## ็น่ฒ
|
|
10
10
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
## ็บไป้บผ้ธๆ่จๆถ้ซๅ
งๅฟซๅ่้ๅค้จๅฟซๅๆๅ๏ผ
|
|
20
|
-
|
|
21
|
-
**็ฐกๅฎๆง่ๆ่ฝ**
|
|
22
|
-
- ็ก้่จญๅฎ - ๅฎ่ฃๅพ็ซๅณไฝฟ็จ
|
|
23
|
-
- ้ถ็ถฒ่ทฏๅปถ้ฒ - ็ดๆฅ่จๆถ้ซๅญๅ
|
|
24
|
-
- ๆธๅฐๅบ็คๆถๆง่ค้ๆง
|
|
25
|
-
|
|
26
|
-
**ๅฏ้ ๆง่้็ผ**
|
|
27
|
-
- ็กๅค้จไพ่ณดๆ็ถฒ่ทฏๆ
้้ขจ้ช
|
|
28
|
-
- ็ฐกๅๆธฌ่ฉฆๅ้ค้ฏ
|
|
29
|
-
- ็ก้ RedisใMemcached ๆๅ
ถไปๅฟซๅไผบๆๅจ
|
|
11
|
+
- ๆฏๆด้ๅๆญฅ็่ผๅ
ฅๅจ๏ผloader๏ผ่ไฟๅญๅจ๏ผsaver๏ผๅฝๆธ
|
|
12
|
+
- ๅฐๅไธ key ็ไธฆ็ผ `get()` ๅผๅซๅ
ฑ็จๅฎไธ่ผๅ
ฅๅจๅท่ก
|
|
13
|
+
- ๅฐๅไธ key ็ๅคๅ `put()` ๅผๅซๆๅบๅๅไธฆไพๅบๅท่ก
|
|
14
|
+
- ่ถ
ๅบ่จญๅฎๅฎน้ๆ่ชๅๅท่ก LRU ๆทๆฑฐ
|
|
15
|
+
- ๆฏๆดๆฏ็ญ้
็ฎ็ๅฏ้ธ TTL๏ผๅญๆดปๆ้๏ผ๏ผไธฆๅฏ่จญๅฎ้ฑๆๆง่ๆฏๆธ
็
|
|
16
|
+
- ๅฏ้้ `onError` ่ช่จ้ฏ่ชค่็๏ผ้ ่จญ็บ่จ้ๅฐ console
|
|
17
|
+
- `get()` ๅฏ็็ฅ loader ้ฒ่กๅฏ่ฎๆฅ่ฉข๏ผ`peek()` ๅๆไพๅฎๅ
จไธๅฝฑ้ฟ LRU ้ ๅบ็ๆฅ่ฉขๆนๅผ
|
|
30
18
|
|
|
31
19
|
## ๅฎ่ฃ
|
|
32
20
|
|
|
@@ -45,236 +33,116 @@ npm install @wfp99/async-lru-cache
|
|
|
45
33
|
```typescript
|
|
46
34
|
import { AsyncLRUCache } from '@wfp99/async-lru-cache';
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
const cache = new AsyncLRUCache({
|
|
50
|
-
capacity: 100
|
|
51
|
-
});
|
|
36
|
+
const cache = new AsyncLRUCache<string, User>({ capacity: 100 });
|
|
52
37
|
|
|
53
|
-
//
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return response.json();
|
|
38
|
+
// get() ๅจๅฟซๅๆชๅฝไธญๆๅผๅซ loader๏ผไธฆๅฟซๅๅ
ถๅๅณๅผใ
|
|
39
|
+
const user = await cache.get('user:123', async () => {
|
|
40
|
+
const response = await fetch('/api/users/123');
|
|
41
|
+
return response.json();
|
|
58
42
|
});
|
|
59
43
|
|
|
60
|
-
//
|
|
44
|
+
// put() ็ดๆฅๅฒๅญๅผ๏ผไธฆๅฏ้ธๆ้้ saver ้ฒ่กๆไน
ๅใ
|
|
61
45
|
await cache.put('user:456', userData, async (key, value) => {
|
|
62
|
-
|
|
63
|
-
await saveToDatabase(key, value);
|
|
46
|
+
await saveToDatabase(key, value);
|
|
64
47
|
});
|
|
65
48
|
```
|
|
66
49
|
|
|
67
|
-
###
|
|
50
|
+
### ๅฏ่ฎๆฅ่ฉข
|
|
68
51
|
|
|
69
52
|
```typescript
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error('ๅฟซๅ่ผๅ
ฅๅคฑๆ:', error);
|
|
76
|
-
// ๅคฑๆ็้
็ฎๆ่ชๅๅพๅฟซๅไธญ็งป้ค
|
|
77
|
-
}
|
|
78
|
-
```
|
|
53
|
+
// ็็ฅ loader ็ get() ๅฑฌๆผๅฏ่ฎๆฅ่ฉข๏ผๅฝไธญๆ่ก็บ่ไธ่ฌ get() ็ธๅ๏ผๆๆดๆฐ LRU ้ ๅบ๏ผ๏ผ
|
|
54
|
+
// ๆชๅฝไธญๆๅๅณ undefined๏ผไธไธๆๆฐๅขไปปไฝ้
็ฎๆๅฝฑ้ฟ LRU ้ ๅบใ
|
|
55
|
+
const cached = await cache.get('user:123'); // User | undefined
|
|
79
56
|
|
|
80
|
-
|
|
57
|
+
// peek() ็ก่ซๅฝไธญๆๆชๅฝไธญ้ฝไธๆๅฝฑ้ฟ LRU ้ ๅบใ
|
|
58
|
+
const peeked = await cache.peek('user:123'); // Promise<User> | undefined
|
|
59
|
+
```
|
|
81
60
|
|
|
82
|
-
|
|
61
|
+
### TTL๏ผๅญๆดปๆ้๏ผ
|
|
83
62
|
|
|
84
63
|
```typescript
|
|
85
|
-
import { AsyncLRUCache } from '@wfp99/async-lru-cache';
|
|
86
|
-
|
|
87
|
-
// ๅปบ็ซๆฏๆด TTL ็ๅฟซๅ
|
|
88
64
|
const cache = new AsyncLRUCache({
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// ไฝฟ็จ้ ่จญ TTL
|
|
95
|
-
const data1 = await cache.get('key1', async () => {
|
|
96
|
-
return await fetchData();
|
|
65
|
+
capacity: 100,
|
|
66
|
+
defaultTtlMs: 5000, // ๅฅ็จๅฐๆฏ็ญ้
็ฎ็้ ่จญ TTL
|
|
67
|
+
cleanupIntervalMs: 10000, // ้ฑๆๆง่ๆฏๆธ
็้ๆ้
็ฎ
|
|
97
68
|
});
|
|
98
69
|
|
|
99
|
-
//
|
|
100
|
-
|
|
101
|
-
return await fetchCriticalData();
|
|
102
|
-
}, 30000); // 30 ็ง TTL
|
|
103
|
-
|
|
104
|
-
// ไฝฟ็จ่ช่จ TTL ้ฒ่ก Put ๆไฝ
|
|
105
|
-
await cache.put('key3', value, async (key, val) => {
|
|
106
|
-
await saveToDb(key, val);
|
|
107
|
-
}, 60000); // 1 ๅ้ TTL
|
|
108
|
-
|
|
109
|
-
// ๆๅๆธ
็้ๆ้
็ฎ
|
|
110
|
-
cache.cleanupExpired();
|
|
70
|
+
// ็บ็นๅฎ้
็ฎ่ฆๅฏซ้ ่จญ TTLใ
|
|
71
|
+
await cache.get('key1', async () => fetchData(), 30000);
|
|
111
72
|
|
|
112
|
-
//
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ๅๅพๅฟซๅๅคงๅฐ
|
|
118
|
-
console.log('็ฎๅๅฟซๅๅคงๅฐ:', cache.size());
|
|
119
|
-
|
|
120
|
-
// ้ทๆฏๅฟซๅ๏ผๅๆญขๆธ
็่จๆๅจไธฆๆธ
้คๆๆ่ณๆ๏ผ
|
|
121
|
-
cache.destroy();
|
|
73
|
+
cache.has('key1'); // ้
็ฎ้ๆๅพๅๅณ false
|
|
74
|
+
cache.cleanupExpired(); // ๆๅ็งป้ค้ๆ้
็ฎ
|
|
75
|
+
cache.destroy(); // ๅๆญขๆธ
็่จๆๅจไธฆๆธ
้คๆๆ่ณๆ
|
|
122
76
|
```
|
|
123
77
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
- **`defaultTtlMs`**๏ผๆๆๅฟซๅ้
็ฎ็้ ่จญ TTL๏ผๅฏ้ธ๏ผ
|
|
127
|
-
- **`cleanupIntervalMs`**๏ผ้ๆ้
็ฎ็่ชๅๆธ
็้้๏ผๅฏ้ธ๏ผ
|
|
128
|
-
- ๅๅฅ็ `get()` ๅ `put()` ๆนๆณๆฅๅ TTL ่ฆๅฏซ
|
|
129
|
-
- ้ๆ้
็ฎๅจๆญฃๅธธๆไฝๆ้ๆ่ชๅ็งป้ค
|
|
130
|
-
- ๅผๅซ `cleanupExpired()` ้ฒ่กๆๅๆธ
็
|
|
131
|
-
- ๅผๅซ `destroy()` ๅๆญข่จๆๅจไธฆ้ฒๆญข่จๆถ้ซๆดฉๆผ
|
|
132
|
-
|
|
133
|
-
### ้ฒ้ไฝฟ็จ
|
|
78
|
+
### ไธฆ็ผ่็
|
|
134
79
|
|
|
135
80
|
```typescript
|
|
136
|
-
//
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
81
|
+
// ไปฅไธไธฆ็ผ็ get() ๅผๅซๆๅ
ฑ็จๅไธๅ loader ๅท่กใ
|
|
82
|
+
const [a, b, c] = await Promise.all([
|
|
83
|
+
cache.get('shared-key', loader),
|
|
84
|
+
cache.get('shared-key', loader),
|
|
85
|
+
cache.get('shared-key', loader),
|
|
86
|
+
]);
|
|
143
87
|
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
88
|
+
// ไปฅไธ put() ๅผๅซๅณไฝฟไธฆ็ผๅๅ๏ผไนๆไพๅบๅบๅๅๅท่กใ
|
|
89
|
+
cache.put('key', 'value1', saver1);
|
|
90
|
+
cache.put('key', 'value2', saver2);
|
|
91
|
+
cache.put('key', 'value3', saver3);
|
|
148
92
|
```
|
|
149
93
|
|
|
150
|
-
###
|
|
94
|
+
### ้ฏ่ชค่็
|
|
151
95
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
96
|
+
- ่ฅ่ผๅ
ฅๅจ๏ผ`get`๏ผๆๅบไพๅค๏ผ่ฉฒ้
็ฎๆๅพๅฟซๅไธญ็งป้ค๏ผ้ฏ่ชคๆๅณ้็ตฆๅผๅซ็ซฏใ
|
|
97
|
+
- ่ฅไฟๅญๅจ๏ผ`put`๏ผๆๅบไพๅค๏ผ่ฉฒ้
็ฎไนๆ่ขซ็งป้ค๏ผ้ฟๅ
ๅฟซๅๅฐๅฐๆชๆไน
ๅ็ๅผใ
|
|
98
|
+
- `put()` ๆๅฟฝ็ฅๅไธ key ๅไธๅๅทฒ็ตๆๆไฝ็ๅคฑๆ๏ผ่ฎๆฐ็ๆไฝๅฏไปฅ็นผ็บ้ฒ่กใ
|
|
99
|
+
- ้ ่จญๆ
ๆณไธ๏ผไธ่ฟฐๅคฑๆๆ้้ `console.error`/`console.warn` ่จ้ใ่ฅ่ฆ่ช่ก่็๏ผๅฏๆไพ `onError`๏ผ
|
|
155
100
|
|
|
156
|
-
|
|
157
|
-
cache
|
|
101
|
+
```typescript
|
|
102
|
+
const cache = new AsyncLRUCache({
|
|
103
|
+
capacity: 100,
|
|
104
|
+
onError(error, { key, source }) {
|
|
105
|
+
// source ็บ 'loader' | 'saver' | 'put-chain'
|
|
106
|
+
myLogger.error(`cache ${source} failed for ${key}`, error);
|
|
107
|
+
},
|
|
108
|
+
});
|
|
158
109
|
```
|
|
159
110
|
|
|
160
111
|
## API ๅ่
|
|
161
112
|
|
|
162
113
|
### `AsyncLRUCache<K, V>`
|
|
163
114
|
|
|
164
|
-
#### ๅปบๆงๅฝๆธ
|
|
165
|
-
|
|
166
115
|
```typescript
|
|
167
|
-
constructor(option: AsyncLRUCacheOption)
|
|
116
|
+
constructor(option: AsyncLRUCacheOption<K>)
|
|
168
117
|
```
|
|
169
118
|
|
|
170
|
-
#### `AsyncLRUCacheOption
|
|
119
|
+
#### `AsyncLRUCacheOption<K>`
|
|
171
120
|
|
|
172
121
|
| ๅฑฌๆง | ้กๅ | ๅฟ
้ | ๆ่ฟฐ |
|
|
173
|
-
|
|
174
|
-
| `capacity` | `number` | ๆฏ |
|
|
175
|
-
| `defaultTtlMs` | `number` | ๅฆ |
|
|
176
|
-
| `cleanupIntervalMs` | `number` | ๅฆ |
|
|
122
|
+
|---|---|---|---|
|
|
123
|
+
| `capacity` | `number` | ๆฏ | ๅฟซๅไธญๅ
่จฑ็ๆๅคง้
็ฎๆธ้๏ผๆๅฐๅผ็บ 10 |
|
|
124
|
+
| `defaultTtlMs` | `number` | ๅฆ | ๅฅ็จๅฐๆชๆๅฎ TTL ไน้
็ฎ็้ ่จญ TTL |
|
|
125
|
+
| `cleanupIntervalMs` | `number` | ๅฆ | ่ชๅ่ๆฏๆธ
็้ๆ้
็ฎ็ๅท่ก้้ |
|
|
126
|
+
| `onError` | `(error: unknown, context: { key: K; source: 'loader' \| 'saver' \| 'put-chain' }) => void` | ๅฆ | ่ผๅ
ฅๅจ/ไฟๅญๅจๅคฑๆๆ็ๅๅผๅฝๆธใๆไพๅพๅฐๅไปฃ้ ่จญ็ console ่จ้่ก็บ |
|
|
177
127
|
|
|
178
128
|
#### ๆนๆณ
|
|
179
129
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
- **key**: ๅฟซๅ้ต
|
|
194
|
-
- **value**: ่ฆๅฟซๅ็ๅผ
|
|
195
|
-
- **saver**: ๅฏ้ธ็้ๅๆญฅไฟๅญๅฝๆธ
|
|
196
|
-
- **ttlMs**: ๆญค้
็ฎ็ๅฏ้ธ TTL ่ฆๅฏซ
|
|
197
|
-
- **ๅๅณ**: Promise๏ผ่งฃๆ็บไฟๅญๆไฝๅฎๆๅพ็ๆๆฐๅผ
|
|
130
|
+
| ๆนๆณ | ๆ่ฟฐ |
|
|
131
|
+
|---|---|
|
|
132
|
+
| `get(key, loader, ttlMs?)` | ๅๅณๅฟซๅๅผ๏ผๆชๅฝไธญๆๅผๅซ `loader()` ไธฆๅฟซๅๅ
ถ็ตๆ |
|
|
133
|
+
| `get(key)` | ็็ฅ loader ็ๅฏ่ฎๆฅ่ฉขใๅฝไธญๆ่ก็บ่ไธๆนๅค่ผ็ธๅ๏ผๆๆดๆฐ LRU ้ ๅบ๏ผ๏ผๆชๅฝไธญๆๅๅณ `undefined`๏ผไธๆ็ฐๅๅฟซๅ |
|
|
134
|
+
| `peek(key)` | ๅๅณๅฟซๅๅผ็ `Promise<V>`๏ผ่ฅไธๅญๅจๆๅทฒ้ๆๅๅๅณ `undefined`ใ็ก่ซๅฝไธญ่ๅฆ้ฝไธๅฝฑ้ฟ LRU ้ ๅบ |
|
|
135
|
+
| `put(key, value, saver?, ttlMs?)` | ๅฒๅญ `value`๏ผไธฆๅฏ้ธๆ็ญๅพ
`saver(key, value)` ้ฒ่กๆไน
ๅ |
|
|
136
|
+
| `invalidate(key)` | ่ฅๅญๅจ๏ผ็งป้ค `key` ๅฐๆ็้
็ฎ |
|
|
137
|
+
| `clear()` | ็งป้คๆๆ้
็ฎ |
|
|
138
|
+
| `has(key)` | ๅๅณ `key` ๆฏๅฆๅญๅจไธๆช้ๆใๆญคๆชขๆฅๆ้ ๅธถๆธ
้คๅทฒ้ๆ็้
็ฎ๏ผไฝไธๅฝฑ้ฟ LRU ้ ๅบ |
|
|
139
|
+
| `size()` | ๅๅณ็ฎๅ็้
็ฎๆธ้ |
|
|
140
|
+
| `cleanupExpired()` | ็ซๅณ็งป้คๆๆ้ๆ้
็ฎ |
|
|
141
|
+
| `destroy()` | ๅๆญขๆธ
็่จๆๅจ๏ผ่ฅๆ๏ผไธฆๆธ
้คๆๆ่ณๆ |
|
|
198
142
|
|
|
199
|
-
|
|
143
|
+
## TypeScript
|
|
200
144
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- **key**: ่ฆๅคฑๆ็ๅฟซๅ้ต
|
|
204
|
-
|
|
205
|
-
##### `clear(): void`
|
|
206
|
-
|
|
207
|
-
ๆธ
้คๆๆๅฟซๅ้
็ฎใๆญคๆนๆณๆ็งป้คๅฟซๅไธญ็ๆๆ้
็ฎไธฆๆๅๆธ
็็ฏ้ป้ฃ็ตไปฅ้ฟๅ
ๆฝๅจ็่จๆถ้ซๆดฉๆผใ
|
|
208
|
-
|
|
209
|
-
##### `has(key: K): boolean`
|
|
210
|
-
|
|
211
|
-
ๆชขๆฅๅฟซๅไธญๆฏๅฆๅญๅจๆๅฎ้ตไธๆช้ๆใ
|
|
212
|
-
|
|
213
|
-
- **key**: ่ฆๆชขๆฅ็ๅฟซๅ้ต
|
|
214
|
-
- **ๅๅณ**: ๅฆๆ้ตๅญๅจไธๆๆๅๅๅณ true
|
|
215
|
-
|
|
216
|
-
##### `size(): number`
|
|
217
|
-
|
|
218
|
-
ๅๅณๅฟซๅไธญ็ฎๅ็้
็ฎๆธ้ใ
|
|
219
|
-
|
|
220
|
-
- **ๅๅณ**: ๅฟซๅ้
็ฎ็ๆธ้
|
|
221
|
-
|
|
222
|
-
##### `cleanupExpired(): void`
|
|
223
|
-
|
|
224
|
-
ๆๅๅพๅฟซๅไธญ็งป้ค้ๆ้
็ฎใ
|
|
225
|
-
|
|
226
|
-
##### `destroy(): void`
|
|
227
|
-
|
|
228
|
-
้ทๆฏๅฟซๅ๏ผๅๆญขๆธ
็่จๆๅจไธฆๆธ
้คๆๆ่ณๆใ
|
|
229
|
-
|
|
230
|
-
## ไธฆ็ผ่็
|
|
231
|
-
|
|
232
|
-
AsyncLRUCache ๆ่ชๅ่็ไธฆ็ผๆไฝ๏ผ
|
|
233
|
-
|
|
234
|
-
- **GET ่ซๆฑๅไฝต**๏ผๅฐๅไธ key ็ๅคๅไธฆ็ผ่ซๆฑๆๅ
ฑไบซๅฎไธ่ผๅ
ฅๅจๅท่ก
|
|
235
|
-
- **PUT ๆไฝๅบๅๅ**๏ผๅฐๅไธ key ็ๅคๅ PUT ๆไฝๆๅบๅๅๅท่กไปฅ็ขบไฟ้ ๅบ
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
// ้ไธๅไธฆ็ผ่ซๆฑๆๅ
ฑไบซๅไธๅ่ผๅ
ฅๅจๅท่ก
|
|
239
|
-
const [data1, data2, data3] = await Promise.all([
|
|
240
|
-
cache.get('shared-key', loader),
|
|
241
|
-
cache.get('shared-key', loader),
|
|
242
|
-
cache.get('shared-key', loader)
|
|
243
|
-
]);
|
|
244
|
-
|
|
245
|
-
// ้ไบๆไฝๆๆ้ ๅบๅท่ก๏ผๅณไฝฟๅฎๅๆฏไธฆ็ผๅๅ็
|
|
246
|
-
cache.put('key', 'value1', saver1);
|
|
247
|
-
cache.put('key', 'value2', saver2);
|
|
248
|
-
cache.put('key', 'value3', saver3);
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## TypeScript ๆฏๆด
|
|
252
|
-
|
|
253
|
-
ๆญคๅฅไปถๅฎๅ
จไฝฟ็จ TypeScript ็ทจๅฏซ๏ผๆไพๅฎๆด็ๅๅฅๆฏๆด๏ผ
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
interface User {
|
|
257
|
-
id: string;
|
|
258
|
-
name: string;
|
|
259
|
-
email: string;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
const userCache = new AsyncLRUCache<string, User>({
|
|
263
|
-
capacity: 1000
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
const user: User = await userCache.get('user:123', async () => {
|
|
267
|
-
// ่ผๅ
ฅๅจๅฟ
้ ๅๅณ User ๅๅฅ
|
|
268
|
-
return fetchUserFromAPI('123');
|
|
269
|
-
});
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
## ้ฏ่ชค่็
|
|
273
|
-
|
|
274
|
-
- **่ผๅ
ฅๅจๅคฑๆ**๏ผๅฆๆ่ผๅ
ฅๅจๅฝๆธๆๅบ็ฐๅธธ๏ผๅฐๆ็ๅฟซๅ้
็ฎๆ่ขซ่ชๅ็งป้ค
|
|
275
|
-
- **ไฟๅญๅจๅคฑๆ**๏ผๅฆๆไฟๅญๅจๅฝๆธๅคฑๆ๏ผๅฟซๅ้
็ฎไนๆ่ขซ็งป้ค๏ผ็ขบไฟ่ณๆไธ่ดๆง
|
|
276
|
-
- **ๆไฝ้้ฏ่ชค**๏ผPUT ๆไฝๆๅฟฝ็ฅๅไธๅๆไฝ็้ฏ่ชค๏ผๅ
่จฑๆฐๆไฝ็นผ็บ้ฒ่ก
|
|
277
|
-
- **้ฏ่ชคๆฅ่ช**๏ผๆๆ้ฏ่ชค้ฝๆ่ชๅ่จ้ๅฐๆงๅถๅฐ๏ผไพฟๆผ้ค้ฏ
|
|
145
|
+
ๆญคๅฅไปถไปฅ TypeScript ๆฐๅฏซไธฆๅ
งๅปบๅๅฅๅฎฃๅๆช๏ผ็ก้ๅฆๅคๅฎ่ฃ `@types` ๅฅไปถใ
|
|
278
146
|
|
|
279
147
|
## ๆๆฌ
|
|
280
148
|
|
|
@@ -284,6 +152,3 @@ MIT
|
|
|
284
152
|
|
|
285
153
|
ๆญก่ฟๅจ [GitHub](https://github.com/wfp99/async-lru-cache) ไธๆๅบๅ้กๅ็ผ้ Pull Requestใ
|
|
286
154
|
|
|
287
|
-
## ไฝ่
|
|
288
|
-
|
|
289
|
-
Wang Feng Ping
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,31 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module AsyncLRUCache
|
|
7
7
|
*/
|
|
8
|
+
/**
|
|
9
|
+
* Identifies which internal operation produced an error passed to `AsyncLRUCacheOption.onError`.
|
|
10
|
+
* - `loader`: The loader function passed to `get()` rejected.
|
|
11
|
+
* - `saver`: The saver function passed to `put()` rejected.
|
|
12
|
+
* - `put-chain`: A previous (already-settled) operation for the same key failed; this is a
|
|
13
|
+
* recoverable warning, since the new `put()` operation is still allowed to proceed.
|
|
14
|
+
*/
|
|
15
|
+
export type AsyncLRUCacheErrorSource = 'loader' | 'saver' | 'put-chain';
|
|
16
|
+
/**
|
|
17
|
+
* Context information supplied alongside an error to `AsyncLRUCacheOption.onError`.
|
|
18
|
+
*/
|
|
19
|
+
export interface AsyncLRUCacheErrorContext<K> {
|
|
20
|
+
/**
|
|
21
|
+
* The cache key associated with the failed operation.
|
|
22
|
+
*/
|
|
23
|
+
key: K;
|
|
24
|
+
/**
|
|
25
|
+
* Which internal operation produced the error.
|
|
26
|
+
*/
|
|
27
|
+
source: AsyncLRUCacheErrorSource;
|
|
28
|
+
}
|
|
8
29
|
/**
|
|
9
30
|
* Configuration options for the AsyncLRUCache.
|
|
10
31
|
*/
|
|
11
|
-
export interface AsyncLRUCacheOption {
|
|
32
|
+
export interface AsyncLRUCacheOption<K = unknown> {
|
|
12
33
|
/**
|
|
13
34
|
* Maximum capacity of the cache, this is the maximum number of items allowed.
|
|
14
35
|
* Must not be less than 10.
|
|
@@ -26,6 +47,14 @@ export interface AsyncLRUCacheOption {
|
|
|
26
47
|
* Setting this enables periodic background cleanup.
|
|
27
48
|
*/
|
|
28
49
|
cleanupIntervalMs?: number;
|
|
50
|
+
/**
|
|
51
|
+
* Optional callback invoked whenever a loader/saver operation fails.
|
|
52
|
+
* When provided, this callback *replaces* the built-in `console.error`/`console.warn`
|
|
53
|
+
* logging, so you can forward errors to your own logger or monitoring system.
|
|
54
|
+
* If not provided, errors are logged to the console as before (default, backward-compatible behavior).
|
|
55
|
+
* This callback must not throw; any error thrown from it is ignored.
|
|
56
|
+
*/
|
|
57
|
+
onError?: (error: unknown, context: AsyncLRUCacheErrorContext<K>) => void;
|
|
29
58
|
}
|
|
30
59
|
/**
|
|
31
60
|
* Asynchronous LRU Cache class.
|
|
@@ -60,12 +89,16 @@ export declare class AsyncLRUCache<K, V> {
|
|
|
60
89
|
* Timer ID for periodic cleanup of expired entries.
|
|
61
90
|
*/
|
|
62
91
|
private cleanupTimer?;
|
|
92
|
+
/**
|
|
93
|
+
* Optional user-supplied error callback. When absent, errors are logged to the console.
|
|
94
|
+
*/
|
|
95
|
+
private readonly onError?;
|
|
63
96
|
/**
|
|
64
97
|
* Creates an instance of AsyncLRUCache with the specified options.
|
|
65
98
|
* @param option - The configuration options for the cache.
|
|
66
99
|
* @throws {Error} Throws an error if the provided capacity is less than 10.
|
|
67
100
|
*/
|
|
68
|
-
constructor(option: AsyncLRUCacheOption);
|
|
101
|
+
constructor(option: AsyncLRUCacheOption<K>);
|
|
69
102
|
/**
|
|
70
103
|
* Cleans up expired entries from the cache.
|
|
71
104
|
* This method removes all nodes that have exceeded their TTL.
|
|
@@ -100,6 +133,15 @@ export declare class AsyncLRUCache<K, V> {
|
|
|
100
133
|
* @param node - The node to add to the head of the list.
|
|
101
134
|
*/
|
|
102
135
|
private _addToHead;
|
|
136
|
+
/**
|
|
137
|
+
* Reports an error that occurred during a loader/saver operation.
|
|
138
|
+
* Delegates to the user-supplied `onError` callback if one was provided in the
|
|
139
|
+
* constructor options; otherwise falls back to logging via `console.error`/`console.warn`.
|
|
140
|
+
* @param error - The error that was thrown/rejected.
|
|
141
|
+
* @param key - The cache key associated with the failed operation.
|
|
142
|
+
* @param source - Which internal operation produced the error.
|
|
143
|
+
*/
|
|
144
|
+
private _reportError;
|
|
103
145
|
/**
|
|
104
146
|
* Retrieves data from the cache. If it does not exist, uses the loader to load it.
|
|
105
147
|
* Automatically merges concurrent requests for the same key.
|
|
@@ -109,6 +151,25 @@ export declare class AsyncLRUCache<K, V> {
|
|
|
109
151
|
* @returns A Promise that resolves to the required data.
|
|
110
152
|
*/
|
|
111
153
|
get(key: K, loader: () => Promise<V>, ttlMs?: number): Promise<V>;
|
|
154
|
+
/**
|
|
155
|
+
* Retrieves data from the cache without loading it on a miss.
|
|
156
|
+
* On a cache hit, this behaves like the loader-based overload: the entry is moved to
|
|
157
|
+
* the head of the LRU list, same as a normal `get()`/`has()` hit.
|
|
158
|
+
* On a cache miss (including an expired entry), it resolves to `undefined` without
|
|
159
|
+
* adding anything to the cache, so it does not affect the LRU order.
|
|
160
|
+
* @param key - Cache key.
|
|
161
|
+
* @returns A Promise that resolves to the cached value, or `undefined` on a miss.
|
|
162
|
+
*/
|
|
163
|
+
get(key: K): Promise<V | undefined>;
|
|
164
|
+
/**
|
|
165
|
+
* Returns the cached value for a key without triggering a loader and without
|
|
166
|
+
* affecting the LRU order, regardless of whether the key is a hit or a miss.
|
|
167
|
+
* If the entry has expired, it is evicted as a side effect of this check, the same
|
|
168
|
+
* way `has()` behaves; this does not count as an LRU-order-affecting access.
|
|
169
|
+
* @param key - Cache key.
|
|
170
|
+
* @returns The cached value's Promise if the key is present and not expired, otherwise `undefined`.
|
|
171
|
+
*/
|
|
172
|
+
peek(key: K): Promise<V> | undefined;
|
|
112
173
|
/**
|
|
113
174
|
* Puts a value into the cache, and optionally executes a saver function to persist it.
|
|
114
175
|
* This method serializes multiple put operations for the same key, ensuring they execute in order.
|
|
@@ -145,8 +206,15 @@ export declare class AsyncLRUCache<K, V> {
|
|
|
145
206
|
size(): number;
|
|
146
207
|
/**
|
|
147
208
|
* Checks if a key exists in the cache and is not expired.
|
|
209
|
+
*
|
|
210
|
+
* Note: this method is **not** side-effect-free. If the entry has expired, it is
|
|
211
|
+
* immediately evicted from the cache as part of this check (same as what would
|
|
212
|
+
* happen on the next `get()`/cleanup pass). It does **not** affect LRU order for
|
|
213
|
+
* entries that are still valid (unlike `get()`, calling `has()` does not move the
|
|
214
|
+
* entry to the head of the list).
|
|
148
215
|
* @param key - The key to check.
|
|
149
216
|
* @returns True if the key exists and is not expired, false otherwise.
|
|
150
217
|
*/
|
|
151
218
|
has(key: K): boolean;
|
|
152
219
|
}
|
|
220
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8DH;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,OAAO,GAAG,WAAW,CAAC;AAExE;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAE3C;;OAEG;IACH,GAAG,EAAE,CAAC,CAAC;IAEP;;OAEG;IACH,MAAM,EAAE,wBAAwB,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB,CAAC,CAAC,GAAG,OAAO;IAE/C;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;CAC1E;AAED;;;;;;;GAOG;AACH,qBAAa,aAAa,CAAC,CAAC,EAAE,CAAC;IAE9B;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAElC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAS;IAEvC;;OAEG;IACH,OAAO,CAAC,OAAO,CAA4B;IAE3C;;OAEG;IACH,OAAO,CAAC,IAAI,CAA2B;IAEvC;;OAEG;IACH,OAAO,CAAC,IAAI,CAA2B;IAEvC;;OAEG;IACH,OAAO,CAAC,YAAY,CAAC,CAAiB;IAEtC;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAkE;IAE3F;;;;OAIG;gBACS,MAAM,EAAE,mBAAmB,CAAC,CAAC,CAAC;IAkB1C;;;OAGG;IACH,OAAO,CAAC,eAAe;IAyBvB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAW9B;;;OAGG;IACH,OAAO,CAAC,cAAc;IAStB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAQnB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAanB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAYlB;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IA6BpB;;;;;;;OAOG;IACI,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAExE;;;;;;;;OAQG;IACI,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;IAiD1C;;;;;;;OAOG;IACI,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS;IAgB3C;;;;;;;;OAQG;IACI,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IA4DrG;;;OAGG;IACI,UAAU,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI;IAW/B;;OAEG;IACI,KAAK,IAAI,IAAI;IA2BpB;;;OAGG;IACI,OAAO,IAAI,IAAI;IAatB;;;OAGG;IACI,cAAc,IAAI,IAAI;IAK7B;;;OAGG;IACI,IAAI,IAAI,MAAM;IAKrB;;;;;;;;;;OAUG;IACI,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;CAe3B"}
|
package/dist/index.js
CHANGED
|
@@ -79,6 +79,7 @@ class AsyncLRUCache {
|
|
|
79
79
|
throw new Error("Capacity must be at least 10.");
|
|
80
80
|
this.capacity = option.capacity;
|
|
81
81
|
this.defaultTtlMs = option.defaultTtlMs;
|
|
82
|
+
this.onError = option.onError;
|
|
82
83
|
// Setup periodic cleanup if specified
|
|
83
84
|
if (option.cleanupIntervalMs && option.cleanupIntervalMs > 0) {
|
|
84
85
|
this.cleanupTimer = setInterval(() => {
|
|
@@ -171,33 +172,60 @@ class AsyncLRUCache {
|
|
|
171
172
|
this.tail = node;
|
|
172
173
|
}
|
|
173
174
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
* @param
|
|
178
|
-
* @param
|
|
179
|
-
* @
|
|
175
|
+
* Reports an error that occurred during a loader/saver operation.
|
|
176
|
+
* Delegates to the user-supplied `onError` callback if one was provided in the
|
|
177
|
+
* constructor options; otherwise falls back to logging via `console.error`/`console.warn`.
|
|
178
|
+
* @param error - The error that was thrown/rejected.
|
|
179
|
+
* @param key - The cache key associated with the failed operation.
|
|
180
|
+
* @param source - Which internal operation produced the error.
|
|
180
181
|
*/
|
|
182
|
+
_reportError(error, key, source) {
|
|
183
|
+
if (this.onError) {
|
|
184
|
+
try {
|
|
185
|
+
this.onError(error, { key, source });
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
// Swallow errors thrown by the user-supplied callback; it must not break cache operations.
|
|
189
|
+
}
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
switch (source) {
|
|
193
|
+
case 'loader':
|
|
194
|
+
console.error(`[AsyncLRUCache ERROR] Loader for key ${key} failed. Removing from cache.`, error);
|
|
195
|
+
break;
|
|
196
|
+
case 'saver':
|
|
197
|
+
console.error(`[AsyncLRUCache ERROR] Saver operation for key ${key} failed. Removing from cache.`, error);
|
|
198
|
+
break;
|
|
199
|
+
case 'put-chain':
|
|
200
|
+
console.warn(`[AsyncLRUCache WARN] Previous operation for key ${key} failed. Chaining new PUT operation.`, error?.message ?? error);
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
181
204
|
get(key, loader, ttlMs) {
|
|
182
205
|
const node = this.dataMap.get(key);
|
|
183
206
|
if (node) {
|
|
184
207
|
// Check if the node has expired
|
|
185
208
|
if (this._checkAndRemoveExpired(key, node)) {
|
|
186
|
-
// Node was expired and removed, proceed to load fresh data
|
|
209
|
+
// Node was expired and removed, proceed to load fresh data (if a loader is provided)
|
|
187
210
|
}
|
|
188
211
|
else {
|
|
189
212
|
this._moveToHead(node);
|
|
190
213
|
return node.value;
|
|
191
214
|
}
|
|
192
215
|
}
|
|
216
|
+
if (!loader) {
|
|
217
|
+
// No loader was provided and there is no valid cached value.
|
|
218
|
+
// Resolve to undefined without touching the cache or its LRU order.
|
|
219
|
+
return Promise.resolve(undefined);
|
|
220
|
+
}
|
|
193
221
|
const loadingPromise = loader();
|
|
194
|
-
const effectiveTtlMs = ttlMs
|
|
222
|
+
const effectiveTtlMs = ttlMs ?? this.defaultTtlMs;
|
|
195
223
|
const newNode = new Node(key, loadingPromise, effectiveTtlMs);
|
|
196
224
|
this.dataMap.set(key, newNode);
|
|
197
225
|
this._addToHead(newNode);
|
|
198
226
|
this._evictIfNeeded();
|
|
199
227
|
loadingPromise.catch(err => {
|
|
200
|
-
|
|
228
|
+
this._reportError(err, key, 'loader');
|
|
201
229
|
if (this.dataMap.get(key) === newNode) {
|
|
202
230
|
this.dataMap.delete(key);
|
|
203
231
|
this._removeNode(newNode);
|
|
@@ -205,6 +233,24 @@ class AsyncLRUCache {
|
|
|
205
233
|
});
|
|
206
234
|
return loadingPromise;
|
|
207
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Returns the cached value for a key without triggering a loader and without
|
|
238
|
+
* affecting the LRU order, regardless of whether the key is a hit or a miss.
|
|
239
|
+
* If the entry has expired, it is evicted as a side effect of this check, the same
|
|
240
|
+
* way `has()` behaves; this does not count as an LRU-order-affecting access.
|
|
241
|
+
* @param key - Cache key.
|
|
242
|
+
* @returns The cached value's Promise if the key is present and not expired, otherwise `undefined`.
|
|
243
|
+
*/
|
|
244
|
+
peek(key) {
|
|
245
|
+
const node = this.dataMap.get(key);
|
|
246
|
+
if (!node) {
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
if (this._checkAndRemoveExpired(key, node)) {
|
|
250
|
+
return undefined;
|
|
251
|
+
}
|
|
252
|
+
return node.value;
|
|
253
|
+
}
|
|
208
254
|
/**
|
|
209
255
|
* Puts a value into the cache, and optionally executes a saver function to persist it.
|
|
210
256
|
* This method serializes multiple put operations for the same key, ensuring they execute in order.
|
|
@@ -218,7 +264,7 @@ class AsyncLRUCache {
|
|
|
218
264
|
const lastPromise = this.dataMap.has(key) ? this.dataMap.get(key).value : Promise.resolve(undefined);
|
|
219
265
|
const saverPromise = lastPromise.catch((err) => {
|
|
220
266
|
// Ignore previous operation errors, so the new operation can proceed.
|
|
221
|
-
|
|
267
|
+
this._reportError(err, key, 'put-chain');
|
|
222
268
|
})
|
|
223
269
|
.then(() => {
|
|
224
270
|
// After the previous operation (success or failure) completes, execute this saver.
|
|
@@ -230,7 +276,7 @@ class AsyncLRUCache {
|
|
|
230
276
|
return value;
|
|
231
277
|
});
|
|
232
278
|
let node = this.dataMap.get(key);
|
|
233
|
-
const effectiveTtlMs = ttlMs
|
|
279
|
+
const effectiveTtlMs = ttlMs ?? this.defaultTtlMs;
|
|
234
280
|
if (!node) {
|
|
235
281
|
node = new Node(key, saverPromise, effectiveTtlMs);
|
|
236
282
|
this.dataMap.set(key, node);
|
|
@@ -249,9 +295,8 @@ class AsyncLRUCache {
|
|
|
249
295
|
this._moveToHead(node);
|
|
250
296
|
}
|
|
251
297
|
saverPromise.catch(err => {
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
if (((_a = this.dataMap.get(key)) === null || _a === void 0 ? void 0 : _a.value) === saverPromise) {
|
|
298
|
+
this._reportError(err, key, 'saver');
|
|
299
|
+
if (this.dataMap.get(key)?.value === saverPromise) {
|
|
255
300
|
this.dataMap.delete(key);
|
|
256
301
|
this._removeNode(node);
|
|
257
302
|
}
|
|
@@ -320,6 +365,12 @@ class AsyncLRUCache {
|
|
|
320
365
|
}
|
|
321
366
|
/**
|
|
322
367
|
* Checks if a key exists in the cache and is not expired.
|
|
368
|
+
*
|
|
369
|
+
* Note: this method is **not** side-effect-free. If the entry has expired, it is
|
|
370
|
+
* immediately evicted from the cache as part of this check (same as what would
|
|
371
|
+
* happen on the next `get()`/cleanup pass). It does **not** affect LRU order for
|
|
372
|
+
* entries that are still valid (unlike `get()`, calling `has()` does not move the
|
|
373
|
+
* entry to the head of the list).
|
|
323
374
|
* @param key - The key to check.
|
|
324
375
|
* @returns True if the key exists and is not expired, false otherwise.
|
|
325
376
|
*/
|
|
@@ -335,3 +386,4 @@ class AsyncLRUCache {
|
|
|
335
386
|
}
|
|
336
387
|
}
|
|
337
388
|
exports.AsyncLRUCache = AsyncLRUCache;
|
|
389
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wfp99/async-lru-cache",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A simple memory cache using the LRU algorithm and supporting asynchronous data access.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cache",
|
|
@@ -14,6 +14,13 @@
|
|
|
14
14
|
"type": "commonjs",
|
|
15
15
|
"main": "dist/index.js",
|
|
16
16
|
"types": "dist/index.d.ts",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"require": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
17
24
|
"files": [
|
|
18
25
|
"dist/",
|
|
19
26
|
"README.md",
|
|
@@ -34,11 +41,13 @@
|
|
|
34
41
|
"scripts": {
|
|
35
42
|
"build": "tsc",
|
|
36
43
|
"clean": "rm -rf dist",
|
|
37
|
-
"prepublishOnly": "npm run clean && npm run build",
|
|
38
|
-
"test": "
|
|
44
|
+
"prepublishOnly": "npm run clean && npm run build && npm test",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:watch": "vitest"
|
|
39
47
|
},
|
|
40
48
|
"devDependencies": {
|
|
41
49
|
"@types/node": "^24.0.7",
|
|
42
|
-
"typescript": "^5.8.3"
|
|
50
|
+
"typescript": "^5.8.3",
|
|
51
|
+
"vitest": "^3.2.4"
|
|
43
52
|
}
|
|
44
53
|
}
|