@@ -20,26 +20,18 @@ import { Test } from "./components/Test";
2020
2121// For demonstration/testing purposes.
2222// Do *not* store cacheKey to localStorage in production.
23- let cacheKey : string = localStorage . cacheKey ;
24- if ( ! cacheKey ) {
25- cacheKey = crypto . randomUUID ( ) ;
26- localStorage . cacheKey = cacheKey ;
23+ let initialCacheKey : string = localStorage . cacheKey ;
24+ if ( ! initialCacheKey ) {
25+ initialCacheKey = crypto . randomUUID ( ) ;
26+ localStorage . cacheKey = initialCacheKey ;
2727}
2828
29- let cacheBuster : string = localStorage . cacheBuster ;
30- if ( ! cacheBuster ) {
31- cacheBuster = crypto . randomUUID ( ) ;
32- localStorage . cacheBuster = cacheBuster ;
29+ let initialCacheBuster : string = localStorage . cacheBuster ;
30+ if ( ! initialCacheBuster ) {
31+ initialCacheBuster = crypto . randomUUID ( ) ;
32+ localStorage . cacheBuster = initialCacheBuster ;
3333}
3434
35- const cache = new IDBCache ( {
36- cacheKey,
37- cacheBuster,
38- debug : true ,
39- } ) ;
40- // @ts -expect-error
41- window . idbCacheInstance = cache ;
42-
4335const DEFAULT_NUM_ITEMS = 1 ;
4436
4537// Default item size set to 32KB
@@ -72,9 +64,14 @@ const App = () => {
7264 const [ chunkSize , setChunkSize ] = useState < number > ( DEFAULT_CHUNK_SIZE ) ;
7365 const [ itemCount , setItemCount ] = useState < number | null > ( null ) ;
7466 const [ maxTotalChunksStored , setMaxTotalChunksStored ] = useState < number > (
75- DEAFULT_MAX_CHUNKS_STORED ,
67+ ( ) => {
68+ const stored = localStorage . getItem ( "maxTotalChunksStored" ) ;
69+ return stored ? Number . parseInt ( stored , 10 ) : DEAFULT_MAX_CHUNKS_STORED ;
70+ } ,
7671 ) ;
7772
73+ const [ cacheReady , setCacheReady ] = useState < boolean > ( false ) ;
74+
7875 useEffect ( ( ) => {
7976 const params = new URLSearchParams ( window . location . hash . slice ( 1 ) ) ;
8077 params . set ( "size" , String ( Math . round ( itemSize / 1024 ) ) ) ;
@@ -88,7 +85,69 @@ const App = () => {
8885 deterministicHash ( `seed-${ keyCounter . current } ` ) ,
8986 ) ;
9087
88+ const cacheRef = useRef < IDBCache | null > ( null ) ;
89+
90+ useEffect ( ( ) => {
91+ let isCancelled = false ;
92+
93+ const initializeCache = async ( ) => {
94+ if ( cacheRef . current ) {
95+ setCacheReady ( false ) ;
96+ try {
97+ await cacheRef . current . destroy ( ) ;
98+ } catch ( error ) {
99+ console . error ( "Error destroying previous cache:" , error ) ;
100+ }
101+ }
102+
103+ try {
104+ const newCache = new IDBCache ( {
105+ cacheKey : initialCacheKey ,
106+ cacheBuster : initialCacheBuster ,
107+ debug : true ,
108+ chunkSize : chunkSize ,
109+ maxTotalChunks : maxTotalChunksStored ,
110+ } ) ;
111+
112+ if ( ! isCancelled ) {
113+ cacheRef . current = newCache ;
114+ setCacheReady ( true ) ;
115+ } else {
116+ await newCache . destroy ( ) ;
117+ }
118+ } catch ( error ) {
119+ console . error ( "Error initializing cache:" , error ) ;
120+ if ( ! isCancelled ) {
121+ setCacheReady ( false ) ;
122+ }
123+ }
124+ } ;
125+
126+ initializeCache ( ) ;
127+
128+ return ( ) => {
129+ isCancelled = true ;
130+ if ( cacheRef . current ) {
131+ cacheRef . current . destroy ( ) . catch ( ( error ) => {
132+ console . error ( "Error destroying cache on cleanup:" , error ) ;
133+ } ) ;
134+ cacheRef . current = null ;
135+ setCacheReady ( false ) ;
136+ }
137+ } ;
138+ } , [ chunkSize , maxTotalChunksStored ] ) ;
139+
140+ useEffect ( ( ) => {
141+ localStorage . setItem ( "maxTotalChunksStored" , String ( maxTotalChunksStored ) ) ;
142+ } , [ maxTotalChunksStored ] ) ;
143+
91144 const encryptAndStore = useCallback ( async ( ) => {
145+ const cache = cacheRef . current ;
146+ if ( ! cache ) {
147+ console . error ( "Cache is not initialized." ) ;
148+ return ;
149+ }
150+
92151 const key = deterministicHash ( `seed-${ keyCounter . current } ` ) ;
93152 localStorage . setItem ( "keyCounter" , String ( keyCounter . current ) ) ;
94153 keyCounter . current += 1 ;
@@ -114,6 +173,12 @@ const App = () => {
114173 } , [ itemSize ] ) ;
115174
116175 const retrieveAndDecrypt = useCallback ( async ( ) => {
176+ const cache = cacheRef . current ;
177+ if ( ! cache ) {
178+ console . error ( "Cache is not initialized." ) ;
179+ return ;
180+ }
181+
117182 const results : Array < string | null > = [ ] ;
118183 const start = performance . now ( ) ;
119184
@@ -132,6 +197,12 @@ const App = () => {
132197 } , [ contentKey ] ) ;
133198
134199 const count = useCallback ( async ( ) => {
200+ const cache = cacheRef . current ;
201+ if ( ! cache ) {
202+ console . error ( "Cache is not initialized." ) ;
203+ return ;
204+ }
205+
135206 const start = performance . now ( ) ;
136207 const count = await cache . count ( ) ;
137208 const end = performance . now ( ) ;
@@ -140,6 +211,12 @@ const App = () => {
140211 } , [ ] ) ;
141212
142213 const clear = useCallback ( async ( ) => {
214+ const cache = cacheRef . current ;
215+ if ( ! cache ) {
216+ console . error ( "Cache is not initialized." ) ;
217+ return ;
218+ }
219+
143220 const start = performance . now ( ) ;
144221 await cache . clear ( ) ;
145222 localStorage . removeItem ( "keyCounter" ) ;
@@ -166,10 +243,10 @@ const App = () => {
166243 < form >
167244 < WrappedFlexContainer >
168245 < WrappedFlexItem >
169- < CacheKey cacheKey = { cacheKey } />
246+ < CacheKey cacheKey = { initialCacheKey } />
170247 </ WrappedFlexItem >
171248 < WrappedFlexItem >
172- < CacheBuster cacheBuster = { cacheBuster } />
249+ < CacheBuster cacheBuster = { initialCacheBuster } />
173250 </ WrappedFlexItem >
174251
175252 < WrappedFlexItem >
@@ -196,7 +273,7 @@ const App = () => {
196273 < NumberInput
197274 renderLabel = "Chunks per item:"
198275 interaction = "disabled"
199- value = { Math . ceil ( itemSize / 25000 ) }
276+ value = { Math . ceil ( itemSize / chunkSize ) }
200277 />
201278 </ WrappedFlexItem >
202279
@@ -244,68 +321,61 @@ const App = () => {
244321 </ Heading >
245322
246323 { /* setItem Performance */ }
247- < View
248- as = "div"
249- display = "block"
250- margin = "small none"
251- padding = "medium"
252- background = "primary"
253- shadow = "resting"
254- >
255- < Flex direction = "column" >
256- < Button
257- data-testid = "set-item-button"
258- color = "primary"
259- onClick = { encryptAndStore }
260- >
261- setItem
262- </ Button >
263- < View padding = "medium 0 0 0" >
264- < Flex >
265- < Flex . Item size = "33.3%" >
266- < Metric
267- renderLabel = "fixtures"
268- data-testid = "generate-time"
269- renderValue = {
270- timeToGenerate !== null ? (
271- `${ Math . round ( timeToGenerate ) } ms`
272- ) : (
273- < BlankStat />
274- )
275- }
276- />
277- </ Flex . Item >
278- < Flex . Item shouldGrow >
279- < Metric
280- renderLabel = "setItem"
281- data-testid = "set-time"
282- renderValue = {
283- setTime !== null ? (
284- `${ Math . round ( setTime ) } ms`
285- ) : (
286- < BlankStat />
287- )
288- }
289- />
290- </ Flex . Item >
291- < Flex . Item size = "33.3%" >
292- < Metric
293- data-testid = "hash1"
294- renderLabel = "hash"
295- renderValue = { hash1 || < BlankStat /> }
296- />
297- </ Flex . Item >
298- </ Flex >
299- </ View >
300- </ Flex >
301- </ View >
324+ < Test >
325+ < Button
326+ data-testid = "set-item-button"
327+ color = "primary"
328+ onClick = { encryptAndStore }
329+ disabled = { ! cacheReady }
330+ >
331+ setItem
332+ </ Button >
333+ < View padding = "medium 0 0 0" >
334+ < Flex >
335+ < Flex . Item size = "33.3%" >
336+ < Metric
337+ renderLabel = "fixtures"
338+ data-testid = "generate-time"
339+ renderValue = {
340+ timeToGenerate !== null ? (
341+ `${ Math . round ( timeToGenerate ) } ms`
342+ ) : (
343+ < BlankStat />
344+ )
345+ }
346+ />
347+ </ Flex . Item >
348+ < Flex . Item shouldGrow >
349+ < Metric
350+ renderLabel = "setItem"
351+ data-testid = "set-time"
352+ renderValue = {
353+ setTime !== null ? (
354+ `${ Math . round ( setTime ) } ms`
355+ ) : (
356+ < BlankStat />
357+ )
358+ }
359+ />
360+ </ Flex . Item >
361+ < Flex . Item size = "33.3%" >
362+ < Metric
363+ data-testid = "hash1"
364+ renderLabel = "hash"
365+ renderValue = { hash1 || < BlankStat /> }
366+ />
367+ </ Flex . Item >
368+ </ Flex >
369+ </ View >
370+ </ Test >
302371
303372 { /* getItem Performance */ }
304373 < Test >
305374 < Button
306375 data-testid = "get-item-button"
307376 color = "primary"
308377 onClick = { retrieveAndDecrypt }
378+ disabled = { ! cacheReady }
309379 >
310380 getItem
311381 </ Button >
@@ -343,6 +413,7 @@ const App = () => {
343413 data-testid = "count-button"
344414 color = "primary"
345415 onClick = { count }
416+ disabled = { ! cacheReady }
346417 >
347418 count
348419 </ Button >
@@ -352,8 +423,8 @@ const App = () => {
352423 < Flex . Item size = "33.3%" > </ Flex . Item >
353424 < Flex . Item shouldGrow >
354425 < Metric
355- data-testid = "count-time"
356426 renderLabel = "count"
427+ data-testid = "count-time"
357428 renderValue = {
358429 countTime !== null ? (
359430 `${ Math . round ( countTime ) } ms`
@@ -386,6 +457,7 @@ const App = () => {
386457 data-testid = "clear-button"
387458 color = "primary"
388459 onClick = { clear }
460+ disabled = { ! cacheReady }
389461 >
390462 clear
391463 </ Button >
0 commit comments