@@ -60,6 +60,21 @@ async function readStored(keys: string[]): Promise<(string | null)[]> {
6060 }
6161}
6262
63+ /**
64+ * A stored value, or `undefined` for a miss. An entry that does not parse — written by
65+ * an older shape, or corrupted — is a miss too: the ledger answers instead of a failed
66+ * page, and the fresh value overwrites it.
67+ */
68+ function parseStored < T > ( key : string , value : string | null | undefined ) : T | undefined {
69+ if ( value == null ) return undefined
70+ try {
71+ return JSON . parse ( value ) as T
72+ } catch ( error ) {
73+ logger . warn ( 'Discarding unreadable usage segment' , { key, error : getErrorMessage ( error ) } )
74+ return undefined
75+ }
76+ }
77+
6378/** Fire-and-forget: a page never waits on, or fails because of, a cache write. */
6479function writeStored ( entries : { key : string ; value : string ; ttlMs : number } [ ] ) : void {
6580 if ( entries . length === 0 ) return
@@ -141,14 +156,16 @@ export async function readThroughSegments<T>({
141156 const writes : { key : string ; value : string ; ttlMs : number } [ ] = [ ]
142157 const cached = new Map < UsageSegment , T > ( )
143158 settled . forEach ( ( segment , index ) => {
144- const value = stored [ index ]
145- if ( value != null ) cached . set ( segment , JSON . parse ( value ) as T )
159+ const value = parseStored < T > ( keyOf ( segment . key ) , stored [ index ] )
160+ if ( value !== undefined ) cached . set ( segment , value )
146161 } )
147162 assemblable . forEach ( ( segment , index ) => {
148163 if ( cached . has ( segment ) ) return
149- const hours = storedHours . slice ( index * 24 , index * 24 + 24 )
150- if ( hours . some ( ( hour ) => hour == null ) ) return
151- const value = combine ( hours . map ( ( hour ) => JSON . parse ( hour as string ) as T ) )
164+ const hours = storedHours
165+ . slice ( index * 24 , index * 24 + 24 )
166+ . map ( ( hour , offset ) => parseStored < T > ( keyOf ( usageHourKey ( segment . day , offset ) ) , hour ) )
167+ if ( hours . some ( ( hour ) => hour === undefined ) ) return
168+ const value = combine ( hours as T [ ] )
152169 cached . set ( segment , value )
153170 writes . push ( { key : keyOf ( segment . key ) , value : JSON . stringify ( value ) , ttlMs } )
154171 } )
0 commit comments