66
66
//! [`RemoteRegistry`]: crate::sources::registry::remote::RemoteRegistry
67
67
68
68
use std:: cell:: OnceCell ;
69
+ use std:: cell:: RefCell ;
70
+ use std:: collections:: BTreeMap ;
69
71
use std:: fs;
70
72
use std:: io;
71
73
use std:: path:: PathBuf ;
@@ -337,8 +339,9 @@ struct LocalDatabase<'gctx> {
337
339
/// The root path where caches are located.
338
340
cache_root : Filesystem ,
339
341
/// Connection to the SQLite database.
340
- conn : OnceCell < Option < Connection > > ,
342
+ conn : OnceCell < Option < RefCell < Connection > > > ,
341
343
/// [`GlobalContext`] reference for convenience.
344
+ deferred_writes : RefCell < BTreeMap < String , Vec < u8 > > > ,
342
345
gctx : & ' gctx GlobalContext ,
343
346
}
344
347
@@ -348,14 +351,16 @@ impl LocalDatabase<'_> {
348
351
LocalDatabase {
349
352
cache_root,
350
353
conn : OnceCell :: new ( ) ,
354
+ deferred_writes : RefCell :: new ( BTreeMap :: new ( ) ) ,
351
355
gctx,
352
356
}
353
357
}
354
358
355
- fn conn ( & self ) -> Option < & Connection > {
359
+ fn conn ( & self ) -> Option < & RefCell < Connection > > {
356
360
self . conn
357
361
. get_or_init ( || {
358
362
self . conn_init ( )
363
+ . map ( RefCell :: new)
359
364
. map_err ( |e| tracing:: debug!( "cannot open index cache db: {e}" ) )
360
365
. ok ( )
361
366
} )
@@ -373,29 +378,53 @@ impl LocalDatabase<'_> {
373
378
sqlite:: migrate ( & mut conn, & migrations ( ) ) ?;
374
379
Ok ( conn)
375
380
}
381
+
382
+ fn bulk_put ( & self ) -> CargoResult < ( ) > {
383
+ let Some ( conn) = self . conn ( ) else {
384
+ anyhow:: bail!( "no connection" ) ;
385
+ } ;
386
+ let mut conn = conn. borrow_mut ( ) ;
387
+ let tx = conn. transaction ( ) ?;
388
+ let mut stmt =
389
+ tx. prepare_cached ( "INSERT OR REPLACE INTO summaries (name, value) VALUES (?, ?)" ) ?;
390
+ for ( key, value) in self . deferred_writes . borrow ( ) . iter ( ) {
391
+ stmt. execute ( params ! ( key, value) ) ?;
392
+ }
393
+ drop ( stmt) ;
394
+ tx. commit ( ) ?;
395
+ self . deferred_writes . borrow_mut ( ) . clear ( ) ;
396
+ Ok ( ( ) )
397
+ }
398
+ }
399
+
400
+ impl Drop for LocalDatabase < ' _ > {
401
+ fn drop ( & mut self ) {
402
+ let _ = self
403
+ . bulk_put ( )
404
+ . map_err ( |e| tracing:: info!( "failed to flush cache: {e}" ) ) ;
405
+ }
376
406
}
377
407
378
408
impl CacheStore for LocalDatabase < ' _ > {
379
409
fn get ( & self , key : & str ) -> Option < Vec < u8 > > {
380
410
self . conn ( ) ?
411
+ . borrow ( )
381
412
. prepare_cached ( "SELECT value FROM summaries WHERE name = ? LIMIT 1" )
382
413
. and_then ( |mut stmt| stmt. query_row ( [ key] , |row| row. get ( 0 ) ) )
383
414
. map_err ( |e| tracing:: debug!( key, "cache missing: {e}" ) )
384
415
. ok ( )
385
416
}
386
417
387
418
fn put ( & self , key : & str , value : & [ u8 ] ) {
388
- if let Some ( conn) = self . conn ( ) {
389
- _ = conn
390
- . prepare_cached ( "INSERT OR REPLACE INTO summaries (name, value) VALUES (?, ?)" )
391
- . and_then ( |mut stmt| stmt. execute ( params ! ( key, value) ) )
392
- . map_err ( |e| tracing:: info!( key, "failed to write cache: {e}" ) ) ;
393
- }
419
+ self . deferred_writes
420
+ . borrow_mut ( )
421
+ . insert ( key. into ( ) , value. into ( ) ) ;
394
422
}
395
423
396
424
fn invalidate ( & self , key : & str ) {
397
425
if let Some ( conn) = self . conn ( ) {
398
426
_ = conn
427
+ . borrow ( )
399
428
. prepare_cached ( "DELETE FROM summaries WHERE name = ?" )
400
429
. and_then ( |mut stmt| stmt. execute ( [ key] ) )
401
430
. map_err ( |e| tracing:: debug!( key, "failed to remove from cache: {e}" ) ) ;
0 commit comments