cacheable 0.3.0 → 0.8.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/LICENSE +1 -1
- package/README.md +108 -142
- package/dist/index.cjs +448 -0
- package/dist/index.d.cts +104 -0
- package/dist/index.d.ts +104 -0
- package/dist/index.js +421 -0
- package/package.json +25 -14
- package/src/index.ts +0 -122
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -109
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
[<img align="center" src="https://
|
|
1
|
+
[<img align="center" src="https://cacheable.org/logo.svg" alt="Cacheable" />](https://github.com/jaredwray/cacheable)
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Cacheable
|
|
4
4
|
|
|
5
5
|
> Simple Caching Engine using Keyv
|
|
6
6
|
|
|
7
|
-
[](https://codecov.io/gh/jaredwray/cacheable)
|
|
8
8
|
[](https://github.com/jaredwray/cacheable/actions/workflows/tests.yml)
|
|
9
9
|
[](https://www.npmjs.com/package/cacheable)
|
|
10
10
|
[](https://www.npmjs.com/package/cacheable)
|
|
11
11
|
|
|
12
|
-
`cacheable` is a
|
|
12
|
+
`cacheable` is a high performance layer 1 / layer 2 caching engine that is focused on distributed caching with enterprise features such as `CacheSync`. It is built on top of the robust storage engine [Keyv](https://keyv.org) and provides a simple API to cache and retrieve data.
|
|
13
|
+
|
|
13
14
|
* Simple to use with robust API
|
|
14
15
|
* Not bloated with additional modules
|
|
15
16
|
* Extendable to your own caching engine
|
|
16
17
|
* Scalable and trusted storage engine by Keyv
|
|
17
|
-
*
|
|
18
|
+
* Resilient to failures with try/catch and offline
|
|
18
19
|
* Hooks and Events to extend functionality
|
|
19
20
|
* Comprehensive testing and code coverage
|
|
20
|
-
*
|
|
21
|
+
* Distributed Caching Sync via Pub/Sub (coming soon)
|
|
22
|
+
* Maintained and supported regularly
|
|
21
23
|
|
|
22
24
|
## Getting Started
|
|
23
25
|
|
|
@@ -33,186 +35,150 @@ npm install cacheable
|
|
|
33
35
|
import { Cacheable } from 'cacheable';
|
|
34
36
|
|
|
35
37
|
const cacheable = new Cacheable();
|
|
36
|
-
cacheable.set('key', 'value', 1000);
|
|
37
|
-
const value = cacheable.get('key');
|
|
38
|
+
await cacheable.set('key', 'value', 1000);
|
|
39
|
+
const value = await cacheable.get('key');
|
|
38
40
|
```
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
This is a basic example where you are only using the in-memory storage engine. To enable layer 1 and layer 2 caching you can use the `secondary` property in the options:
|
|
41
43
|
|
|
42
44
|
```javascript
|
|
43
45
|
import { Cacheable } from 'cacheable';
|
|
46
|
+
import KeyvRedis from '@keyv/redis';
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
From here you now how the ability to use the `cacheable` API. You can also extend the API to add your own functionality.
|
|
53
|
-
|
|
54
|
-
## Storage Adapters and Keyv
|
|
48
|
+
const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
|
|
49
|
+
const cache = new Cacheable({secondary});
|
|
50
|
+
```
|
|
55
51
|
|
|
56
|
-
|
|
52
|
+
In this example, the primary store we will use `lru-cache` and the secondary store is Redis. You can also set multiple stores in the options:
|
|
57
53
|
|
|
58
54
|
```javascript
|
|
59
55
|
import { Cacheable } from 'cacheable';
|
|
60
|
-
import Keyv from 'keyv';
|
|
56
|
+
import { Keyv } from 'keyv';
|
|
57
|
+
import KeyvRedis from '@keyv/redis';
|
|
58
|
+
import { LRUCache } from 'lru-cache'
|
|
61
59
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
}
|
|
60
|
+
const primary = new Keyv({store: new LRUCache()});
|
|
61
|
+
const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
|
|
62
|
+
const cache = new Cacheable({primary, secondary});
|
|
67
63
|
```
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
This is a more advanced example and not needed for most use cases.
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
import { Cacheable } from 'cacheable';
|
|
73
|
-
import Keyv from 'keyv';
|
|
67
|
+
## Hooks and Events
|
|
74
68
|
|
|
75
|
-
|
|
76
|
-
constructor() {
|
|
77
|
-
super();
|
|
69
|
+
The following hooks are available for you to extend the functionality of `cacheable` via `CacheableHooks` enum:
|
|
78
70
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
* `BEFORE_SET`: This is called before the `set()` method is called.
|
|
72
|
+
* `AFTER_SET`: This is called after the `set()` method is called.
|
|
73
|
+
* `BEFORE_SET_MANY`: This is called before the `setMany()` method is called.
|
|
74
|
+
* `AFTER_SET_MANY`: This is called after the `setMany()` method is called.
|
|
75
|
+
* `BEFORE_GET`: This is called before the `get()` method is called.
|
|
76
|
+
* `AFTER_GET`: This is called after the `get()` method is called.
|
|
77
|
+
* `BEFORE_GET_MANY`: This is called before the `getMany()` method is called.
|
|
78
|
+
* `AFTER_GET_MANY`: This is called after the `getMany()` method is called.
|
|
79
|
+
|
|
80
|
+
An example of how to use these hooks:
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
import { Cacheable, CacheableHooks } from 'cacheable';
|
|
84
|
+
|
|
85
|
+
const cacheable = new Cacheable();
|
|
86
|
+
cacheable.onHook(CacheableHooks.BEFORE_SET, (data) => {
|
|
87
|
+
console.log(`before set: ${data.key} ${data.value}`);
|
|
88
|
+
});
|
|
82
89
|
```
|
|
83
90
|
|
|
84
|
-
##
|
|
91
|
+
## Storage Tiering and Caching
|
|
85
92
|
|
|
86
|
-
|
|
93
|
+
`cacheable` is built as a layer 1 and layer 2 caching engine by default. The purpose is to have your layer 1 be fast and your layer 2 be more persistent. The primary store is the layer 1 cache and the secondary store is the layer 2 cache. By adding the secondary store you are enabling layer 2 caching. By default the operations are blocking but fault tolerant:
|
|
94
|
+
|
|
95
|
+
* `Setting Data`: Sets the value in the primary store and then the secondary store.
|
|
96
|
+
* `Getting Data`: Gets the value from the primary if the value does not exist it will get it from the secondary store and set it in the primary store.
|
|
97
|
+
* `Deleting Data`: Deletes the value from the primary store and secondary store at the same time waiting for both to respond.
|
|
98
|
+
* `Clearing Data`: Clears the primary store and secondary store at the same time waiting for both to respond.
|
|
99
|
+
|
|
100
|
+
## Non-Blocking Operations
|
|
101
|
+
|
|
102
|
+
If you want your layer 2 (secondary) store to be non-blocking you can set the `nonBlocking` property to `true` in the options. This will make the secondary store non-blocking and will not wait for the secondary store to respond on `setting data`, `deleting data`, or `clearing data`. This is useful if you want to have a faster response time and not wait for the secondary store to respond.
|
|
87
103
|
|
|
88
104
|
```javascript
|
|
89
105
|
import { Cacheable } from 'cacheable';
|
|
106
|
+
import {KeyvRedis} from '@keyv/redis';
|
|
90
107
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
super();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
async getStats() {
|
|
97
|
-
return this.stats.getReport();
|
|
98
|
-
}
|
|
99
|
-
}
|
|
108
|
+
const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
|
|
109
|
+
const cache = new Cacheable({secondary, nonBlocking: true});
|
|
100
110
|
```
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
```json
|
|
105
|
-
{
|
|
106
|
-
"cacheSize": 100,
|
|
107
|
-
"currentSize": 80,
|
|
108
|
-
"hits": 500,
|
|
109
|
-
"misses": 200,
|
|
110
|
-
"hitRate": 0.71,
|
|
111
|
-
"evictions": 50,
|
|
112
|
-
"averageLoadPenalty": 0.05,
|
|
113
|
-
"loadSuccessCount": 700,
|
|
114
|
-
"loadExceptionCount": 10,
|
|
115
|
-
"totalLoadTime": 3500,
|
|
116
|
-
"topHits": [
|
|
117
|
-
{
|
|
118
|
-
"key": "key1",
|
|
119
|
-
"value": "value1",
|
|
120
|
-
"lastAccessed": 1627593600000,
|
|
121
|
-
"accessCount": 50
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
"key": "key2",
|
|
125
|
-
"value": "value2",
|
|
126
|
-
"lastAccessed": 1627593600000,
|
|
127
|
-
"accessCount": 45
|
|
128
|
-
}
|
|
129
|
-
// More items...
|
|
130
|
-
],
|
|
131
|
-
"leastUsed": [
|
|
132
|
-
{
|
|
133
|
-
"key": "key3",
|
|
134
|
-
"value": "value3",
|
|
135
|
-
"lastAccessed": 1627593600000,
|
|
136
|
-
"accessCount": 5
|
|
137
|
-
},
|
|
138
|
-
{
|
|
139
|
-
"key": "key4",
|
|
140
|
-
"value": "value4",
|
|
141
|
-
"lastAccessed": 1627593600000,
|
|
142
|
-
"accessCount": 4
|
|
143
|
-
}
|
|
144
|
-
// More items...
|
|
145
|
-
]
|
|
146
|
-
}
|
|
147
|
-
```
|
|
112
|
+
## CacheSync - Distributed Updates
|
|
148
113
|
|
|
149
|
-
|
|
150
|
-
* `currentSize`: The current number of items in the cache.
|
|
151
|
-
hits: The number of cache hits. A cache hit occurs when the requested data is found in the cache.
|
|
152
|
-
* `misses`: The number of cache misses. A cache miss occurs when the requested data is not found in the cache and needs to be loaded.
|
|
153
|
-
* `hitRate`: The ratio of cache hits to the total number of cache lookups. This is a measure of the cache's effectiveness.
|
|
154
|
-
* `evictions`: The number of items that have been evicted from the cache, typically because the cache is full.
|
|
155
|
-
* `averageLoadPenalty`: The average time spent loading new values into the cache, typically measured in milliseconds. This could be calculated as totalLoadTime / (hits + misses).
|
|
156
|
-
* `loadSuccessCount`: The number of times cache loading has succeeded.
|
|
157
|
-
* `loadExceptionCount`: The number of times cache loading has failed due to exceptions.
|
|
158
|
-
* `totalLoadTime`: The total time spent loading new values into the cache, typically measured in milliseconds.
|
|
114
|
+
`cacheable` has a feature called `CacheSync` that is coming soon. This feature will allow you to have distributed caching with Pub/Sub. This will allow you to have multiple instances of `cacheable` running and when a value is set, deleted, or cleared it will update all instances of `cacheable` with the same value. Current plan is to support the following:
|
|
159
115
|
|
|
160
|
-
|
|
116
|
+
* [Google Pub/Sub](https://cloud.google.com/pubsub)
|
|
117
|
+
* [AWS SQS](https://aws.amazon.com/sqs)
|
|
118
|
+
* [RabbitMQ](https://www.rabbitmq.com)
|
|
119
|
+
* [Nats](https://nats.io)
|
|
120
|
+
* [Azure Service Bus](https://azure.microsoft.com/en-us/services/service-bus)
|
|
121
|
+
* [Redis Pub/Sub](https://redis.io/topics/pubsub)
|
|
161
122
|
|
|
162
|
-
|
|
123
|
+
This feature should be live by end of year.
|
|
163
124
|
|
|
164
|
-
|
|
165
|
-
* `postSet`: This is called after the `set` method is called.
|
|
166
|
-
* `preSetMany`: This is called before the `setMany` method is called.
|
|
167
|
-
* `postSetMany`: This is called after the `setMany` method is called.
|
|
168
|
-
* `preGet`: This is called before the `get` method is called.
|
|
169
|
-
* `postGet`: This is called after the `get` method is called.
|
|
170
|
-
* `preGetMany`: This is called before the `getMany` method is called.
|
|
171
|
-
* `postGetMany`: This is called after the `getMany` method is called.
|
|
125
|
+
## Cacheable Options
|
|
172
126
|
|
|
173
|
-
|
|
127
|
+
The following options are available for you to configure `cacheable`:
|
|
174
128
|
|
|
175
|
-
|
|
176
|
-
|
|
129
|
+
* `primary`: The primary store for the cache (layer 1) defaults to in-memory by Keyv.
|
|
130
|
+
* `secondary`: The secondary store for the cache (layer 2) usually a persistent cache by Keyv.
|
|
131
|
+
* `nonBlocking`: If the secondary store is non-blocking. Default is `false`.
|
|
132
|
+
* `enableStats`: If you want to enable statistics for this instance. Default is `false`.
|
|
177
133
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
134
|
+
## Cacheable Statistics (Instance Only)
|
|
135
|
+
|
|
136
|
+
If you want to enable statistics for your instance you can set the `enableStats` property to `true` in the options. This will enable statistics for your instance and you can get the statistics by calling the `stats` property. Here are the following property statistics:
|
|
137
|
+
|
|
138
|
+
* `hits`: The number of hits in the cache.
|
|
139
|
+
* `misses`: The number of misses in the cache.
|
|
140
|
+
* `sets`: The number of sets in the cache.
|
|
141
|
+
* `deletes`: The number of deletes in the cache.
|
|
142
|
+
* `clears`: The number of clears in the cache.
|
|
143
|
+
* `errors`: The number of errors in the cache.
|
|
144
|
+
* `count`: The number of keys in the cache.
|
|
145
|
+
* `vsize`: The estimated byte size of the values in the cache.
|
|
146
|
+
* `ksize`: The estimated byte size of the keys in the cache.
|
|
183
147
|
|
|
184
|
-
|
|
148
|
+
You can clear the stats by calling the `clearStats()` method.
|
|
185
149
|
|
|
186
|
-
|
|
187
|
-
* `setMany`: This is called when the `setMany` method is called.
|
|
188
|
-
* `get`: This is called when the `get` method is called.
|
|
189
|
-
* `getMany`: This is called when the `getMany` method is called.
|
|
190
|
-
* `clear`: This is called when the `clear` method is called.
|
|
191
|
-
* `has`: This is called when the `has` method is called.
|
|
192
|
-
* `disconnect`: This is called when the `disconnect` method is called.
|
|
193
|
-
* `error`: This is called when an error occurs.
|
|
150
|
+
_This does not enable statistics for your layer 2 cache as that is a distributed cache_.
|
|
194
151
|
|
|
195
152
|
## API
|
|
196
153
|
|
|
197
|
-
* `set(key, value, ttl?)`: Sets a value in the cache.
|
|
154
|
+
* `set(key, value, ttl? | [{string, string, ttl?}])`: Sets a value in the cache.
|
|
198
155
|
* `setMany([{key, value, ttl?}])`: Sets multiple values in the cache.
|
|
199
|
-
* `get(key)`: Gets a value from the cache.
|
|
200
|
-
* `has(key)`: Checks if a value exists in the cache.
|
|
156
|
+
* `get(key | [keys])`: Gets a value from the cache.
|
|
201
157
|
* `getMany([keys])`: Gets multiple values from the cache.
|
|
202
|
-
* `
|
|
203
|
-
* `
|
|
204
|
-
* `
|
|
205
|
-
* `
|
|
206
|
-
* `
|
|
207
|
-
* `
|
|
208
|
-
* `
|
|
158
|
+
* `has(key | [key])`: Checks if a value exists in the cache.
|
|
159
|
+
* `hasMany([keys])`: Checks if multiple values exist in the cache.
|
|
160
|
+
* `take(key)`: Takes a value from the cache and deletes it. (coming soon)
|
|
161
|
+
* `takeMany([keys])`: Takes multiple values from the cache and deletes them. (coming soon)
|
|
162
|
+
* `delete(key | [key])`: Deletes a value from the cache.
|
|
163
|
+
* `deleteMany([keys])`: Deletes multiple values from the cache.
|
|
164
|
+
* `clear()`: Clears the cache stores. Be careful with this as it will clear both layer 1 and layer 2.
|
|
165
|
+
* `clearPrimary()`: Clears the primary store. (coming soon)
|
|
166
|
+
* `clearSecondary()`: Clears the secondary store. (coming soon)
|
|
167
|
+
* `wrap(function, options)`: Wraps a function in a cache. (coming soon)
|
|
168
|
+
* `disconnect()`: Disconnects from the cache stores.
|
|
169
|
+
* `onHook(hook, callback)`: Sets a hook.
|
|
170
|
+
* `removeHook(hook)`: Removes a hook.
|
|
209
171
|
* `on(event, callback)`: Listens for an event.
|
|
210
172
|
* `removeListener(event, callback)`: Removes a listener.
|
|
211
|
-
* `
|
|
173
|
+
* `primary`: The primary store for the cache (layer 1) defaults to in-memory by Keyv.
|
|
174
|
+
* `secondary`: The secondary store for the cache (layer 2) usually a persistent cache by Keyv.
|
|
175
|
+
* `nonBlocking`: If the secondary store is non-blocking. Default is `false`.
|
|
176
|
+
* `stats`: The statistics for this instance which includes `hits`, `misses`, `sets`, `deletes`, `clears`, `errors`, `count`, `vsize`, `ksize`.
|
|
177
|
+
* `clearStats()`: Clears the statistics for this instance.
|
|
212
178
|
|
|
213
179
|
## How to Contribute
|
|
214
180
|
|
|
215
181
|
You can contribute by forking the repo and submitting a pull request. Please make sure to add tests and update the documentation. To learn more about how to contribute go to our main README [https://github.com/jaredwray/cacheable](https://github.com/jaredwray/cacheable). This will talk about how to `Open a Pull Request`, `Ask a Question`, or `Post an Issue`.
|
|
216
182
|
|
|
217
183
|
## License and Copyright
|
|
218
|
-
MIT © Jared Wray
|
|
184
|
+
[MIT © Jared Wray](./LICENSE)
|