aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-01 20:40:52 +0100
committertv <tv@krebsco.de>2026-11-01 20:40:52 +0100
commit9e2529fe4ce61e57b9473c2ac85359b3c3f5cb65 (patch)
tree1a434d5400cf4bdc58df43e95b8d6156a1356fea
parent6d9b462e1bb1e2ebbda6c0dcdcfe22a15d4b4cbe (diff)
remake: download wakes on end instead of ticker
-rw-r--r--src/remake/content.rs5
-rw-r--r--src/remake/local.rs16
2 files changed, 15 insertions, 6 deletions
diff --git a/src/remake/content.rs b/src/remake/content.rs
index d036b87..467d083 100644
--- a/src/remake/content.rs
+++ b/src/remake/content.rs
@@ -11,7 +11,6 @@
use std::collections::HashSet;
use std::sync::Arc;
-use std::time::Duration;
use tracing::{info, warn};
@@ -59,9 +58,7 @@ pub(super) async fn ensure<H: Host>(
.ok_or_else(|| format!("couldn't download content {}", reference.blake3));
}
// Someone else is downloading it.
- while host.remake().content_fetch_running(&hash) {
- tokio::time::sleep(Duration::from_millis(500)).await;
- }
+ host.remake().content_fetch_ended(&hash).await;
}
}
diff --git a/src/remake/local.rs b/src/remake/local.rs
index ce133ec..c80a5a5 100644
--- a/src/remake/local.rs
+++ b/src/remake/local.rs
@@ -25,6 +25,8 @@ pub(crate) struct RemakeState {
started_at: UnixMillis,
// A std mutex: every access is short and never spans an await.
inner: Mutex<Inner>,
+ /// A download of content ended (`end_content_fetch`).
+ content_fetch_ended: tokio::sync::Notify,
}
impl RemakeState {
@@ -33,6 +35,7 @@ impl RemakeState {
Self {
started_at,
inner: Mutex::default(),
+ content_fetch_ended: tokio::sync::Notify::new(),
}
}
}
@@ -339,10 +342,19 @@ impl RemakeState {
pub(crate) fn end_content_fetch(&self, hash: &[u8; 32]) {
self.lock().content_fetches.remove(hash);
+ self.content_fetch_ended.notify_waiters();
}
- pub(crate) fn content_fetch_running(&self, hash: &[u8; 32]) -> bool {
- self.lock().content_fetches.contains(hash)
+ /// Waits until no download of `hash` runs.
+ pub(crate) async fn content_fetch_ended(&self, hash: &[u8; 32]) {
+ loop {
+ // Before looking, so that an end in between isn't missed.
+ let ended = self.content_fetch_ended.notified();
+ if !self.lock().content_fetches.contains(hash) {
+ return;
+ }
+ ended.await;
+ }
}
/// Drops content that no remake in `referenced` needs, once its grace has passed.