use std::str::FromStr;
use crate::{
backend::{Backend, TaskSink, WireFormatBackend},
task::{Task, status::Status},
};
const DEFAULT_PAGE_SIZE: u32 = 10;
pub trait Expose<Args, Kind> {}
impl<B, Args, Kind> Expose<Args, Kind> for B where
B: Backend
+ Metrics
+ ListWorkers
+ ListQueues
+ ListAllTasks
+ ListTasks
+ TaskSink<Args, Kind>
{
}
pub trait ListQueues: Backend {
fn list_queues(&self) -> impl Future<Output = Result<Vec<QueueInfo>, Self::Error>> + Send;
}
pub trait ListWorkers: Backend {
fn list_workers(&self) -> impl Future<Output = Result<Vec<RunningWorker>, Self::Error>> + Send;
fn list_all_workers(
&self,
) -> impl Future<Output = Result<Vec<RunningWorker>, Self::Error>> + Send;
}
pub trait ListTasks: WireFormatBackend + Backend {
#[allow(clippy::type_complexity)]
fn list_tasks(
&self,
filter: &Filter,
) -> impl Future<Output = Result<Vec<Task<Self::Compact>>, Self::Error>> + Send;
}
pub trait ListAllTasks: WireFormatBackend + Backend {
#[allow(clippy::type_complexity)]
fn list_all_tasks(
&self,
filter: &Filter,
) -> impl Future<Output = Result<Vec<Task<Self::Compact>>, Self::Error>> + Send;
}
pub trait Metrics: Backend {
fn global(&self) -> impl Future<Output = Result<Vec<Statistic>, Self::Error>> + Send;
fn fetch_by_queue(&self) -> impl Future<Output = Result<Vec<Statistic>, Self::Error>> + Send;
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct QueueInfo {
pub name: String,
pub stats: Vec<Statistic>,
pub workers: Vec<String>,
pub activity: Vec<usize>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct RunningWorker {
pub id: String,
pub queue: String,
pub backend: String,
pub started_at: u64,
pub last_heartbeat: u64,
pub layers: String,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct Filter {
#[cfg_attr(feature = "serde", serde(default))]
pub status: Option<Status>,
#[cfg_attr(feature = "serde", serde(default = "default_page"))]
pub page: u32,
#[cfg_attr(feature = "serde", serde(default))]
pub page_size: Option<u32>,
}
impl Filter {
#[must_use]
pub fn offset(&self) -> u32 {
(self.page - 1) * self.page_size.unwrap_or(DEFAULT_PAGE_SIZE)
}
#[must_use]
pub fn limit(&self) -> u32 {
self.page_size.unwrap_or(DEFAULT_PAGE_SIZE)
}
}
#[cfg(feature = "serde")]
fn default_page() -> u32 {
1
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone)]
pub struct Statistic {
pub title: String,
pub stat_type: StatType,
pub value: String,
pub priority: Option<u64>,
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[non_exhaustive]
pub enum StatType {
Timestamp,
#[default]
Number,
Decimal,
Percentage,
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum ParseStatTypeError {
#[error("invalid stat type: `{0}`")]
InvalidStatType(String),
}
impl FromStr for StatType {
type Err = ParseStatTypeError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Timestamp" => Ok(Self::Timestamp),
"Decimal" => Ok(Self::Decimal),
"Percentage" => Ok(Self::Percentage),
"Number" => Ok(Self::Number),
_ => Err(ParseStatTypeError::InvalidStatType(s.to_owned())),
}
}
}