Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 25 additions & 2 deletions packages/bentocache/src/cache/cache_entry/cache_entry_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export function createCacheEntryOptions(
) {
const options = { ...defaults, ...newOptions }

const grace = resolveGrace(options)
const graceBackoff = resolveTtl(options.graceBackoff, null) ?? 0
let grace = resolveGrace(options)
let graceBackoff = resolveTtl(options.graceBackoff, null) ?? 0

let logicalTtl = resolveTtl(options.ttl)
let physicalTtl = grace > 0 ? grace : logicalTtl
Expand Down Expand Up @@ -132,6 +132,29 @@ export function createCacheEntryOptions(
return self
},

/**
* Set a new grace period
*/
setGrace(newGrace: false | Duration) {
options.grace = newGrace
grace = resolveGrace(options)
self.grace = grace
physicalTtl = self.isGraceEnabled() ? grace : logicalTtl

return self
},

/**
* Set a new grace backoff duration
*/
setGraceBackoff(newGraceBackoff: Duration) {
options.graceBackoff = newGraceBackoff
graceBackoff = resolveTtl(options.graceBackoff, null) ?? 0
self.graceBackoff = graceBackoff

return self
},

/**
* Compute the logical TTL timestamp from now
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/bentocache/src/cache/factory_runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ export class FactoryRunner {
setTags: (tags) => params.options.tags.push(...tags),
setOptions: (options) => {
if (options.ttl) params.options.setLogicalTtl(options.ttl)
if ('grace' in options) params.options.setGrace(options.grace ?? false)
if ('graceBackoff' in options) params.options.setGraceBackoff(options.graceBackoff ?? null)
params.options.skipBusNotify = options.skipBusNotify ?? false
params.options.skipL2Write = options.skipL2Write ?? false
},
Expand Down
8 changes: 7 additions & 1 deletion packages/bentocache/src/types/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ export type GetSetFactoryContext = {
/**
* Set the options for the current factory
*/
setOptions: (options: { ttl?: Duration; skipBusNotify?: boolean; skipL2Write?: boolean }) => void
setOptions: (options: {
ttl?: Duration
grace?: false | Duration
graceBackoff?: Duration
skipBusNotify?: boolean
skipL2Write?: boolean
}) => void

/**
* Set the tags for the current factory
Expand Down
17 changes: 17 additions & 0 deletions packages/bentocache/tests/cache/cache_entry_options.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,4 +115,21 @@ test.group('Cache Entry Options', () => {
assert.equal(options.getLogicalTtl(), ms.parse('5m'))
assert.equal(options.getPhysicalTtl(), ms.parse('5m'))
})

test('setGrace should re-compute physical ttl', ({ assert }) => {
const options = createCacheEntryOptions({ ttl: '10m' })

options.setGrace('30m')
assert.equal(options.getPhysicalTtl(), ms.parse('30m'))

options.setGrace(false)
assert.equal(options.getPhysicalTtl(), ms.parse('10m'))
})

test('setGraceBackoff should update grace backoff value', ({ assert }) => {
const options = createCacheEntryOptions({ graceBackoff: '10s' })

options.setGraceBackoff('25s')
assert.equal(options.graceBackoff, ms.parse('25s'))
})
})
41 changes: 41 additions & 0 deletions packages/bentocache/tests/cache/factory_context.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,45 @@ test.group('Factory Context', () => {

assert.deepEqual(r1, 'bar')
})

test('can set grace and graceBackoff with adaptive options', async ({ assert }) => {
const { cache } = new CacheFactory().withMemoryL1().merge({ timeout: '2s' }).create()

const r1 = await cache.getOrSet({
key: 'key1',
factory: (ctx) => {
ctx.setOptions({ ttl: 10, grace: '6h' })
return { foo: 'bar' }
},
})

await sleep(50)

const r2 = await cache.getOrSet({
key: 'key1',
factory: (ctx) => {
ctx.setOptions({ graceBackoff: '0.5s', grace: '6h' })
throw new Error('factory error')
},
})

let factoryCalledDuringBackoff = false
const r3 = await cache.getOrSet({
key: 'key1',
factory: () => {
factoryCalledDuringBackoff = true
throw new Error('should not be called')
},
})

await sleep(800)

const r4 = await cache.getOrSet({ key: 'key1', factory: () => ({ foo: 'baz' }) })

assert.deepEqual(r1, { foo: 'bar' })
assert.deepEqual(r2, { foo: 'bar' })
assert.deepEqual(r3, { foo: 'bar' })
assert.deepEqual(r4, { foo: 'baz' })
assert.isFalse(factoryCalledDuringBackoff)
})
})
8 changes: 8 additions & 0 deletions packages/bentocache/tests/typings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,11 +94,19 @@ test.group('Typings', () => {
ttl: 1000,
factory: () => 34,
})
const r5 = await cache.getOrSet({
key: 'key',
factory: (ctx) => {
ctx.setOptions({ ttl: '1m', grace: '2m', graceBackoff: '10s' })
return 99
},
})

expectTypeOf(r1).toEqualTypeOf<string>()
expectTypeOf(r2).toEqualTypeOf<number>()
expectTypeOf(r3).toEqualTypeOf<number>()
expectTypeOf(r4).toEqualTypeOf<number>()
expectTypeOf(r5).toEqualTypeOf<number>()
})

test('getOrSet() typings on bento', async ({ expectTypeOf }) => {
Expand Down