diff --git a/README.md b/README.md index 0f8eb52..81ed5e0 100644 --- a/README.md +++ b/README.md @@ -121,9 +121,10 @@ See the [events documentation](https://bentocache.dev/docs/events) for more info All TTLs can be passed in a human-readable string format. We use [lukeed/ms](https://github.com/lukeed/ms) under the hood. (this is optional, and you can pass a `number` in milliseconds if you prefer) ```ts -bento.getOrSet('foo', () => getFromDb(), { - ttl: '2.5h' - gracePeriod: { enabled: true, duration: '6h' } +bento.getOrSet({ + key: 'foo', + ttl: '2.5h', + factory: () => getFromDb(), }) ``` @@ -132,8 +133,10 @@ bento.getOrSet('foo', () => getFromDb(), { When you cached item will expire soon, you can refresh it in advance, in the background. This way, next time the entry is requested, it will already be computed and thus returned to the user super quickly. ```ts -bento.getOrSet('foo', () => getFromDb(), { +bento.getOrSet({ + key: 'foo', earlyExpiration: 0.8 + factory: () => getFromDb(), }) ``` diff --git a/docs/content/docs/introduction.md b/docs/content/docs/introduction.md index 75947e3..5984d9b 100644 --- a/docs/content/docs/introduction.md +++ b/docs/content/docs/introduction.md @@ -132,9 +132,10 @@ See the [events documentation](./digging_deeper/events.md) for more information. All TTLs can be passed in a human-readable string format. We use [lukeed/ms](https://github.com/lukeed/ms) under the hood. (this is optional, and you can pass a `number` in milliseconds if you prefer) ```ts -bento.getOrSet('foo', () => getFromDb(), { +bento.getOrSet({ + key: 'foo', ttl: '2.5h', - gracePeriod: { enabled: true, duration: '6h' } + factory: () => getFromDb(), }) ``` @@ -143,8 +144,10 @@ bento.getOrSet('foo', () => getFromDb(), { When you cached item will expire soon, you can refresh it in advance, in the background. This way, next time the entry is requested, it will already be computed and thus returned to the user super quickly. ```ts -bento.getOrSet('foo', () => getFromDb(), { - earlyExpiration: 0.8 +bento.getOrSet({ + key: 'foo', + earlyExpiration: 0.8, + factory: () => getFromDb(), }) ``` diff --git a/docs/content/docs/methods.md b/docs/content/docs/methods.md index 6ec3d2b..0b8ef1e 100644 --- a/docs/content/docs/methods.md +++ b/docs/content/docs/methods.md @@ -6,6 +6,32 @@ summary: "Comprehensive list of all methods available when using BentoCache" Below is a list of all the methods available when using BentoCache. +### Single object vs multiple arguments + +Most of the methods accept arguments in two different ways : either as a single argument or as an object. + +If you need to pass some specific options, the object way is probably the best choice since it is more "vertical" and may be easier to read. On the other hand, the single argument may be more concise when you don't need to pass specific options. + +Example : + +```ts +// multiple arguments +await bento.getOrSet('products', () => fetchProducts(), { + ttl: '5m', + gracePeriod: { enabled: true, duration: '1m' }, +}) + +// is equivalent to +await bento.getOrSet({ + key: 'products', + ttl: '5m', + factory: () => fetchProducts(), + gracePeriod: { enabled: true, duration: '1m' }, +}) +``` + +--- + ### namespace Returns a new instance of the driver namespace. See [Namespaces](./namespaces.md) for more information. @@ -22,7 +48,7 @@ usersNamespace.clear(); ### get -`get` has multiple signatures and so it can be used in different ways. +`get` allows you to retrieve a value from the cache. It returns `undefined` if the key does not exist. #### get(key: string) @@ -53,6 +79,17 @@ const products = await bento.get('products', [], { }); ``` +#### get(options: GetPojoOptions) + +Same as above, but with an object as argument. + +```ts +const products = await bento.get({ + key: 'products', + defaultValue: [], +}); +``` + ### set Set a value in the cache. @@ -62,6 +99,12 @@ await bento.set('products', products); await bento.set('products', products, { gracePeriod: { enabled: true, duration: '5m' } }); + +await bento.set({ + key: 'products', + value: products, + gracePeriod: { enabled: true, duration: '5m' } +}) ``` ### setForever @@ -70,6 +113,12 @@ Set a value in the cache forever. It will never expire. ```ts await bento.setForever('products', products); + +await bento.setForever({ + key: 'products', + value: products, + gracePeriod: { enabled: true, duration: '5m' } +}) ``` ### getOrSet @@ -87,6 +136,14 @@ const products = await bento.getOrSet('products', () => fetchProducts(), { ttl: '5m', gracePeriod: { enabled: true, duration: '1m' }, }) + +// with options as object +const products = await bento.getOrSet({ + key: 'products', + ttl: '5m', + factory: () => fetchProducts(), + gracePeriod: { enabled: true, duration: '1m' }, +}) ``` The `getOrSet` factory function accepts an `options` object as argument that can be used to dynamically set some cache options. This can be particulary useful when caching options depends on the value itself. @@ -107,6 +164,11 @@ Same as `getOrSet`, but the value will never expire. ```ts const products = await bento.getOrSetForever('products', () => fetchProducts()) + +const products = await bento.getOrSetForever({ + key: 'products', + factory: () => fetchProducts(), +}) ``` ### has @@ -115,6 +177,7 @@ Returns `true` if the key exists in the cache, `false` otherwise. ```ts const hasProducts = await bento.has('products'); +const hasProducts = await bento.has({ key: 'products' }) ``` ### missing @@ -123,6 +186,7 @@ Returns `true` if the key does not exist in the cache, `false` otherwise. ```ts const missingProducts = await bento.missing('products'); +const missingProducts = await bento.missing({ key: 'products' }) ``` ### pull @@ -131,6 +195,7 @@ Get the value of the key, and then delete it from the cache. Returns `undefined` ```ts const products = await bento.pull('products'); +const products = await bento.pull({ key: 'products' }) ``` ### delete @@ -139,6 +204,7 @@ Delete a key from the cache. ```ts await bento.delete('products'); +await bento.delete({ key: 'products' }) ``` ### deleteMany @@ -147,6 +213,7 @@ Delete multiple keys from the cache. ```ts await bento.deleteMany(['products', 'users']); +await bento.deleteMany({ keys: ['products', 'users'] }) ``` ### clear diff --git a/docs/content/docs/stampede_protection.md b/docs/content/docs/stampede_protection.md index 0219476..c71d272 100644 --- a/docs/content/docs/stampede_protection.md +++ b/docs/content/docs/stampede_protection.md @@ -14,11 +14,12 @@ Imagine this simple route that allows retrieving a post by its ID. ```ts router.get('/posts/:id', async (request) => { const { id } = request.params - const post = await bento.getOrSet( - `post:${id}`, - () => getPostFromDb(id), - { ttl: '1h' } - ) + + const post = await bento.getOrSet({ + key: `post:${id}`, + ttl: '1h', + factory: () => getPostFromDb(id), + }) return user }) diff --git a/docs/content/docs/walkthrough.md b/docs/content/docs/walkthrough.md index 4711254..5e797f7 100644 --- a/docs/content/docs/walkthrough.md +++ b/docs/content/docs/walkthrough.md @@ -47,11 +47,11 @@ const bento = new BentoCache({ router.get('/products/:id', async (req, res) => { const productId = req.params.id - const product = await bento.getOrSet( - `product:${productId}`, - () => Product.find(productId), - { ttl: '1m' } - ) + const product = await bento.getOrSet({ + key: `product:${productId}`, + ttl: '1m', + factory: () => Product.find(productId), + }) res.json(product) }) @@ -135,11 +135,11 @@ const bento = new BentoCache({ router.get('/products/:id', async (req, res) => { const productId = req.params.id - const product = await bento.getOrSet( - `product:${productId}`, - () => Product.find(productId), - { ttl: '1m' } - ) + const product = await bento.getOrSet({ + key: `product:${productId}`, + ttl: '1m', + factory: () => Product.find(productId), + }) res.json(product) }) @@ -207,11 +207,11 @@ const bento = new BentoCache({ router.get('/products/:id', async (req, res) => { const productId = req.params.id - const product = await bento.getOrSet( - `product:${productId}`, - () => Product.find(productId), - { ttl: '1m' } - ) + const product = await bento.getOrSet({ + key: `product:${productId}`, + ttl: '1m', + factory: () => Product.find(productId), + }) res.json(product) }) @@ -258,11 +258,11 @@ const bento = new BentoCache({ router.get('/products/:id', async (req, res) => { const productId = req.params.id - const product = await bento.getOrSet( - `product:${productId}`, - () => Product.find(productId), - { ttl: '1m' } - ) + const product = await bento.getOrSet({ + key: `product:${productId}`, + ttl: '1m', + factory: () => Product.find(productId), + }) res.json(product) }) diff --git a/packages/bentocache/tests/cache/one_tier_local.spec.ts b/packages/bentocache/tests/cache/one_tier_local.spec.ts index 97938d8..f781028 100644 --- a/packages/bentocache/tests/cache/one_tier_local.spec.ts +++ b/packages/bentocache/tests/cache/one_tier_local.spec.ts @@ -600,14 +600,14 @@ test.group('One tier tests', () => { test('adaptive caching', async ({ assert }) => { const { cache, local, stack } = new CacheFactory().withMemoryL1().merge({ ttl: '10m' }).create() - await cache.getOrSet( - 'key1', - (options) => { + await cache.getOrSet({ + key: 'key1', + ttl: '4m', + factory: (options) => { options.setTtl('2d') return { foo: 'bar' } }, - { ttl: '4m' }, - ) + }) const res = local.get('key1', stack.defaultOptions)! const logicalExpiration = res.getLogicalExpiration()