use std::time::Duration;
use apalis_core::worker::context::WorkerContext;
use serde::{Deserialize, Serialize};
pub(crate) use apalis_core::backend::queue::Queue;
const ACTIVE_TASKS_LIST: &str = "{queue}:active";
const WORKERS_SET: &str = "{queue}:workers";
const DEAD_TASKS_SET: &str = "{queue}:dead";
const DONE_TASKS_SET: &str = "{queue}:done";
const FAILED_TASKS_SET: &str = "{queue}:failed";
const INFLIGHT_TASKS_SET: &str = "{queue}:inflight";
const TASK_DATA_HASH: &str = "{queue}:data";
const JOB_META_HASH: &str = "{queue}:meta";
const SCHEDULED_TASKS_SET: &str = "{queue}:scheduled";
const SIGNAL_LIST: &str = "{queue}:signal";
const IDEMPOTENCY_KEY_SET: &str = "{queue}:idempotency";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Config {
#[serde(default = "default_batch_size")]
pub batch_size: usize,
#[serde(default = "default_heartbeat_interval")]
pub heartbeat_interval: Duration,
#[serde(default = "default_missed_heartbeats")]
pub missed_heartbeats: usize,
pub queue: Queue,
pub database_url: Option<String>,
#[serde(default = "default_events")]
pub lock_tasks: bool,
#[serde(default = "default_events")]
pub persist_results: bool,
#[serde(default = "default_events")]
pub emit_events: bool,
#[serde(default)]
pub idempotency_ttl: Option<Duration>,
}
impl Default for Config {
fn default() -> Self {
Self {
batch_size: 10,
heartbeat_interval: Duration::from_secs(30),
missed_heartbeats: 10,
queue: Queue::from("default"),
database_url: None,
lock_tasks: true,
persist_results: true,
emit_events: true,
idempotency_ttl: None,
}
}
}
fn default_batch_size() -> usize {
10
}
fn default_heartbeat_interval() -> Duration {
Duration::from_secs(30)
}
fn default_missed_heartbeats() -> usize {
2
}
fn default_events() -> bool {
true
}
impl Config {
#[must_use]
pub fn batch_size(mut self, size: usize) -> Self {
assert!(size > 0, "batch size cannot be 0");
self.batch_size = size;
self
}
#[must_use]
pub fn heartbeat_interval(mut self, interval: Duration) -> Self {
self.heartbeat_interval = interval;
self
}
#[must_use]
pub fn queue(mut self, queue: impl AsRef<str>) -> Self {
self.queue = Queue::from(queue.as_ref());
self
}
#[must_use]
pub fn missed_heartbeats(mut self, missed_heartbeats: usize) -> Self {
self.missed_heartbeats = missed_heartbeats;
self
}
#[must_use]
pub fn database_url(mut self, database_url: impl Into<String>) -> Self {
self.database_url = Some(database_url.into());
self
}
#[must_use]
pub fn lock_tasks(mut self, lock_tasks: bool) -> Self {
self.lock_tasks = lock_tasks;
self
}
#[must_use]
pub fn emit_events(mut self, emit_events: bool) -> Self {
self.emit_events = emit_events;
self
}
#[must_use]
pub fn persist_results(mut self, persist_results: bool) -> Self {
self.persist_results = persist_results;
self
}
#[must_use]
pub fn idempotency_ttl(mut self, ttl: Option<Duration>) -> Self {
self.idempotency_ttl = ttl;
self
}
#[must_use]
pub fn orphaned_duration(&self) -> Duration {
self.heartbeat_interval * self.missed_heartbeats as u32
}
pub fn active_jobs_list(&self) -> String {
ACTIVE_TASKS_LIST.replace("{queue}", self.queue.as_ref())
}
pub fn workers_set(&self) -> String {
WORKERS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn worker_metadata_key(&self, worker: &WorkerContext) -> String {
format!("{}:workers:metadata:{}", self.queue.as_ref(), worker.name())
}
pub fn dead_jobs_set(&self) -> String {
DEAD_TASKS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn done_jobs_set(&self) -> String {
DONE_TASKS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn failed_jobs_set(&self) -> String {
FAILED_TASKS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn inflight_jobs_set(&self) -> String {
INFLIGHT_TASKS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn inflight_set_for(&self, worker: &WorkerContext) -> String {
format!("{}:{}", self.inflight_jobs_set(), worker.name())
}
pub fn job_data_hash(&self) -> String {
TASK_DATA_HASH.replace("{queue}", self.queue.as_ref())
}
pub fn job_meta_hash(&self) -> String {
JOB_META_HASH.replace("{queue}", self.queue.as_ref())
}
pub fn scheduled_jobs_set(&self) -> String {
SCHEDULED_TASKS_SET.replace("{queue}", self.queue.as_ref())
}
pub fn signal_list(&self) -> String {
SIGNAL_LIST.replace("{queue}", self.queue.as_ref())
}
pub fn idempotency_key_set(&self) -> String {
IDEMPOTENCY_KEY_SET.replace("{queue}", self.queue.as_ref())
}
}