node: Revise fetch dequeue behavior

The fetch queue could sometimes not drain due to skipped fetches not
signaling that to the dequeue loop.

We now return a `bool` from `try_fetch` and keep trying to dequeue
fetches until one of them actually is initiated.

Additionally, we try to dequeue fetches at a regular interval
(`IDLE_INTERVAL`) to ensure that the queue is drained.
This commit is contained in:
cloudhead 2024-06-18 17:26:51 +02:00
parent 47c9f792e6
commit dd7a0b3524
No known key found for this signature in database
1 changed files with 22 additions and 6 deletions

View File

@ -809,6 +809,7 @@ where
self.disconnect_unresponsive_peers(&now); self.disconnect_unresponsive_peers(&now);
self.idle_connections(); self.idle_connections();
self.maintain_connections(); self.maintain_connections();
self.dequeue_fetch();
self.outbox.wakeup(IDLE_INTERVAL); self.outbox.wakeup(IDLE_INTERVAL);
self.last_idle = now; self.last_idle = now;
} }
@ -989,8 +990,7 @@ where
if status.want.is_empty() { if status.want.is_empty() {
debug!(target: "service", "Skipping fetch for {rid}, all refs are already in storage"); debug!(target: "service", "Skipping fetch for {rid}, all refs are already in storage");
} else { } else {
self._fetch(rid, from, status.want, timeout, channel); return self._fetch(rid, from, status.want, timeout, channel);
return true;
} }
} }
Err(e) => { Err(e) => {
@ -1008,7 +1008,7 @@ where
from: NodeId, from: NodeId,
timeout: time::Duration, timeout: time::Duration,
channel: Option<chan::Sender<FetchResult>>, channel: Option<chan::Sender<FetchResult>>,
) { ) -> bool {
self._fetch(rid, from, vec![], timeout, channel) self._fetch(rid, from, vec![], timeout, channel)
} }
@ -1019,12 +1019,13 @@ where
refs_at: Vec<RefsAt>, refs_at: Vec<RefsAt>,
timeout: time::Duration, timeout: time::Duration,
channel: Option<chan::Sender<FetchResult>>, channel: Option<chan::Sender<FetchResult>>,
) { ) -> bool {
match self.try_fetch(rid, &from, refs_at.clone(), timeout) { match self.try_fetch(rid, &from, refs_at.clone(), timeout) {
Ok(fetching) => { Ok(fetching) => {
if let Some(c) = channel { if let Some(c) = channel {
fetching.subscribe(c); fetching.subscribe(c);
} }
return true;
} }
Err(TryFetchError::AlreadyFetching(fetching)) => { Err(TryFetchError::AlreadyFetching(fetching)) => {
// If we're already fetching the same refs from the requested peer, there's nothing // If we're already fetching the same refs from the requested peer, there's nothing
@ -1047,7 +1048,7 @@ where
if self.queue.contains(&fetch) { if self.queue.contains(&fetch) {
debug!(target: "service", "Fetch for {rid} with {from} is already queued.."); debug!(target: "service", "Fetch for {rid} with {from} is already queued..");
} else { } else {
debug!(target: "service", "Queueing fetch for {rid} with {from}.."); debug!(target: "service", "Queueing fetch for {rid} with {from} (already fetching)..");
self.queue.push_back(fetch); self.queue.push_back(fetch);
} }
} }
@ -1071,6 +1072,7 @@ where
} }
} }
} }
false
} }
// TODO: Buffer/throttle fetches. // TODO: Buffer/throttle fetches.
@ -1220,6 +1222,8 @@ where
/// 1. The RID was already being fetched. /// 1. The RID was already being fetched.
/// 2. The session was already at fetch capacity. /// 2. The session was already at fetch capacity.
pub fn dequeue_fetch(&mut self) { pub fn dequeue_fetch(&mut self) {
let mut tries = self.queue.len();
while let Some(QueuedFetch { while let Some(QueuedFetch {
rid, rid,
from, from,
@ -1245,7 +1249,19 @@ where
} }
} else { } else {
// If no refs are specified, always do a full fetch. // If no refs are specified, always do a full fetch.
self.fetch(rid, from, timeout, channel); if self.fetch(rid, from, timeout, channel) {
break;
}
}
// Nb. Just a precaution, `tries` should always be >= 1 here.
tries = tries.saturating_sub(1);
// To avoid looping forever, only try to dequeue a fixed number of fetches at a time.
if tries == 0 {
debug!(
target: "service",
"Giving up on dequeuing, {} item(s) still left in the queue..",
self.queue.len()
);
break; break;
} }
} }