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.idle_connections();
self.maintain_connections();
self.dequeue_fetch();
self.outbox.wakeup(IDLE_INTERVAL);
self.last_idle = now;
}
@ -989,8 +990,7 @@ where
if status.want.is_empty() {
debug!(target: "service", "Skipping fetch for {rid}, all refs are already in storage");
} else {
self._fetch(rid, from, status.want, timeout, channel);
return true;
return self._fetch(rid, from, status.want, timeout, channel);
}
}
Err(e) => {
@ -1008,7 +1008,7 @@ where
from: NodeId,
timeout: time::Duration,
channel: Option<chan::Sender<FetchResult>>,
) {
) -> bool {
self._fetch(rid, from, vec![], timeout, channel)
}
@ -1019,12 +1019,13 @@ where
refs_at: Vec<RefsAt>,
timeout: time::Duration,
channel: Option<chan::Sender<FetchResult>>,
) {
) -> bool {
match self.try_fetch(rid, &from, refs_at.clone(), timeout) {
Ok(fetching) => {
if let Some(c) = channel {
fetching.subscribe(c);
}
return true;
}
Err(TryFetchError::AlreadyFetching(fetching)) => {
// 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) {
debug!(target: "service", "Fetch for {rid} with {from} is already queued..");
} 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);
}
}
@ -1071,6 +1072,7 @@ where
}
}
}
false
}
// TODO: Buffer/throttle fetches.
@ -1220,6 +1222,8 @@ where
/// 1. The RID was already being fetched.
/// 2. The session was already at fetch capacity.
pub fn dequeue_fetch(&mut self) {
let mut tries = self.queue.len();
while let Some(QueuedFetch {
rid,
from,
@ -1245,7 +1249,19 @@ where
}
} else {
// 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;
}
}