app

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

commit aff09a20eb5b2e6eee195c865954c2a57623f599
parent 0fcc40ffb626736f8eb20d1498caee53d1a8ce4f
Author: triesap <tyson@radroots.org>
Date:   Mon, 10 Aug 2026 18:36:54 +0000

test: stabilize observer qualification timing

- wait for callback panic cleanup instead of assuming a fixed scheduler delay
- give the local relay adapter a realistic bounded test deadline
- preserve production observer behavior and public FFI metadata unchanged
- exercise the observer suite repeatedly and keep the full capsule check green

Diffstat:
Mcore/crates/harvestcircle_ffi/src/observer.rs | 16+++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/core/crates/harvestcircle_ffi/src/observer.rs b/core/crates/harvestcircle_ffi/src/observer.rs @@ -239,6 +239,7 @@ mod tests { }; const SECRET_HEX: &str = "7e7e9c42a91bfef19fa7ea99d52d8afdb67d893a8fefba1f5cb9793f2107f6d7"; + const TEST_RELAY_TIMEOUT: Duration = Duration::from_secs(2); #[derive(Default)] struct RecordingObserver { @@ -274,7 +275,7 @@ mod tests { RuntimeDependencies::new( Arc::new(InMemorySecretStore::default()), Arc::new(SystemClock), - Arc::new(SdkNostrClient::new(std::time::Duration::from_millis(10))), + Arc::new(SdkNostrClient::new(TEST_RELAY_TIMEOUT)), Arc::new(UuidInstallationIdentitySource), ), NonZeroUsize::new(ACTOR_MAILBOX_CAPACITY).expect("capacity"), @@ -382,8 +383,7 @@ mod tests { .subscribe_changes_v2(Box::new(PanickingObserver)) .await .expect("panic observer registration"); - tokio::time::sleep(Duration::from_millis(10)).await; - assert!(core.inner.observers.lock().expect("observers").is_empty()); + wait_for_observer_count(&core, 0).await; panic_subscription.unsubscribe().await; let observer = Arc::new(RecordingObserver::default()); @@ -503,6 +503,16 @@ mod tests { .expect("snapshot delivery"); } + async fn wait_for_observer_count(core: &HarvestCircleAppCore, expected: usize) { + tokio::time::timeout(OBSERVER_DELIVERY_TIMEOUT, async { + while core.inner.observers.lock().expect("observers").len() != expected { + tokio::task::yield_now().await; + } + }) + .await + .expect("observer deregistration"); + } + async fn wait_for_fresh_profile(observer: &RecordingObserver) { tokio::time::timeout(OBSERVER_DELIVERY_TIMEOUT, async { loop {