use std::{
cmp::Ordering,
sync::Arc,
time::{Duration, Instant},
};
use reifydb_core::Result;
use reifydb_engine::StandardEngine;
use reifydb_sub_api::{Priority, TaskHandle};
use crate::tracker::CancellationToken;
pub struct InternalTaskContext {
pub cancel_token: Option<CancellationToken>,
pub engine: StandardEngine,
}
impl InternalTaskContext {
pub fn is_cancelled(&self) -> bool {
self.cancel_token.as_ref().map(|t| t.is_cancelled()).unwrap_or(false)
}
}
pub trait PoolTask: Send + Sync {
fn execute(&self, ctx: &InternalTaskContext) -> Result<()>;
fn priority(&self) -> Priority {
Priority::Normal
}
fn name(&self) -> &str {
"unnamed_task"
}
fn can_retry(&self) -> bool {
false
}
fn max_retries(&self) -> usize {
3
}
}
pub(crate) struct ScheduledTask {
pub handle: TaskHandle,
pub task: Arc<dyn PoolTask>,
pub next_run: Instant,
pub interval: Option<Duration>,
pub priority: Priority,
}
impl ScheduledTask {
pub fn new(
handle: TaskHandle,
task: Box<dyn PoolTask>,
next_run: Instant,
interval: Option<Duration>,
priority: Priority,
) -> Self {
Self {
handle,
task: Arc::from(task),
next_run,
interval,
priority,
}
}
}
pub struct PeriodicTask {
inner: Arc<dyn PoolTask>,
interval: Duration,
priority: Priority,
}
impl PeriodicTask {
pub fn new(task: Arc<dyn PoolTask>, interval: Duration, priority: Priority) -> Self {
Self {
inner: task,
interval,
priority,
}
}
}
impl PoolTask for PeriodicTask {
fn execute(&self, ctx: &InternalTaskContext) -> Result<()> {
self.inner.execute(ctx)
}
fn priority(&self) -> Priority {
self.priority
}
fn name(&self) -> &str {
self.inner.name()
}
}
pub struct PrioritizedTask {
pub task: Box<dyn PoolTask>,
pub priority: Priority,
pub submitted_at: Instant,
}
impl PrioritizedTask {
pub fn new(task: Box<dyn PoolTask>) -> Self {
let priority = task.priority();
Self {
task,
priority,
submitted_at: Instant::now(),
}
}
}
impl PartialEq for PrioritizedTask {
fn eq(&self, other: &Self) -> bool {
self.priority == other.priority && self.submitted_at == other.submitted_at
}
}
impl Eq for PrioritizedTask {}
impl PartialOrd for PrioritizedTask {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for PrioritizedTask {
fn cmp(&self, other: &Self) -> Ordering {
match self.priority.cmp(&other.priority) {
Ordering::Equal => {
other.submitted_at.cmp(&self.submitted_at)
}
other => other,
}
}
}
pub struct InternalClosureTask<F>
where
F: Fn(&InternalTaskContext) -> Result<()> + Send + Sync,
{
name: String,
priority: Priority,
closure: F,
}
impl<F> InternalClosureTask<F>
where
F: Fn(&InternalTaskContext) -> Result<()> + Send + Sync,
{
pub fn new(name: impl Into<String>, priority: Priority, closure: F) -> Self {
Self {
name: name.into(),
priority,
closure,
}
}
}
impl<F> PoolTask for InternalClosureTask<F>
where
F: Fn(&InternalTaskContext) -> Result<()> + Send + Sync,
{
fn execute(&self, ctx: &InternalTaskContext) -> Result<()> {
(self.closure)(ctx)
}
fn priority(&self) -> Priority {
self.priority
}
fn name(&self) -> &str {
&self.name
}
}