@@ -63,6 +63,8 @@ func NewIndexedClient(
6363 name : cacheName ,
6464 cacheProvider : cacheProvider ,
6565 cancel : cancel ,
66+ forceFlush : make (chan bool ),
67+ hasFlushed : make (chan bool , 1 ),
6668 }
6769 indexExpiry := o .IndexExpiry
6870 idx .options .Store (o )
@@ -128,6 +130,8 @@ type IndexedClient struct {
128130 lastWrite atomicx.Time `msg:"-"`
129131 isClosing atomic.Bool
130132 cancel context.CancelFunc
133+ forceFlush chan bool
134+ hasFlushed chan bool
131135 flusherExited atomic.Bool
132136 reaperExited atomic.Bool
133137}
@@ -294,25 +298,50 @@ func (idx *IndexedClient) Close() error {
294298
295299// flusher periodically calls the cache's index flush func that writes the cache index to disk
296300func (idx * IndexedClient ) flusher (ctx context.Context ) {
301+ fi := idx .options .Load ().(* options.Options ).FlushInterval
302+ ticker := time .NewTicker (fi )
303+ defer ticker .Stop ()
297304FLUSHER:
298305 for {
299- fi := idx .options .Load ().(* options.Options ).FlushInterval
300306 select {
301307 case <- ctx .Done ():
302308 break FLUSHER
303- case <- time . After ( fi ) :
309+ case <- ticker . C :
304310 if idx .lastWrite .Load ().Before (idx .LastFlush .Load ()) {
305311 continue
306312 }
307- idx .flushOnce ()
313+ case <- idx .forceFlush :
314+ }
315+ idx .flushOnce ()
316+ select {
317+ case idx .hasFlushed <- true :
318+ // signal that a flush has occurred
319+ default :
320+ // drop message if no listener
308321 }
309322 }
310323 idx .flusherExited .Store (true )
311324}
312325
326+ // clone the msgpack encoded fields of the IndexedClient structure
327+ // not meant to be a deep clone / usable client, just a snapshot of the index state
328+ func (idx * IndexedClient ) clone () * IndexedClient {
329+ clone := & IndexedClient {
330+ CacheSize : atomic .LoadInt64 (& idx .CacheSize ),
331+ ObjectCount : atomic .LoadInt64 (& idx .ObjectCount ),
332+ }
333+ clone .LastFlush .Store (idx .LastFlush .Load ())
334+ idx .Objects .Range (func (key , value any ) bool {
335+ clone .Objects .Store (key , value )
336+ return true
337+ })
338+ return clone
339+ }
340+
313341func (idx * IndexedClient ) flushOnce () {
314342 idx .LastFlush .Store (time .Now ()) // update flush time, so that it is marshalled / stored
315- bytes , err := idx .MarshalMsg (nil )
343+ clone := idx .clone ()
344+ bytes , err := clone .MarshalMsg (nil )
316345 if err != nil {
317346 logger .Warn ("unable to serialize index for flushing" ,
318347 logging.Pairs {"cacheName" : idx .name , "detail" : err .Error ()})
0 commit comments