@@ -31,6 +31,9 @@ class OnyxCache {
3131 /** A map of cached values */
3232 private storageMap : Record < OnyxKey , OnyxValue < OnyxKey > > ;
3333
34+ /** A map of cached collection values for faster access */
35+ private collectionMap : Record < OnyxKey , Record < OnyxKey , OnyxValue < OnyxKey > > > ;
36+
3437 /**
3538 * Captured pending tasks for already running storage methods
3639 * Using a map yields better performance on operations such a delete
@@ -49,11 +52,15 @@ class OnyxCache {
4952 /** List of keys that have been directly subscribed to or recently modified from least to most recent */
5053 private recentlyAccessedKeys : OnyxKey [ ] = [ ] ;
5154
55+ /** Set of collection keys for fast lookup */
56+ private collectionKeys = new Set < OnyxKey > ( ) ;
57+
5258 constructor ( ) {
5359 this . storageKeys = new Set ( ) ;
5460 this . nullishStorageKeys = new Set ( ) ;
5561 this . recentKeys = new Set ( ) ;
5662 this . storageMap = { } ;
63+ this . collectionMap = { } ;
5764 this . pendingPromises = new Map ( ) ;
5865
5966 // bind all public methods to prevent problems with `this`
@@ -83,6 +90,10 @@ class OnyxCache {
8390 'addLastAccessedKey' ,
8491 'addEvictableKeysToRecentlyAccessedList' ,
8592 'getKeyForEviction' ,
93+ 'setCollectionKeys' ,
94+ 'isCollectionKey' ,
95+ 'getCollectionKey' ,
96+ 'getCollectionData' ,
8697 ) ;
8798 }
8899
@@ -130,6 +141,17 @@ class OnyxCache {
130141
131142 /** Check whether cache has data for the given key */
132143 hasCacheForKey ( key : OnyxKey ) : boolean {
144+ // Check if this is a collection key
145+ if ( this . isCollectionKey ( key ) ) {
146+ return this . collectionMap [ key ] !== undefined ;
147+ }
148+
149+ // Check if this is a collection member key
150+ const collectionKey = this . getCollectionKey ( key ) ;
151+ if ( collectionKey ) {
152+ return ( this . collectionMap [ collectionKey ] && this . collectionMap [ collectionKey ] [ key ] !== undefined ) || this . hasNullishStorageKey ( key ) ;
153+ }
154+
133155 return this . storageMap [ key ] !== undefined || this . hasNullishStorageKey ( key ) ;
134156 }
135157
@@ -141,6 +163,18 @@ class OnyxCache {
141163 if ( shouldReindexCache ) {
142164 this . addToAccessedKeys ( key ) ;
143165 }
166+
167+ // Check if this is a collection key request
168+ if ( this . isCollectionKey ( key ) ) {
169+ return this . collectionMap [ key ] ;
170+ }
171+
172+ // Check if this is a collection member key
173+ const collectionKey = this . getCollectionKey ( key ) ;
174+ if ( collectionKey && this . collectionMap [ collectionKey ] ) {
175+ return this . collectionMap [ collectionKey ] [ key ] ;
176+ }
177+
144178 return this . storageMap [ key ] ;
145179 }
146180
@@ -157,18 +191,47 @@ class OnyxCache {
157191 this . nullishStorageKeys . delete ( key ) ;
158192
159193 if ( value === null || value === undefined ) {
160- delete this . storageMap [ key ] ;
194+ // Handle deletion for collection keys
195+ const collectionKey = this . getCollectionKey ( key ) ;
196+ if ( collectionKey && this . collectionMap [ collectionKey ] ) {
197+ delete this . collectionMap [ collectionKey ] [ key ] ;
198+ } else {
199+ delete this . storageMap [ key ] ;
200+ }
161201 return undefined ;
162202 }
163203
164- this . storageMap [ key ] = value ;
204+ // Check if this is a collection member key
205+ const collectionKey = this . getCollectionKey ( key ) ;
206+ if ( collectionKey ) {
207+ // Initialize collection if it doesn't exist
208+ if ( ! this . collectionMap [ collectionKey ] ) {
209+ this . collectionMap [ collectionKey ] = { } ;
210+ }
211+ this . collectionMap [ collectionKey ] [ key ] = value ;
212+ } else {
213+ // Regular key or collection key itself
214+ this . storageMap [ key ] = value ;
215+ }
165216
166217 return value ;
167218 }
168219
169220 /** Forget the cached value for the given key */
170221 drop ( key : OnyxKey ) : void {
171- delete this . storageMap [ key ] ;
222+ // Check if this is a collection key - drop entire collection
223+ if ( this . isCollectionKey ( key ) ) {
224+ delete this . collectionMap [ key ] ;
225+ } else {
226+ // Check if this is a collection member key
227+ const collectionKey = this . getCollectionKey ( key ) ;
228+ if ( collectionKey && this . collectionMap [ collectionKey ] ) {
229+ delete this . collectionMap [ collectionKey ] [ key ] ;
230+ } else {
231+ delete this . storageMap [ key ] ;
232+ }
233+ }
234+
172235 this . storageKeys . delete ( key ) ;
173236 this . recentKeys . delete ( key ) ;
174237 }
@@ -182,7 +245,32 @@ class OnyxCache {
182245 throw new Error ( 'data passed to cache.merge() must be an Object of onyx key/value pairs' ) ;
183246 }
184247
185- this . storageMap = { ...utils . fastMerge ( this . storageMap , data ) } ;
248+ // Separate collection keys from regular keys
249+ const collectionData : Record < OnyxKey , Record < OnyxKey , OnyxValue < OnyxKey > > > = { } ;
250+ const regularData : Record < OnyxKey , OnyxValue < OnyxKey > > = { } ;
251+
252+ Object . entries ( data ) . forEach ( ( [ key , value ] ) => {
253+ const collectionKey = this . getCollectionKey ( key ) ;
254+ if ( collectionKey ) {
255+ if ( ! collectionData [ collectionKey ] ) {
256+ collectionData [ collectionKey ] = { } ;
257+ }
258+ collectionData [ collectionKey ] [ key ] = value ;
259+ } else {
260+ regularData [ key ] = value ;
261+ }
262+ } ) ;
263+
264+ // Merge regular data
265+ this . storageMap = { ...utils . fastMerge ( this . storageMap , regularData ) } ;
266+
267+ // Merge collection data
268+ Object . entries ( collectionData ) . forEach ( ( [ collectionKey , memberData ] ) => {
269+ if ( ! this . collectionMap [ collectionKey ] ) {
270+ this . collectionMap [ collectionKey ] = { } ;
271+ }
272+ this . collectionMap [ collectionKey ] = { ...utils . fastMerge ( this . collectionMap [ collectionKey ] , memberData ) } ;
273+ } ) ;
186274
187275 Object . entries ( data ) . forEach ( ( [ key , value ] ) => {
188276 this . addKey ( key ) ;
@@ -260,7 +348,13 @@ class OnyxCache {
260348 }
261349
262350 for ( const key of keysToRemove ) {
263- delete this . storageMap [ key ] ;
351+ // Check if this is a collection member key
352+ const collectionKey = this . getCollectionKey ( key ) ;
353+ if ( collectionKey && this . collectionMap [ collectionKey ] ) {
354+ delete this . collectionMap [ collectionKey ] [ key ] ;
355+ } else {
356+ delete this . storageMap [ key ] ;
357+ }
264358 this . recentKeys . delete ( key ) ;
265359 }
266360 }
@@ -272,7 +366,8 @@ class OnyxCache {
272366
273367 /** Check if the value has changed */
274368 hasValueChanged ( key : OnyxKey , value : OnyxValue < OnyxKey > ) : boolean {
275- return ! deepEqual ( this . storageMap [ key ] , value ) ;
369+ const currentValue = this . get ( key , false ) ;
370+ return ! deepEqual ( currentValue , value ) ;
276371 }
277372
278373 /**
@@ -358,6 +453,47 @@ class OnyxCache {
358453 getKeyForEviction ( ) : OnyxKey | undefined {
359454 return this . recentlyAccessedKeys . find ( ( key ) => ! this . evictionBlocklist [ key ] ) ;
360455 }
456+
457+ /**
458+ * Set the collection keys for optimized storage
459+ */
460+ setCollectionKeys ( collectionKeys : Set < OnyxKey > ) : void {
461+ this . collectionKeys = collectionKeys ;
462+ // Initialize collection maps for existing collection keys
463+ collectionKeys . forEach ( ( collectionKey ) => {
464+ if ( this . collectionMap [ collectionKey ] ) {
465+ return ;
466+ }
467+
468+ this . collectionMap [ collectionKey ] = { } ;
469+ } ) ;
470+ }
471+
472+ /**
473+ * Check if a key is a collection key
474+ */
475+ isCollectionKey ( key : OnyxKey ) : boolean {
476+ return this . collectionKeys . has ( key ) ;
477+ }
478+
479+ /**
480+ * Get the collection key for a given member key
481+ */
482+ getCollectionKey ( key : OnyxKey ) : OnyxKey | null {
483+ for ( const collectionKey of this . collectionKeys ) {
484+ if ( key . startsWith ( collectionKey ) && key . length > collectionKey . length ) {
485+ return collectionKey ;
486+ }
487+ }
488+ return null ;
489+ }
490+
491+ /**
492+ * Get all data for a collection key
493+ */
494+ getCollectionData ( collectionKey : OnyxKey ) : Record < OnyxKey , OnyxValue < OnyxKey > > | undefined {
495+ return this . collectionMap [ collectionKey ] ;
496+ }
361497}
362498
363499const instance = new OnyxCache ( ) ;
0 commit comments