@@ -29,6 +29,7 @@ type Entry[V ~[]E, E any] struct {
2929
3030 dirty atomic.Bool
3131 full atomic.Bool
32+ count atomic.Uint64 // track number of entries only if max > 0
3233
3334 max uint
3435
@@ -122,6 +123,15 @@ func (e *Entry[V, E]) setEntryUnsafe(ctx context.Context, cdc codec.BinaryCodec,
122123 store := e .storeService .OpenMemoryStore (ctx )
123124 storeKey := e .getStoreKey (key )
124125
126+ exists := false
127+ if e .max > 0 {
128+ existingBz , err := store .Get (storeKey )
129+ if err != nil {
130+ return err
131+ }
132+ exists = existingBz != nil
133+ }
134+
125135 bz , err := marshal (cdc , e .cacheType , value )
126136 if err != nil {
127137 return err
@@ -131,12 +141,10 @@ func (e *Entry[V, E]) setEntryUnsafe(ctx context.Context, cdc codec.BinaryCodec,
131141 return err
132142 }
133143
134- if e .max > 0 {
135- count , err := e .countEntries (ctx )
136- if err != nil {
137- return err
138- }
139- if count >= e .max {
144+ // Only increment counter if this is a new key
145+ if e .max > 0 && ! exists {
146+ newCount := e .count .Add (1 )
147+ if newCount >= uint64 (e .max ) {
140148 e .full .Store (true )
141149 }
142150 }
@@ -151,16 +159,23 @@ func (e *Entry[V, E]) deleteEntry(ctx context.Context, key string) error {
151159 store := e .storeService .OpenMemoryStore (ctx )
152160 storeKey := e .getStoreKey (key )
153161
154- if err := store .Delete (storeKey ); err != nil {
155- return err
156- }
157-
162+ exists := false
158163 if e .max > 0 {
159- count , err := e . countEntries ( ctx )
164+ existingBz , err := store . Get ( storeKey )
160165 if err != nil {
161166 return err
162167 }
163- if count < e .max {
168+ exists = existingBz != nil
169+ }
170+
171+ if err := store .Delete (storeKey ); err != nil {
172+ return err
173+ }
174+
175+ // Only decrement counter if the key actually existed
176+ if e .max > 0 && exists {
177+ newCount := e .count .Add (^ uint64 (0 )) // Subtract 1 using two's complement
178+ if newCount < uint64 (e .max ) {
164179 e .full .Store (false )
165180 }
166181 }
@@ -184,27 +199,11 @@ func (e *Entry[V, E]) clearUnsafe(ctx context.Context) error {
184199 }
185200 }
186201
202+ e .count .Store (0 )
187203 e .full .Store (false )
188204 return nil
189205}
190206
191- func (e * Entry [V , E ]) countEntries (ctx context.Context ) (uint , error ) {
192- store := e .storeService .OpenMemoryStore (ctx )
193- prefix := e .getPrefix ()
194- iter , err := store .Iterator (prefix , storetypes .PrefixEndBytes (prefix ))
195- if err != nil {
196- return 0 , err
197- }
198- defer iter .Close ()
199-
200- count := uint (0 )
201- for ; iter .Valid (); iter .Next () {
202- count ++
203- }
204-
205- return count , nil
206- }
207-
208207func (e * Entry [V , E ]) getStoreKey (key string ) []byte {
209208 prefix := e .getPrefix ()
210209 return append (prefix , []byte (key )... )
@@ -316,34 +315,29 @@ func NewCache(
316315// Unbonding Validators Queue
317316
318317func (c * ValidatorsQueueCache ) checkReloadUnbondingValidatorsQueue (ctx context.Context ) error {
318+ c .unbondingValidatorsQueue .mu .Lock ()
319+ defer c .unbondingValidatorsQueue .mu .Unlock ()
320+
319321 if c .unbondingValidatorsQueue .dirty .Load () {
320322 c .logger (ctx ).Info ("Unbonding validators queue is dirty. Reinitializing cache from store." )
321- if err := c .loadUnbondingValidatorsQueue (ctx ); err != nil {
323+ data , err := c .unbondingValidatorsQueue .loadFromStore (ctx )
324+ if err != nil {
322325 return err
323326 }
324- }
325- return nil
326- }
327327
328- func (c * ValidatorsQueueCache ) loadUnbondingValidatorsQueue (ctx context.Context ) error {
329- data , err := c .unbondingValidatorsQueue .loadFromStore (ctx )
330- if err != nil {
331- return err
332- }
333- c .unbondingValidatorsQueue .mu .Lock ()
334- defer c .unbondingValidatorsQueue .mu .Unlock ()
335-
336- if err := c .unbondingValidatorsQueue .clearUnsafe (ctx ); err != nil {
337- return err
338- }
339-
340- for key , value := range data {
341- if err := c .unbondingValidatorsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
328+ if err := c .unbondingValidatorsQueue .clearUnsafe (ctx ); err != nil {
342329 return err
343330 }
331+
332+ for key , value := range data {
333+ if err := c .unbondingValidatorsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
334+ return err
335+ }
336+ }
337+
338+ c .unbondingValidatorsQueue .dirty .Store (false )
344339 }
345340
346- c .unbondingValidatorsQueue .dirty .Store (false )
347341 return nil
348342}
349343
@@ -382,35 +376,28 @@ func (c *ValidatorsQueueCache) DeleteUnbondingValidatorQueueEntry(ctx context.Co
382376// Unbonding Delegations
383377
384378func (c * ValidatorsQueueCache ) checkReloadUnbondingDelegationsQueue (ctx context.Context ) error {
379+ c .unbondingDelegationsQueue .mu .Lock ()
380+ defer c .unbondingDelegationsQueue .mu .Unlock ()
381+
385382 if c .unbondingDelegationsQueue .dirty .Load () {
386383 c .logger (ctx ).Info ("Unbonding delegations queue is dirty. Reinitializing cache from store." )
387- if err := c .loadUnbondingDelegationsQueue (ctx ); err != nil {
384+
385+ data , err := c .unbondingDelegationsQueue .loadFromStore (ctx )
386+ if err != nil {
388387 return err
389388 }
390- }
391- return nil
392- }
393389
394- func (c * ValidatorsQueueCache ) loadUnbondingDelegationsQueue (ctx context.Context ) error {
395- data , err := c .unbondingDelegationsQueue .loadFromStore (ctx )
396- if err != nil {
397- return err
398- }
399-
400- c .unbondingDelegationsQueue .mu .Lock ()
401- defer c .unbondingDelegationsQueue .mu .Unlock ()
402-
403- if err := c .unbondingDelegationsQueue .clearUnsafe (ctx ); err != nil {
404- return err
405- }
406-
407- for key , value := range data {
408- if err := c .unbondingDelegationsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
390+ if err := c .unbondingDelegationsQueue .clearUnsafe (ctx ); err != nil {
409391 return err
410392 }
411- }
412393
413- c .unbondingDelegationsQueue .dirty .Store (false )
394+ for key , value := range data {
395+ if err := c .unbondingDelegationsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
396+ return err
397+ }
398+ }
399+ c .unbondingDelegationsQueue .dirty .Store (false )
400+ }
414401 return nil
415402}
416403
@@ -449,35 +436,28 @@ func (c *ValidatorsQueueCache) DeleteUnbondingDelegationQueueEntry(ctx context.C
449436// Redelegations Queue
450437
451438func (c * ValidatorsQueueCache ) checkReloadRedelegationsQueue (ctx context.Context ) error {
439+ c .redelegationsQueue .mu .Lock ()
440+ defer c .redelegationsQueue .mu .Unlock ()
441+
452442 if c .redelegationsQueue .dirty .Load () {
453443 c .logger (ctx ).Info ("Redelegations queue is dirty. Reinitializing cache from store." )
454- if err := c .loadRedelegationsQueue (ctx ); err != nil {
444+ data , err := c .redelegationsQueue .loadFromStore (ctx )
445+ if err != nil {
455446 return err
456447 }
457- }
458- return nil
459- }
460448
461- func (c * ValidatorsQueueCache ) loadRedelegationsQueue (ctx context.Context ) error {
462- data , err := c .redelegationsQueue .loadFromStore (ctx )
463- if err != nil {
464- return err
465- }
466-
467- c .redelegationsQueue .mu .Lock ()
468- defer c .redelegationsQueue .mu .Unlock ()
469-
470- if err := c .redelegationsQueue .clearUnsafe (ctx ); err != nil {
471- return err
472- }
473-
474- for key , value := range data {
475- if err := c .redelegationsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
449+ if err := c .redelegationsQueue .clearUnsafe (ctx ); err != nil {
476450 return err
477451 }
478- }
479452
480- c .redelegationsQueue .dirty .Store (false )
453+ for key , value := range data {
454+ if err := c .redelegationsQueue .setEntryUnsafe (ctx , c .cdc , key , value ); err != nil {
455+ return err
456+ }
457+ }
458+
459+ c .redelegationsQueue .dirty .Store (false )
460+ }
481461 return nil
482462}
483463
0 commit comments