node: Add a max capacity to fetch queues
This commit is contained in:
parent
3c1c35f259
commit
aac23dde0c
|
|
@ -1017,12 +1017,9 @@ where
|
||||||
timeout,
|
timeout,
|
||||||
channel,
|
channel,
|
||||||
};
|
};
|
||||||
|
debug!(target: "service", "Queueing fetch for {rid} with {from} (already fetching)..");
|
||||||
|
|
||||||
if self.queue_fetch(fetch) {
|
self.queue_fetch(fetch);
|
||||||
debug!(target: "service", "Queueing fetch for {rid} with {from} (already fetching)..");
|
|
||||||
} else {
|
|
||||||
debug!(target: "service", "Fetch for {rid} with {from} is already queued..");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(TryFetchError::SessionCapacityReached) => {
|
Err(TryFetchError::SessionCapacityReached) => {
|
||||||
|
|
@ -1047,12 +1044,15 @@ where
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn queue_fetch(&mut self, fetch: QueuedFetch) -> bool {
|
fn queue_fetch(&mut self, fetch: QueuedFetch) {
|
||||||
let Some(s) = self.sessions.get_mut(&fetch.from) else {
|
let Some(s) = self.sessions.get_mut(&fetch.from) else {
|
||||||
log::error!(target: "service", "Cannot queue fetch for unknown session {}", fetch.from);
|
log::error!(target: "service", "Cannot queue fetch for unknown session {}", fetch.from);
|
||||||
return false;
|
return;
|
||||||
};
|
};
|
||||||
s.queue_fetch(fetch)
|
if let Err(e) = s.queue_fetch(fetch) {
|
||||||
|
let fetch = e.inner();
|
||||||
|
log::debug!(target: "service", "Unable to queue fetch for {} with {}: {e}", &fetch.rid, &fetch.from);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Buffer/throttle fetches.
|
// TODO: Buffer/throttle fetches.
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ pub use crate::node::{PingState, State};
|
||||||
|
|
||||||
/// Time after which a connection is considered stable.
|
/// Time after which a connection is considered stable.
|
||||||
pub const CONNECTION_STABLE_THRESHOLD: LocalDuration = LocalDuration::from_mins(1);
|
pub const CONNECTION_STABLE_THRESHOLD: LocalDuration = LocalDuration::from_mins(1);
|
||||||
|
/// Maximum items in the fetch queue.
|
||||||
|
pub const MAX_FETCH_QUEUE_SIZE: usize = 128;
|
||||||
|
|
||||||
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
#[derive(thiserror::Error, Debug, Clone, Copy)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
@ -46,6 +48,27 @@ impl Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Error when trying to queue a fetch.
|
||||||
|
#[derive(thiserror::Error, Debug, Clone)]
|
||||||
|
pub enum QueueError {
|
||||||
|
/// The item already exists in the queue.
|
||||||
|
#[error("item is already queued")]
|
||||||
|
Duplicate(QueuedFetch),
|
||||||
|
/// The queue is at capacity.
|
||||||
|
#[error("queue capacity reached")]
|
||||||
|
CapacityReached(QueuedFetch),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueueError {
|
||||||
|
/// Get the inner [`QueuedFetch`].
|
||||||
|
pub fn inner(&self) -> &QueuedFetch {
|
||||||
|
match self {
|
||||||
|
Self::Duplicate(f) => f,
|
||||||
|
Self::CapacityReached(f) => f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch waiting to be processed, in the fetch queue.
|
/// Fetch waiting to be processed, in the fetch queue.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct QueuedFetch {
|
pub struct QueuedFetch {
|
||||||
|
|
@ -131,7 +154,7 @@ impl Session {
|
||||||
subscribe: None,
|
subscribe: None,
|
||||||
persistent,
|
persistent,
|
||||||
last_active: LocalTime::default(),
|
last_active: LocalTime::default(),
|
||||||
queue: VecDeque::new(),
|
queue: VecDeque::with_capacity(MAX_FETCH_QUEUE_SIZE),
|
||||||
attempts: 1,
|
attempts: 1,
|
||||||
rng,
|
rng,
|
||||||
limits,
|
limits,
|
||||||
|
|
@ -205,15 +228,17 @@ impl Session {
|
||||||
|
|
||||||
/// Queue a fetch. Returns `true` if it was added to the queue, and `false` if
|
/// Queue a fetch. Returns `true` if it was added to the queue, and `false` if
|
||||||
/// it already was present in the queue.
|
/// it already was present in the queue.
|
||||||
pub fn queue_fetch(&mut self, fetch: QueuedFetch) -> bool {
|
pub fn queue_fetch(&mut self, fetch: QueuedFetch) -> Result<(), QueueError> {
|
||||||
assert_eq!(fetch.from, self.id);
|
assert_eq!(fetch.from, self.id);
|
||||||
|
|
||||||
if self.queue.contains(&fetch) {
|
if self.queue.len() >= MAX_FETCH_QUEUE_SIZE {
|
||||||
false
|
return Err(QueueError::CapacityReached(fetch));
|
||||||
} else {
|
} else if self.queue.contains(&fetch) {
|
||||||
self.queue.push_back(fetch);
|
return Err(QueueError::Duplicate(fetch));
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
self.queue.push_back(fetch);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dequeue_fetch(&mut self) -> Option<QueuedFetch> {
|
pub fn dequeue_fetch(&mut self) -> Option<QueuedFetch> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue