app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 3e1f96aaed82966f4b6dd8dd6b26dbe26205b100
parent b33a3f6bff9a224a61077b668c82aadc621b558d
Author: triesap <triesap@radroots.dev>
Date:   Tue, 20 Jan 2026 23:14:58 +0000

app: streamline log loading and flush

- add no-prune buffer flush helper

- switch log entry loading to prefix datastore queries

- export new log flush helper for UI usage

- add unit test for no-prune flush path

Diffstat:
Mapp/src/lib.rs | 1+
Mapp/src/logging.rs | 49+++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/app/src/lib.rs b/app/src/lib.rs @@ -58,6 +58,7 @@ pub use logging::{ app_log_buffer_drain, app_log_buffer_flush_critical, app_log_buffer_flush, + app_log_buffer_flush_no_prune, app_log_buffer_push, app_log_entries_dump, app_log_entries_clear, diff --git a/app/src/logging.rs b/app/src/logging.rs @@ -367,9 +367,10 @@ fn app_log_entry_should_persist(level: RadrootsAppLogLevel) -> bool { matches!(level, RadrootsAppLogLevel::Warn | RadrootsAppLogLevel::Error) } -pub async fn app_log_buffer_flush<T: RadrootsClientDatastore>( +async fn app_log_buffer_flush_internal<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, + prune: bool, ) -> RadrootsAppLogResult<usize> { let entries = app_log_buffer_drain(); let mut stored = 0; @@ -384,10 +385,26 @@ pub async fn app_log_buffer_flush<T: RadrootsClientDatastore>( } stored += 1; } - let _ = app_log_entries_prune(datastore, key_maps, APP_LOG_MAX_ENTRIES).await?; + if prune { + let _ = app_log_entries_prune(datastore, key_maps, APP_LOG_MAX_ENTRIES).await?; + } Ok(stored) } +pub async fn app_log_buffer_flush<T: RadrootsClientDatastore>( + datastore: &T, + key_maps: &RadrootsAppKeyMapConfig, +) -> RadrootsAppLogResult<usize> { + app_log_buffer_flush_internal(datastore, key_maps, true).await +} + +pub async fn app_log_buffer_flush_no_prune<T: RadrootsClientDatastore>( + datastore: &T, + key_maps: &RadrootsAppKeyMapConfig, +) -> RadrootsAppLogResult<usize> { + app_log_buffer_flush_internal(datastore, key_maps, false).await +} + pub async fn app_log_buffer_flush_critical<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, @@ -433,13 +450,13 @@ pub async fn app_log_entries_load<T: RadrootsClientDatastore>( datastore: &T, key_maps: &RadrootsAppKeyMapConfig, ) -> RadrootsAppLogResult<Vec<RadrootsAppLogEntry>> { - let entries = datastore.entries().await.map_err(RadrootsAppLogError::Datastore)?; let prefix = app_log_entry_prefix(key_maps)?; + let entries = datastore + .entries_pref(&prefix) + .await + .map_err(RadrootsAppLogError::Datastore)?; let mut out = Vec::new(); for entry in entries { - if !entry.key.starts_with(&prefix) { - continue; - } let Some(value) = entry.value else { continue; }; @@ -559,6 +576,7 @@ mod tests { app_log_entry_prefix, app_log_buffer_drain, app_log_buffer_flush_critical, + app_log_buffer_flush_no_prune, app_log_buffer_flush, app_log_buffer_push, app_log_metadata, @@ -941,4 +959,23 @@ mod tests { assert_eq!(stored, 1); assert_eq!(datastore.len(), 1); } + + #[test] + fn log_buffer_flush_no_prune_stores_entries() { + let _guard = LOG_TEST_LOCK.lock().unwrap_or_else(|err| err.into_inner()); + let _ = app_log_buffer_drain(); + let key_maps = app_key_maps_default(); + let datastore = TestDatastore::new(Vec::new()); + app_log_buffer_push(app_log_entry_new( + RadrootsAppLogLevel::Info, + "log.code.flush.noprune", + "flush", + None, + )); + let stored = + futures::executor::block_on(app_log_buffer_flush_no_prune(&datastore, &key_maps)) + .expect("flush"); + assert_eq!(stored, 1); + assert_eq!(datastore.len(), 1); + } }