From 9b9165fc7dfb896707d32f426764c5ec229535ab Mon Sep 17 00:00:00 2001 From: Karl Stenerud Date: Mon, 22 Sep 2025 15:41:43 +0200 Subject: [PATCH] Use resilient storage for globals --- Cargo.Bazel.lock | 6 +++++- Cargo.lock | 1 + .../io/bitdrift/capture/CaptureJniLibrary.kt | 2 -- .../main/kotlin/io/bitdrift/capture/IBridge.kt | 1 - .../kotlin/io/bitdrift/capture/LoggerImpl.kt | 1 - .../capture/CaptureLoggerNetworkTest.kt | 3 --- .../io/bitdrift/capture/ConfigurationTest.kt | 3 --- platform/jvm/src/jni.rs | 17 +++++++++++++---- platform/swift/source/src/bridge.rs | 11 ++++++++--- platform/swift/source/src/crash_report.rs | 3 +-- test/platform/swift/bridging/Cargo.toml | 1 + 11 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 50927e6af..9e66f6b55 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "f82c53dbe0d8bcfb4edf75508e8596220b4ff1dc97dd37f49f86e8a61af24c73", + "checksum": "17babf02f978c40081fc31e0f9091d487e0424ee0165fa275af861b01fad5a70", "crates": { "addr2line 0.25.1": { "name": "addr2line", @@ -19147,6 +19147,10 @@ "id": "bd-bonjson 1.0.0", "target": "bd_bonjson" }, + { + "id": "bd-bonjson-ffi 1.0.0", + "target": "bd_bonjson_ffi" + }, { "id": "bd-client-common 1.0.0", "target": "bd_client_common" diff --git a/Cargo.lock b/Cargo.lock index d27566c7a..b24226b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3138,6 +3138,7 @@ name = "test_swift_bridge" version = "1.0.0" dependencies = [ "bd-bonjson", + "bd-bonjson-ffi", "bd-client-common", "bd-error-reporter", "bd-key-value", diff --git a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/CaptureJniLibrary.kt b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/CaptureJniLibrary.kt index 0c32fca14..192e34607 100644 --- a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/CaptureJniLibrary.kt +++ b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/CaptureJniLibrary.kt @@ -50,7 +50,6 @@ internal object CaptureJniLibrary : IBridge, IStreamingReportProcessor { * @param applicationVersion the version of the current app, used to identify with the backend * @param model the host device model, used to identify with the backend * @param network the network implementation to use to communicate with the backend - * @param preferences the preferences storage to use for persistent storage of simple settings and configuration. * @param errorReporter the error reporter to use for reporting error to bitdrift services. * @param startInSleepMode true to initialize in sleep mode */ @@ -66,7 +65,6 @@ internal object CaptureJniLibrary : IBridge, IStreamingReportProcessor { applicationVersion: String, model: String, network: ICaptureNetwork, - preferences: IPreferences, errorReporter: IErrorReporter, startInSleepMode: Boolean, ): Long diff --git a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/IBridge.kt b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/IBridge.kt index 44da2ef70..e03813790 100644 --- a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/IBridge.kt +++ b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/IBridge.kt @@ -24,7 +24,6 @@ internal interface IBridge { applicationVersion: String, model: String, network: ICaptureNetwork, - preferences: IPreferences, errorReporter: IErrorReporter, startInSleepMode: Boolean, ): Long diff --git a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt index 2cfd78598..86b4ed252 100644 --- a/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt +++ b/platform/jvm/capture/src/main/kotlin/io/bitdrift/capture/LoggerImpl.kt @@ -201,7 +201,6 @@ internal class LoggerImpl( clientAttributes.appVersion, deviceAttributes.model(), network, - preferences, localErrorReporter, configuration.sleepMode == SleepMode.ACTIVE, ) diff --git a/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/CaptureLoggerNetworkTest.kt b/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/CaptureLoggerNetworkTest.kt index 94ad3b25d..c81a77963 100644 --- a/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/CaptureLoggerNetworkTest.kt +++ b/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/CaptureLoggerNetworkTest.kt @@ -86,7 +86,6 @@ class CaptureLoggerNetworkTest { "test", network, mock(), - mock(), false, ) CaptureJniLibrary.startLogger(logger) @@ -169,7 +168,6 @@ class CaptureLoggerNetworkTest { "test", network, mock(), - mock(), false, ) CaptureJniLibrary.startLogger(loggerId) @@ -203,7 +201,6 @@ class CaptureLoggerNetworkTest { network, // this test fails if we pass mock() in here. It has something to do with // jni trying to call methods on Mockito mocks. - MockPreferences(), mock(), false, ) diff --git a/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/ConfigurationTest.kt b/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/ConfigurationTest.kt index 92351b0e7..d666fa048 100644 --- a/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/ConfigurationTest.kt +++ b/platform/jvm/capture/src/test/kotlin/io/bitdrift/capture/ConfigurationTest.kt @@ -44,7 +44,6 @@ class ConfigurationTest { anyOrNull(), anyOrNull(), anyOrNull(), - anyOrNull(), ), ).thenReturn(-1L) @@ -76,7 +75,6 @@ class ConfigurationTest { anyOrNull(), anyOrNull(), anyOrNull(), - anyOrNull(), ) // We perform another attempt to configure the logger to verify that @@ -105,7 +103,6 @@ class ConfigurationTest { anyOrNull(), anyOrNull(), anyOrNull(), - anyOrNull(), ) } diff --git a/platform/jvm/src/jni.rs b/platform/jvm/src/jni.rs index c04ba8048..b6a803969 100644 --- a/platform/jvm/src/jni.rs +++ b/platform/jvm/src/jni.rs @@ -6,7 +6,6 @@ // https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt use crate::events::ListenerTargetHandler as EventsListenerTargetHandler; -use crate::key_value_storage::PreferencesHandle; use crate::resource_utilization::TargetHandler as ResourceUtilizationTargetHandler; use crate::session::SessionStrategyConfigurationHandle; use crate::session_replay::{self, TargetHandler as SessionReplayTargetHandler}; @@ -58,6 +57,8 @@ use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::{Arc, OnceLock}; use time::{Duration, OffsetDateTime}; +static STORAGE_BUFFER_SIZE: usize = 1024 * 1024; + // If we are running on Android, we need to initialize the logging system to send logs to // `android_log` instead of `stderr. Use a compile time flag to determine if we are running on // Android to avoid setting this up in JVM tests where we want to log to stderr. @@ -596,7 +597,6 @@ pub extern "system" fn Java_io_bitdrift_capture_CaptureJniLibrary_createLogger( application_version: JString<'_>, model: JString<'_>, network: JObject<'_>, - preferences: JObject<'_>, error_reporter: JObject<'_>, start_in_sleep_mode: jboolean, ) -> jlong { @@ -609,13 +609,22 @@ pub extern "system" fn Java_io_bitdrift_capture_CaptureJniLibrary_createLogger( .to_string_lossy() .to_string(), ); + + // Create the SDK directory if it doesn't exist + std::fs::create_dir_all(&sdk_directory)?; + let network_manager = Box::new(Network { handle: new_global!(NetworkHandle, &mut env, network)?, active_streams: Arc::new(AtomicU32::new(0)), }); - let preferences = new_global!(PreferencesHandle, &mut env, preferences)?; - let store = Arc::new(bd_key_value::Store::new(Box::new(preferences))); + let storage = Box::new(bd_key_value::resilient_kv::ResilientKvStorage::new( + sdk_directory.join("storage"), + STORAGE_BUFFER_SIZE, + None, + None, + )?); + let store = Arc::new(bd_key_value::Store::new(storage)); let previous_run_global_state = read_global_state_snapshot(store.clone()); let session_strategy = Arc::new(new_global!( diff --git a/platform/swift/source/src/bridge.rs b/platform/swift/source/src/bridge.rs index f9e448501..22566ca07 100644 --- a/platform/swift/source/src/bridge.rs +++ b/platform/swift/source/src/bridge.rs @@ -11,7 +11,6 @@ mod bridge_tests; use crate::bridge::ffi::make_nsstring; use crate::ffi::{make_empty_nsstring, nsstring_into_string}; -use crate::key_value_storage::UserDefaultsStorage; use crate::{events, ffi, resource_utilization, session_replay}; use anyhow::anyhow; use bd_api::{Platform, PlatformNetworkManager, PlatformNetworkStream, StreamEvent}; @@ -51,6 +50,7 @@ use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::EnvFilter; +static STORAGE_BUFFER_SIZE: usize = 1024 * 1024; static LOGGING_INIT: Once = Once::new(); fn initialize_logging() { @@ -447,7 +447,13 @@ extern "C" fn capture_create_logger( with_handle_unexpected_or( || { - let storage = Box::::default(); + let path = unsafe { CStr::from_ptr(path) }.to_str()?; + let storage = Box::new(bd_key_value::resilient_kv::ResilientKvStorage::new( + format!("{path}/storage"), + STORAGE_BUFFER_SIZE, + None, + None, + )?); let store = Arc::new(bd_key_value::Store::new(storage)); let previous_run_global_state = read_global_state_snapshot(store.clone()); @@ -493,7 +499,6 @@ extern "C" fn capture_create_logger( }) }; - let path = unsafe { CStr::from_ptr(path) }.to_str()?; let logger = bd_logger::LoggerBuilder::new(bd_logger::InitParams { sdk_directory: path.into(), api_key: unsafe { CStr::from_ptr(api_key) }.to_str()?.to_string(), diff --git a/platform/swift/source/src/crash_report.rs b/platform/swift/source/src/crash_report.rs index cc9c15e86..4af7e5999 100644 --- a/platform/swift/source/src/crash_report.rs +++ b/platform/swift/source/src/crash_report.rs @@ -267,8 +267,7 @@ fn parse_address_value(address: &Value) -> anyhow::Result { }) .ok_or_else(|| anyhow::anyhow!("Address value is negative: {address}")), _ => Err(anyhow::anyhow!( - "Address value is not a valid number (got {:?})", - address + "Address value is not a valid number (got {address:?})" )), } } diff --git a/test/platform/swift/bridging/Cargo.toml b/test/platform/swift/bridging/Cargo.toml index cee24594b..53642afbf 100644 --- a/test/platform/swift/bridging/Cargo.toml +++ b/test/platform/swift/bridging/Cargo.toml @@ -8,6 +8,7 @@ version = "1.0.0" [dependencies] bd-bonjson = { workspace = true } +bd-bonjson-ffi = { workspace = true } bd-client-common = { workspace = true } bd-error-reporter = { workspace = true } bd-key-value = { workspace = true }