persistent_scheduler/core/
model.rsuse crate::{
core::{
retry::{RetryPolicy, RetryStrategy},
task_kind::TaskKind,
},
generate_token, utc_now,
};
use serde::{Deserialize, Serialize};
use std::fmt;
type LinearInterval = u32;
type ExponentialBase = u32;
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct TaskMeta {
pub id: String, pub task_key: String, pub task_params: String, pub queue_name: String, pub updated_at: i64, pub status: TaskStatus, pub stopped_reason: Option<String>, pub last_error: Option<String>, pub last_run: i64, pub next_run: i64, pub kind: TaskKind, pub success_count: u32, pub failure_count: u32, pub runner_id: Option<String>, pub retry_strategy: Retry, pub retry_interval: u32, pub base_interval: u32, pub delay_seconds: u32, pub max_retries: Option<u32>, pub cron_schedule: Option<String>, pub cron_timezone: Option<String>, pub is_repeating: bool, pub repeat_interval: u32, pub heartbeat_at: i64, }
#[derive(Clone, Debug, Eq, Default, PartialEq, Serialize, Deserialize, Hash)]
pub enum TaskStatus {
#[default]
Scheduled,
Running,
Success,
Failed,
Removed,
Stopped,
}
impl fmt::Display for TaskStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let status_str = match self {
TaskStatus::Scheduled => "Scheduled",
TaskStatus::Running => "Running",
TaskStatus::Success => "Success",
TaskStatus::Failed => "Failed",
TaskStatus::Removed => "Removed",
TaskStatus::Stopped => "Stopped",
};
write!(f, "{}", status_str)
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
pub enum Retry {
#[default]
Linear,
Exponential,
}
impl fmt::Display for Retry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Retry::Linear => write!(f, "Linear"),
Retry::Exponential => write!(f, "Exponential"),
}
}
}
fn to_retry(retry_policy: RetryPolicy) -> (Retry, LinearInterval, ExponentialBase) {
match retry_policy.strategy {
RetryStrategy::Linear { interval } => (Retry::Linear, interval, Default::default()),
RetryStrategy::Exponential { base } => (Retry::Exponential, Default::default(), base),
}
}
impl TaskMeta {
pub fn new(
task_key: String,
task_params: String,
queue_name: String,
kind: TaskKind,
retry_policy: RetryPolicy,
cron_schedule: Option<String>,
cron_timezone: Option<String>,
is_repeating: bool,
repeat_interval: Option<u32>,
delay_seconds: u32,
) -> Self {
let (retry_strategy, retry_interval, base_interval) = to_retry(retry_policy);
let repeat_interval = match repeat_interval {
Some(v) => v,
None => Default::default(),
};
Self {
id: generate_token!(),
task_key,
task_params,
queue_name,
updated_at: utc_now!(),
status: TaskStatus::Scheduled,
last_error: Default::default(),
last_run: Default::default(),
next_run: Default::default(),
kind,
stopped_reason: Default::default(),
success_count: Default::default(),
failure_count: Default::default(),
runner_id: Default::default(),
retry_strategy,
retry_interval,
base_interval,
max_retries: retry_policy.max_retries,
cron_schedule,
cron_timezone,
is_repeating,
repeat_interval,
heartbeat_at: Default::default(),
delay_seconds,
}
}
pub fn retry_policy(&self) -> RetryPolicy {
let strategy = match self.retry_strategy {
Retry::Linear => RetryStrategy::Linear {
interval: self.retry_interval,
},
Retry::Exponential => RetryStrategy::Exponential {
base: self.base_interval,
},
};
RetryPolicy {
strategy,
max_retries: self.max_retries,
}
}
}