Skip to content

Commit 2facbd0

Browse files
committed
add context to status/tracing objects
1 parent 156eecd commit 2facbd0

File tree

4 files changed

+93
-12
lines changed

4 files changed

+93
-12
lines changed

src/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,18 @@ export namespace LRUCache {
267267
*/
268268
memo?: 'hit' | 'miss'
269269

270+
/**
271+
* The `context` option provided to a memo or fetch operation
272+
*
273+
* In practice, of course, this will be the same type as the `FC`
274+
* fetch context param used to instantiate the LRUCache, but the
275+
* convolutions of threading that through would get quite complicated,
276+
* and preclude forcing/forbidding the passing of a `context` param
277+
* where it is/isn't expected, which is more valuable for error
278+
* prevention.
279+
*/
280+
context?: unknown
281+
270282
/**
271283
* the ttl stored for the item, or undefined if ttls are not used.
272284
*/
@@ -2679,6 +2691,9 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
26792691
const ths = tracing.hasSubscribers
26802692
const { status = hasSubscribers() ? {} : undefined } = fetchOptions
26812693
fetchOptions.status = status
2694+
if (status && fetchOptions.context) {
2695+
status.context = fetchOptions.context
2696+
}
26822697
const p = this.#fetch(k, fetchOptions)
26832698
if (status && hasSubscribers()) {
26842699
if (ths) {
@@ -2825,6 +2840,9 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
28252840
const ths = tracing.hasSubscribers
28262841
const { status = hasSubscribers() ? {} : undefined } = fetchOptions
28272842
fetchOptions.status = status
2843+
if (status && fetchOptions.context) {
2844+
status.context = fetchOptions.context
2845+
}
28282846
const p = this.#forceFetch(k, fetchOptions)
28292847
if (status && hasSubscribers()) {
28302848
if (ths) {
@@ -2885,6 +2903,9 @@ export class LRUCache<K extends {}, V extends {}, FC = unknown> {
28852903
if (status) {
28862904
status.op = 'memo'
28872905
status.key = k
2906+
if (memoOptions.context) {
2907+
status.context = memoOptions.context
2908+
}
28882909
}
28892910
const result = this.#memo(k, memoOptions)
28902911
if (status) status.value = result

tap-snapshots/test/fetch.ts.test.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ Array [
316316
"op": "fetch",
317317
},
318318
Object {
319+
"context": true,
319320
"fetch": "refresh",
320321
"fetchDispatched": true,
321322
"fetchResolved": true,

tap-snapshots/test/tracing.ts.test.cjs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ Array [
10051005
"trace": true,
10061006
},
10071007
Object {
1008+
"context": true,
10081009
"fetch": "refresh",
10091010
"fetchDispatched": true,
10101011
"fetchResolved": true,
@@ -1234,6 +1235,7 @@ Array [
12341235
exports[`test/tracing.ts > TAP > test/tracing.ts > TAP > abort, but then keep on fetching anyway traces 1`] = `
12351236
Map {
12361237
Object {
1238+
"context": true,
12371239
"fetch": "miss",
12381240
"fetchAborted": true,
12391241
"fetchAbortIgnored": true,
@@ -1253,6 +1255,7 @@ Map {
12531255
"asyncEnd",
12541256
],
12551257
Object {
1258+
"context": true,
12561259
"fetch": "miss",
12571260
"fetchAborted": true,
12581261
"fetchAbortIgnored": true,
@@ -1269,6 +1272,7 @@ Map {
12691272
"asyncEnd",
12701273
],
12711274
Object {
1275+
"context": true,
12721276
"fetch": "miss",
12731277
"fetchAborted": true,
12741278
"fetchAbortIgnored": true,
@@ -1285,6 +1289,7 @@ Map {
12851289
"asyncEnd",
12861290
],
12871291
Object {
1292+
"context": true,
12881293
"fetch": "miss",
12891294
"fetchDispatched": true,
12901295
"fetchResolved": true,
@@ -1299,6 +1304,7 @@ Map {
12991304
"asyncEnd",
13001305
],
13011306
Object {
1307+
"context": true,
13021308
"error": Error: fetch() returned undefined {
13031309
"name": "Error",
13041310
},
@@ -3832,6 +3838,9 @@ Array []
38323838
exports[`test/tracing.ts > TAP > test/tracing.ts > TAP > fetch context required if set in ctor type traces 1`] = `
38333839
Map {
38343840
Object {
3841+
"context": Object {
3842+
"a": 1,
3843+
},
38353844
"fetch": "miss",
38363845
"fetchDispatched": true,
38373846
"key": "x",
@@ -3852,6 +3861,9 @@ Map {
38523861
"end",
38533862
],
38543863
Object {
3864+
"context": Object {
3865+
"x": 1,
3866+
},
38553867
"fetch": "miss",
38563868
"fetchDispatched": true,
38573869
"key": "z",
@@ -3862,6 +3874,9 @@ Map {
38623874
"end",
38633875
],
38643876
Object {
3877+
"context": Object {
3878+
"a": 1,
3879+
},
38653880
"fetch": "miss",
38663881
"fetchDispatched": true,
38673882
"key": "x",
@@ -3891,6 +3906,9 @@ Map {
38913906
"end",
38923907
],
38933908
Object {
3909+
"context": Object {
3910+
"x": 1,
3911+
},
38943912
"fetch": "miss",
38953913
"fetchDispatched": true,
38963914
"key": "z",
@@ -3906,6 +3924,7 @@ Map {
39063924
exports[`test/tracing.ts > TAP > test/tracing.ts > TAP > fetch context traces 1`] = `
39073925
Map {
39083926
Object {
3927+
"context": "overridden",
39093928
"fetch": "miss",
39103929
"fetchDispatched": true,
39113930
"fetchResolved": true,
@@ -3933,6 +3952,7 @@ Map {
39333952
"asyncEnd",
39343953
],
39353954
Object {
3955+
"context": "first context",
39363956
"fetch": "miss",
39373957
"fetchDispatched": true,
39383958
"fetchResolved": true,
@@ -3960,6 +3980,7 @@ Map {
39603980
"asyncEnd",
39613981
],
39623982
Object {
3983+
"context": "ignored",
39633984
"fetch": "hit",
39643985
"key": "x",
39653986
"now": 1092,
@@ -4596,12 +4617,14 @@ Array [
45964617
"value": 10,
45974618
},
45984619
Object {
4620+
"context": 8,
45994621
"key": "10",
46004622
"memo": "hit",
46014623
"op": "memo",
46024624
"value": 10,
46034625
},
46044626
Object {
4627+
"context": 8,
46054628
"forceRefresh": true,
46064629
"key": "10",
46074630
"memo": "miss",
@@ -4660,6 +4683,7 @@ Map {}
46604683
exports[`test/tracing.ts > TAP > test/tracing.ts > TAP > forceRefresh traces 2`] = `
46614684
Map {
46624685
Object {
4686+
"context": true,
46634687
"fetch": "hit",
46644688
"key": 1,
46654689
"now": 1092,
@@ -4773,6 +4797,7 @@ Map {
47734797
"asyncEnd",
47744798
],
47754799
Object {
4800+
"context": true,
47764801
"fetch": "refresh",
47774802
"fetchDispatched": true,
47784803
"fetchResolved": true,
@@ -4842,6 +4867,9 @@ Map {
48424867
"asyncEnd",
48434868
],
48444869
Object {
4870+
"context": Object {
4871+
"a": 1,
4872+
},
48454873
"fetch": "miss",
48464874
"fetchDispatched": true,
48474875
"fetchResolved": true,
@@ -4872,6 +4900,9 @@ Map {
48724900
"asyncEnd",
48734901
],
48744902
Object {
4903+
"context": Object {
4904+
"x": 1,
4905+
},
48754906
"fetch": "miss",
48764907
"fetchDispatched": true,
48774908
"fetchResolved": true,
@@ -4887,6 +4918,9 @@ Map {
48874918
"asyncEnd",
48884919
],
48894920
Object {
4921+
"context": Object {
4922+
"a": 1,
4923+
},
48904924
"fetch": "miss",
48914925
"fetchDispatched": true,
48924926
"fetchResolved": true,
@@ -4927,6 +4961,9 @@ Map {
49274961
"asyncEnd",
49284962
],
49294963
Object {
4964+
"context": Object {
4965+
"x": 1,
4966+
},
49304967
"fetch": "miss",
49314968
"fetchDispatched": true,
49324969
"fetchResolved": true,
@@ -10367,12 +10404,14 @@ Map {
1036710404
exports[`test/tracing.ts > TAP > test/tracing.ts > TAP > with context metrics 1`] = `
1036810405
Array [
1036910406
Object {
10407+
"context": true,
1037010408
"key": 1,
1037110409
"memo": "miss",
1037210410
"op": "memo",
1037310411
"value": 1,
1037410412
},
1037510413
Object {
10414+
"context": true,
1037610415
"key": 1,
1037710416
"memo": "hit",
1037810417
"op": "memo",
@@ -10391,6 +10430,7 @@ Array [
1039110430
"value": 4,
1039210431
},
1039310432
Object {
10433+
"context": true,
1039410434
"key": 2,
1039510435
"memo": "hit",
1039610436
"op": "memo",

test/fetch.ts

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ t.test('forceRefresh', async t => {
395395
return status
396396
}
397397

398-
const cache = new LRU<number, number>({
398+
const cache = new LRU<number, number, boolean>({
399399
max: 10,
400400
allowStale: true,
401401
ttl: 100,
@@ -413,33 +413,52 @@ t.test('forceRefresh', async t => {
413413
// put in some values that don't match what fetchMethod returns
414414
cache.set(1, 100)
415415
cache.set(2, 200)
416-
t.equal(await cache.fetch(1), 100)
416+
t.equal(await cache.fetch(1, { context: true }), 100)
417417
// still there, because we're allowing stale, and it's not stale
418418
const status: LRUCache.Status<number, number> = {}
419419
t.equal(
420420
await cache.fetch(2, {
421421
forceRefresh: true,
422422
allowStale: false,
423423
status,
424+
context: false,
424425
}),
425426
2,
426427
)
427428
t.equal(status.fetch, 'refresh', 'status reflects forced refresh')
428-
t.equal(await cache.fetch(1, { forceRefresh: true }), 100)
429+
t.equal(
430+
await cache.fetch(1, { forceRefresh: true, context: false }),
431+
100,
432+
)
429433
clock.advance(100)
430-
t.equal(await cache.fetch(2, { forceRefresh: true, status: s() }), 2)
434+
t.equal(
435+
await cache.fetch(2, {
436+
forceRefresh: true,
437+
status: s(),
438+
context: false,
439+
}),
440+
2,
441+
)
431442
t.equal(cache.peek(1), 100)
432443
// if we don't allow stale though, then that means that we wait
433444
// for the background fetch to complete, so we get the updated value.
434-
t.equal(await cache.fetch(1, { allowStale: false, status: s() }), 1)
445+
t.equal(
446+
await cache.fetch(1, {
447+
allowStale: false,
448+
context: false,
449+
status: s(),
450+
}),
451+
1,
452+
)
435453

436454
cache.set(1, 100)
437-
t.equal(await cache.fetch(1, { allowStale: false }), 100)
455+
t.equal(await cache.fetch(1, { allowStale: false, context: false }), 100)
438456
t.equal(
439457
await cache.fetch(1, {
440458
forceRefresh: true,
441459
allowStale: false,
442460
status: s(),
461+
context: true,
443462
}),
444463
1,
445464
)
@@ -599,7 +618,7 @@ t.test('abort, but then keep on fetching anyway', async t => {
599618
let aborted: Error | undefined = undefined
600619
let resolved: boolean = false
601620
let returnUndefined: boolean = false
602-
const cache = new LRU<number, number>({
621+
const cache = new LRU<number, number, boolean>({
603622
max: 10,
604623
ignoreFetchAbort: true,
605624
fetchMethod: async (k, _, { signal, options }) => {
@@ -618,7 +637,7 @@ t.test('abort, but then keep on fetching anyway', async t => {
618637
})
619638
const ac = new AbortController()
620639
const status: LRUCache.Status<number, number> = {}
621-
const p = cache.fetch(1, { signal: ac.signal, status })
640+
const p = cache.fetch(1, { signal: ac.signal, status, context: true })
622641
const er = new Error('ignored abort signal')
623642
ac.abort(er)
624643
clock.advance(100)
@@ -632,7 +651,7 @@ t.test('abort, but then keep on fetching anyway', async t => {
632651
t.equal(ac.signal.reason, er)
633652
t.equal(cache.get(1), 1)
634653

635-
const p2 = cache.forceFetch(2)
654+
const p2 = cache.forceFetch(2, { context: true })
636655
t.equal(cache.get(2), undefined)
637656
cache.delete(2)
638657
t.equal(cache.get(2), undefined)
@@ -641,7 +660,7 @@ t.test('abort, but then keep on fetching anyway', async t => {
641660
t.equal(cache.get(2), undefined)
642661

643662
// if aborted for cause, we don't save the fetched value
644-
const p3 = cache.fetch(3)
663+
const p3 = cache.fetch(3, { context: true })
645664
t.equal(cache.get(3), undefined)
646665
cache.set(3, 33)
647666
t.equal(cache.get(3), 33)
@@ -652,10 +671,10 @@ t.test('abort, but then keep on fetching anyway', async t => {
652671
const e = expose(cache)
653672
returnUndefined = true
654673
const before = e.valList.slice()
655-
const p4 = cache.fetch(4)
674+
const p4 = cache.fetch(4, { context: true })
656675
clock.advance(100)
657676
t.equal(await p4, undefined)
658-
const p5 = cache.forceFetch(4)
677+
const p5 = cache.forceFetch(4, { context: true })
659678
clock.advance(100)
660679
await t.rejects(p5, { message: 'fetch() returned undefined' })
661680
t.same(e.valList, before, 'did not update values with undefined')

0 commit comments

Comments
 (0)