use crate::{
backend::queue::Queue,
task::{
ExecutionContext, Task,
attempt::Attempt,
extensions::Extensions,
metadata::{Metadata, MetadataStore},
status::Status,
task_id::TaskId,
},
};
use std::{
fmt::Debug,
sync::Arc,
time::{Duration, SystemTime, UNIX_EPOCH},
};
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[must_use = "TaskBuilder is used to construct a Task. Ensure to call `.build()` to create the Task instance."]
pub struct TaskBuilder<Args> {
pub(super) args: Args,
pub(super) ctx: ExecutionContext,
}
impl<Args> TaskBuilder<Args> {
pub fn new(args: Args) -> Self {
Self {
args,
ctx: ExecutionContext::default(),
}
}
pub fn with_metadata(mut self, metadata: MetadataStore) -> Self {
self.ctx.metadata = metadata;
self
}
pub fn with_data(mut self, data: Extensions) -> Self {
self.ctx.data = data;
self
}
pub fn data<D: Clone + Send + Sync + 'static>(mut self, value: D) -> Self {
self.ctx.data.insert(value);
self
}
pub fn metadata<M>(mut self, value: &M) -> Self
where
M: Metadata,
M::Error: Debug,
{
value
.inject(&mut self.ctx.metadata)
.expect("Could not add Metadata");
self
}
pub fn task_id(mut self, task_id: TaskId) -> Self {
self.ctx.task_id = Some(task_id);
self
}
pub fn attempt(mut self, attempt: usize) -> Self {
self.ctx.attempt = Attempt::new_with_value(attempt);
self
}
pub fn status(mut self, status: Status) -> Self {
self.ctx.status = status.into();
self
}
pub fn max_attempts(mut self, max_attempts: usize) -> Self {
self.ctx.max_attempts = Some(max_attempts);
self
}
pub fn priority(mut self, priority: usize) -> Self {
self.ctx.priority = Some(priority);
self
}
pub fn queue(mut self, queue: Queue) -> Self {
self.ctx.queue = Some(queue);
self
}
pub fn run_at_timestamp(mut self, timestamp: u64) -> Self {
self.ctx.run_at = Some(timestamp);
self
}
pub fn run_at_time(mut self, time: SystemTime) -> Self {
let timestamp = time
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
self.ctx.run_at = Some(timestamp);
self
}
pub fn run_after(mut self, delay: Duration) -> Self {
let now = SystemTime::now();
let run_time = now + delay;
let timestamp = run_time
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs();
self.ctx.run_at = Some(timestamp);
self
}
pub fn run_in_seconds(self, seconds: u64) -> Self {
self.run_after(Duration::from_secs(seconds))
}
pub fn run_in_minutes(self, minutes: u64) -> Self {
self.run_after(Duration::from_secs(minutes * 60))
}
pub fn run_in_hours(self, hours: u64) -> Self {
self.run_after(Duration::from_secs(hours * 3600))
}
pub fn idempotency_key<S: AsRef<str>>(mut self, idempotency_key: S) -> Self {
self.ctx.idempotency_key = Some(idempotency_key.as_ref().to_owned());
self
}
pub fn done_at(mut self, done_at: Option<u64>) -> Self {
self.ctx.done_at = done_at;
self
}
pub fn lock_at(mut self, lock_at: Option<u64>) -> Self {
self.ctx.lock_at = lock_at;
self
}
pub fn lock_by(mut self, lock_by: Option<String>) -> Self {
self.ctx.lock_by = lock_by;
self
}
pub fn build(self) -> Task<Args> {
Task {
args: self.args,
ctx: Arc::new(self.ctx),
}
}
}
impl<Args> TaskBuilder<Args> {
pub fn try_map_args<F, NewArgs, Err>(self, f: F) -> Result<TaskBuilder<NewArgs>, Err>
where
F: FnOnce(Args) -> Result<NewArgs, Err>,
{
Ok(TaskBuilder {
args: f(self.args)?,
ctx: self.ctx,
})
}
pub fn map_args<F, NewArgs>(self, f: F) -> TaskBuilder<NewArgs>
where
F: FnOnce(Args) -> NewArgs,
{
TaskBuilder {
args: f(self.args),
ctx: self.ctx,
}
}
pub fn map_context<F>(self, f: F) -> Self
where
F: FnOnce(ExecutionContext) -> ExecutionContext,
{
Self {
args: self.args,
ctx: f(self.ctx),
}
}
}