From fe64186ee3461dc18f554ff9eb9973aaa5b27408 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:47:54 +0000 Subject: [PATCH 01/10] refactor(tinymemory-tools): make EngineResolver::resolve async The EngineResolver trait now exposes an async resolve method, and all call sites await it. This lets resolvers perform asynchronous work such as I/O when locating the configured engine and identity instead of blocking the caller. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/lifecycle/turn.rs | 9 +++++---- .../tinymemory-tools/src/lifecycle/turn_runtime_tests.rs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crates/tinymemory-tools/src/lifecycle/turn.rs b/crates/tinymemory-tools/src/lifecycle/turn.rs index d39209b5..2dad6f83 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn.rs @@ -56,13 +56,14 @@ pub trait Clock: Send + Sync { } /// Resolves the configured engine and identity to their lifecycle instance. +#[async_trait] pub trait EngineResolver: Send + Sync { /// Returns the configured memory instance for this host hook. /// /// # Errors /// /// Returns the host's engine or identity resolution failure. - fn resolve(&self) -> tinymemory_api::Result; + async fn resolve(&self) -> tinymemory_api::Result; } /// Receives background jobs returned by a successful post-turn log. @@ -307,7 +308,7 @@ impl TurnHooks { let work_clock = clock.clone(); let model = self.date_hint_model.clone(); let operation = async move { - let mut memory = resolver.resolve().ok()?; + let mut memory = resolver.resolve().await.ok()?; if deadline.is_some_and(|deadline| work_clock.now() >= deadline) { return None; } @@ -427,7 +428,7 @@ impl TurnHooks { if !logging { return; } - let Ok(memory) = self.resolver.resolve() else { + let Ok(memory) = self.resolver.resolve().await else { return; }; let Ok(report) = memory.post_turn(turn).await else { @@ -483,7 +484,7 @@ impl TurnHooks { let resolver = self.resolver.clone(); let clock = self.clock.clone(); let operation = async move { - let memory = resolver.resolve().ok()?; + let memory = resolver.resolve().await.ok()?; if deadline.is_some_and(|deadline| clock.now() >= deadline) { return None; } diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index dee04197..21554ad9 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -139,7 +139,7 @@ struct StaticResolver { } impl EngineResolver for StaticResolver { - fn resolve(&self) -> Result { + async fn resolve(&self) -> Result { self.calls.fetch_add(1, Ordering::SeqCst); self.clock.advance_by(self.advance); if self.fail { From 2583965aca6a6f3adae3daf63531b410033ce27a Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:48:16 +0000 Subject: [PATCH 02/10] test(lifecycle): cover pre-turn awaiting async engine resolution Add a DeferredResolver test double whose resolve future stays pending until released, and a test asserting that pre_turn does not complete while engine resolution is still in flight. This pins down the ordering guarantee that citations are not recorded before the engine memory is available. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- .../src/lifecycle/turn_runtime_tests.rs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index 21554ad9..c0eb3130 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -138,6 +138,21 @@ struct StaticResolver { advance: Duration, } +struct DeferredResolver { + memory: AgentMemory, + release: Mutex>>, +} + +#[async_trait] +impl EngineResolver for DeferredResolver { + async fn resolve(&self) -> Result { + if let Some(release) = self.release.lock().unwrap().take() { + let _ = release.await; + } + Ok(self.memory.clone()) + } +} + impl EngineResolver for StaticResolver { async fn resolve(&self) -> Result { self.calls.fetch_add(1, Ordering::SeqCst); @@ -296,6 +311,39 @@ fn fixture_with_memory_and_advance( } } +#[tokio::test] +async fn pre_turn_awaits_async_engine_resolution() { + let engine = Arc::new(ReferenceEngine::new()); + let (release, wait) = oneshot::channel(); + let resolver = Arc::new(DeferredResolver { + memory: memory(engine), + release: Mutex::new(Some(wait)), + }); + let clock = FakeClock::at(Duration::ZERO); + let citations = Arc::new(RecordingCitations::default()); + let hooks = TurnHooks::new( + resolver, + Arc::new(clock.clone()), + None, + Arc::new(RecordingJobs::default()), + citations.clone(), + ); + let mut work = Box::pin(hooks.pre_turn( + PreTurn::new("thread", 0, "remember this"), + options(true, true), + )); + + poll_fn(|cx| match work.as_mut().poll(cx) { + Poll::Pending => Poll::Ready(()), + Poll::Ready(_) => panic!("pre-turn completed before async engine resolution"), + }) + .await; + release.send(()).unwrap(); + + assert!(work.await.is_some()); + assert_eq!(citations.calls.load(Ordering::SeqCst), 0); +} + fn options(logging: bool, recall: bool) -> PreTurnOptions { PreTurnOptions { logging, From 7d8cf40eec4dd42bcc4f099aa48c682b41d56861 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:48:32 +0000 Subject: [PATCH 03/10] test(lifecycle): add async_trait to StaticResolver and scope release lock The StaticResolver implementation of EngineResolver was missing the async_trait attribute, so it now matches the trait's async signature. The DeferredResolver resolve method also drops its mutex guard before awaiting the release, avoiding holding the lock across an await point. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index c0eb3130..61c22d7f 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -146,13 +146,15 @@ struct DeferredResolver { #[async_trait] impl EngineResolver for DeferredResolver { async fn resolve(&self) -> Result { - if let Some(release) = self.release.lock().unwrap().take() { + let release = self.release.lock().unwrap().take(); + if let Some(release) = release { let _ = release.await; } Ok(self.memory.clone()) } } +#[async_trait] impl EngineResolver for StaticResolver { async fn resolve(&self) -> Result { self.calls.fetch_add(1, Ordering::SeqCst); From d9fe2fdc6732f1f22939e645f17430efb4bd7a06 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:49:10 +0000 Subject: [PATCH 04/10] test(lifecycle): assert engine resolution is awaited once Track resolver invocations with an atomic counter so the pre-turn test can verify the async engine resolution is awaited exactly once before proceeding. The fixture now clones the resolver handle to keep it accessible after the turn completes. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- .../tinymemory-tools/src/lifecycle/turn_runtime_tests.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index 61c22d7f..2aab74fd 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -141,11 +141,13 @@ struct StaticResolver { struct DeferredResolver { memory: AgentMemory, release: Mutex>>, + calls: AtomicUsize, } #[async_trait] impl EngineResolver for DeferredResolver { async fn resolve(&self) -> Result { + self.calls.fetch_add(1, Ordering::SeqCst); let release = self.release.lock().unwrap().take(); if let Some(release) = release { let _ = release.await; @@ -304,7 +306,7 @@ fn fixture_with_memory_and_advance( )); Fixture { hooks, - resolver, + resolver.clone(), clock, model, jobs, @@ -320,6 +322,7 @@ async fn pre_turn_awaits_async_engine_resolution() { let resolver = Arc::new(DeferredResolver { memory: memory(engine), release: Mutex::new(Some(wait)), + calls: AtomicUsize::new(0), }); let clock = FakeClock::at(Duration::ZERO); let citations = Arc::new(RecordingCitations::default()); @@ -340,9 +343,10 @@ async fn pre_turn_awaits_async_engine_resolution() { Poll::Ready(_) => panic!("pre-turn completed before async engine resolution"), }) .await; + assert_eq!(resolver.calls.load(Ordering::SeqCst), 1); release.send(()).unwrap(); - assert!(work.await.is_some()); + let _ = work.await; assert_eq!(citations.calls.load(Ordering::SeqCst), 0); } From 67496f622088cda20c3342199d16143af348ac1a Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:49:17 +0000 Subject: [PATCH 05/10] test(lifecycle): clone resolver in pre-turn async resolution test The test now clones the resolver before passing it to TurnHooks so the original binding stays available for later assertions. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index 2aab74fd..0ae27690 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -327,7 +327,7 @@ async fn pre_turn_awaits_async_engine_resolution() { let clock = FakeClock::at(Duration::ZERO); let citations = Arc::new(RecordingCitations::default()); let hooks = TurnHooks::new( - resolver, + resolver.clone(), Arc::new(clock.clone()), None, Arc::new(RecordingJobs::default()), From 1098a54c8cde259caaa7c37c6bb93552b10ff356 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:49:28 +0000 Subject: [PATCH 06/10] test(lifecycle): drop redundant clone in turn runtime fixture The fixture builder cloned the resolver before moving it into the struct, which was unnecessary since the value is not used afterwards. Removing the clone keeps the test setup free of a needless allocation. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs index 0ae27690..fb3ce185 100644 --- a/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs +++ b/crates/tinymemory-tools/src/lifecycle/turn_runtime_tests.rs @@ -306,7 +306,7 @@ fn fixture_with_memory_and_advance( )); Fixture { hooks, - resolver.clone(), + resolver, clock, model, jobs, From 54ec2a36a190bbffb1f73b03181442e8cfb58f87 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 02:52:57 +0000 Subject: [PATCH 07/10] chore(deps): update tokio to 1.53.3 and pin windows-sys to 0.52.0 Bumps tokio from 1.53.1 to 1.53.3 and downgrades the windows-sys dependency pulled in by several crates from 0.61.2 to 0.52.0. The lockfile was regenerated to reflect the resolved dependency graph. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dc49190b..c1f1b409 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -392,7 +392,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1133,7 +1133,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1328,7 +1328,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1652,7 +1652,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -1770,9 +1770,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e" dependencies = [ "bytes", "libc", @@ -2182,7 +2182,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] From c6a6a6289272b9892dcf95bb0110a4fcd91b6842 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 03:17:35 +0000 Subject: [PATCH 08/10] refactor(deletion): make is_reachable async on DeletionExecutor The reachability probe is now an async method so executors can await a real backend check instead of blocking, and the drain path awaits it before running anything. A test with a deferred reachability future covers the new behaviour. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/deletion/mod.rs | 4 +- .../src/deletion/mod_tests.rs | 50 ++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/crates/tinymemory-tools/src/deletion/mod.rs b/crates/tinymemory-tools/src/deletion/mod.rs index 6130ee75..ac7f67be 100644 --- a/crates/tinymemory-tools/src/deletion/mod.rs +++ b/crates/tinymemory-tools/src/deletion/mod.rs @@ -88,7 +88,7 @@ impl Backoff { pub trait DeletionExecutor: Send + Sync { /// Whether the engine can be reached at all. When not, a drain stops /// before running anything. - fn is_reachable(&self) -> bool; + async fn is_reachable(&self) -> bool; /// Runs `deletion`, returning how many items went. /// @@ -252,7 +252,7 @@ impl> DeletionQueue { if queued.is_empty() { return 0; } - if !executor.is_reachable() { + if !executor.is_reachable().await { log::debug!( "[tinymemory:deletion] memory off; {} pending deletions wait", queued.len() diff --git a/crates/tinymemory-tools/src/deletion/mod_tests.rs b/crates/tinymemory-tools/src/deletion/mod_tests.rs index 55a9cdc8..1a6adc9b 100644 --- a/crates/tinymemory-tools/src/deletion/mod_tests.rs +++ b/crates/tinymemory-tools/src/deletion/mod_tests.rs @@ -1,8 +1,12 @@ use super::*; +use std::future::Future; use std::sync::Mutex as StdMutex; +use std::task::Poll; use crate::list_store::MemoryListStore; +use futures::channel::oneshot; +use futures::future::poll_fn; fn thread(id: &str) -> PendingDeletion { PendingDeletion::Thread { @@ -22,7 +26,7 @@ struct Engine { #[async_trait] impl DeletionExecutor for Engine { - fn is_reachable(&self) -> bool { + async fn is_reachable(&self) -> bool { self.reachable } async fn run(&self, deletion: &PendingDeletion) -> Result { @@ -35,6 +39,27 @@ impl DeletionExecutor for Engine { } } +struct DeferredReachability { + release: StdMutex>>, + ran: StdMutex>, +} + +#[async_trait] +impl DeletionExecutor for DeferredReachability { + async fn is_reachable(&self) -> bool { + let release = self.release.lock().unwrap().take(); + if let Some(release) = release { + let _ = release.await; + } + true + } + + async fn run(&self, deletion: &PendingDeletion) -> Result { + self.ran.lock().unwrap().push(deletion.clone()); + Ok(1) + } +} + fn engine(reachable: bool, failing: bool) -> Engine { Engine { reachable, @@ -64,6 +89,29 @@ async fn nothing_runs_while_the_engine_is_unreachable() { assert_eq!(queue.pending(), vec![thread("t")]); } +#[tokio::test] +async fn drain_awaits_async_reachability_before_running_deletions() { + let queue = queue(); + queue.enqueue(thread("t")); + let (release, wait) = oneshot::channel(); + let engine = DeferredReachability { + release: StdMutex::new(Some(wait)), + ran: StdMutex::new(Vec::new()), + }; + let mut drain = Box::pin(queue.drain(&engine, Drain::Force, Utc::now())); + + poll_fn(|cx| match drain.as_mut().poll(cx) { + Poll::Pending => Poll::Ready(()), + Poll::Ready(_) => panic!("drain completed before async reachability resolved"), + }) + .await; + assert!(engine.ran.lock().unwrap().is_empty()); + + release.send(()).unwrap(); + assert_eq!(drain.await, 1); + assert_eq!(engine.ran.lock().unwrap().as_slice(), &[thread("t")]); +} + #[tokio::test] async fn a_reachable_engine_settles_the_queue() { let queue = queue(); From 1cd17edd7a131a09662e2b9adc36d9def3277188 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 03:23:24 +0000 Subject: [PATCH 09/10] refactor(layout_migration): make LayoutHost::engines async The engines accessor on the LayoutHost trait is now async, and its call sites in the migration job and scan service await it. This lets hosts resolve engines through asynchronous work instead of blocking, and the test hosts were updated to match the new signature. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/layout_migration/job.rs | 4 ++-- crates/tinymemory-tools/src/layout_migration/service.rs | 2 +- crates/tinymemory-tools/src/layout_migration/service_tests.rs | 4 ++-- crates/tinymemory-tools/src/layout_migration/test_host.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/tinymemory-tools/src/layout_migration/job.rs b/crates/tinymemory-tools/src/layout_migration/job.rs index 97fc8d95..6e58b2ed 100644 --- a/crates/tinymemory-tools/src/layout_migration/job.rs +++ b/crates/tinymemory-tools/src/layout_migration/job.rs @@ -94,7 +94,7 @@ pub trait LayoutHost: Send + Sync { /// # Errors /// /// When memory is off or the account has no per-user root. - fn engines(&self) -> Result; + async fn engines(&self) -> Result; /// Where items go in the per-user tree. /// @@ -167,7 +167,7 @@ where if state.phase == Phase::Cleaned && (state.rechecked || !host.listed_unconfirmed()) { return Ok(Outcome::Done); } - let engines = host.engines()?; + let engines = host.engines().await?; if state.phase == Phase::Idle && !state.switched && !legacy_present(&*engines.legacy).await? { return nothing_to_move(host, &mut state).await; } diff --git a/crates/tinymemory-tools/src/layout_migration/service.rs b/crates/tinymemory-tools/src/layout_migration/service.rs index 85fb124d..c4b44e5c 100644 --- a/crates/tinymemory-tools/src/layout_migration/service.rs +++ b/crates/tinymemory-tools/src/layout_migration/service.rs @@ -215,7 +215,7 @@ pub async fn scan(host: &dyn LayoutHost) -> Result { { false } - Phase::Idle if !state.switched => match host.engines() { + Phase::Idle if !state.switched => match host.engines().await { // Memory off or signed out: nothing to show. Err(Error::Off(_)) => false, Err(error) => return Err(error), diff --git a/crates/tinymemory-tools/src/layout_migration/service_tests.rs b/crates/tinymemory-tools/src/layout_migration/service_tests.rs index 8f76232f..1745cdec 100644 --- a/crates/tinymemory-tools/src/layout_migration/service_tests.rs +++ b/crates/tinymemory-tools/src/layout_migration/service_tests.rs @@ -208,7 +208,7 @@ impl LayoutHost for CountingHost { &self.store } - fn engines(&self) -> crate::layout_migration::Result { + async fn engines(&self) -> crate::layout_migration::Result { if self.fail_engines { Err(crate::layout_migration::Error::Off( "engine unavailable".to_string(), @@ -219,7 +219,7 @@ impl LayoutHost for CountingHost { tree: self.inner.tree.clone(), }) } else { - self.inner.engines() + self.inner.engines().await } } diff --git a/crates/tinymemory-tools/src/layout_migration/test_host.rs b/crates/tinymemory-tools/src/layout_migration/test_host.rs index d5083fbd..466d19d3 100644 --- a/crates/tinymemory-tools/src/layout_migration/test_host.rs +++ b/crates/tinymemory-tools/src/layout_migration/test_host.rs @@ -100,7 +100,7 @@ impl LayoutHost for FakeHost { &self.store } - fn engines(&self) -> Result { + async fn engines(&self) -> Result { Ok(Engines { legacy: self.legacy.clone(), tree: self.tree.clone(), From 465d9444a085bf7aecec576c5b90c0c542e2d08a Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Tue, 27 Oct 2026 03:27:38 +0000 Subject: [PATCH 10/10] refactor(layout_migration): make legacy_claim async The LayoutHost::legacy_claim method is now async, and its callers in the migration job and scan service await it. This lets host implementations perform asynchronous work when acquiring the legacy claim instead of blocking the caller. Auto-committed-on: cuttlefish Co-authored-by: Medulla --- crates/tinymemory-tools/src/layout_migration/job.rs | 4 ++-- crates/tinymemory-tools/src/layout_migration/service.rs | 2 +- crates/tinymemory-tools/src/layout_migration/service_tests.rs | 4 ++-- crates/tinymemory-tools/src/layout_migration/test_host.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/crates/tinymemory-tools/src/layout_migration/job.rs b/crates/tinymemory-tools/src/layout_migration/job.rs index 6e58b2ed..3ac1b5fb 100644 --- a/crates/tinymemory-tools/src/layout_migration/job.rs +++ b/crates/tinymemory-tools/src/layout_migration/job.rs @@ -128,7 +128,7 @@ pub trait LayoutHost: Send + Sync { /// # Errors /// /// When memory is off or the account has no per-user root. - fn legacy_claim(&self) -> Result>>; + async fn legacy_claim(&self) -> Result>>; /// Whether the last import of old local memory ended with its last batch /// not confirmed listed. The migration then forgets by id, never erasing @@ -175,7 +175,7 @@ where state.takeover = true; store.save(&state)?; } - let shared = host.legacy_claim()?; + let shared = host.legacy_claim().await?; if let Some(claim) = &shared { if claim.held_by_other()? { return claimed_elsewhere(host, &mut state).await; diff --git a/crates/tinymemory-tools/src/layout_migration/service.rs b/crates/tinymemory-tools/src/layout_migration/service.rs index c4b44e5c..0aabedd9 100644 --- a/crates/tinymemory-tools/src/layout_migration/service.rs +++ b/crates/tinymemory-tools/src/layout_migration/service.rs @@ -197,7 +197,7 @@ pub struct MigrationStatus { /// tree cannot be read. pub async fn scan(host: &dyn LayoutHost) -> Result { let state = host.store().load()?; - let claim = match host.legacy_claim() { + let claim = match host.legacy_claim().await { // Memory off or signed out: nothing to show. Err(Error::Off(_)) => None, claim => claim?, diff --git a/crates/tinymemory-tools/src/layout_migration/service_tests.rs b/crates/tinymemory-tools/src/layout_migration/service_tests.rs index 1745cdec..8dc74c2c 100644 --- a/crates/tinymemory-tools/src/layout_migration/service_tests.rs +++ b/crates/tinymemory-tools/src/layout_migration/service_tests.rs @@ -239,8 +239,8 @@ impl LayoutHost for CountingHost { self.inner.free_now().await } - fn legacy_claim(&self) -> crate::layout_migration::Result>> { - self.inner.legacy_claim() + async fn legacy_claim(&self) -> crate::layout_migration::Result>> { + self.inner.legacy_claim().await } fn listed_unconfirmed(&self) -> bool { diff --git a/crates/tinymemory-tools/src/layout_migration/test_host.rs b/crates/tinymemory-tools/src/layout_migration/test_host.rs index 466d19d3..8211948a 100644 --- a/crates/tinymemory-tools/src/layout_migration/test_host.rs +++ b/crates/tinymemory-tools/src/layout_migration/test_host.rs @@ -134,7 +134,7 @@ impl LayoutHost for FakeHost { self.free.load(Ordering::SeqCst) && left > 0 } - fn legacy_claim(&self) -> Result>> { + async fn legacy_claim(&self) -> Result>> { Ok(self .claim .clone()