use crate::Context;
use async_trait::async_trait;
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::time::Duration;
#[derive(Debug)]
pub enum TriggerResult {
Skip,
Fire(Option<Context<serde_json::Value>>),
}
impl TriggerResult {
pub fn should_fire(&self) -> bool {
matches!(self, TriggerResult::Fire(_))
}
pub fn into_context(self) -> Option<Context<serde_json::Value>> {
match self {
TriggerResult::Fire(ctx) => ctx,
TriggerResult::Skip => None,
}
}
pub fn context_hash(&self) -> String {
match self {
TriggerResult::Skip => "skip".to_string(),
TriggerResult::Fire(None) => "fire_no_context".to_string(),
TriggerResult::Fire(Some(ctx)) => {
let mut hasher = DefaultHasher::new();
if let Ok(serialized) = serde_json::to_string(ctx.data()) {
serialized.hash(&mut hasher);
}
format!("{:016x}", hasher.finish())
}
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum TriggerError {
#[error("Trigger poll error: {message}")]
PollError { message: String },
#[error("Context error: {0}")]
ContextError(#[from] crate::error::ContextError),
}
#[async_trait]
pub trait Trigger: Send + Sync + fmt::Debug {
fn name(&self) -> &str;
fn poll_interval(&self) -> Duration;
fn allow_concurrent(&self) -> bool;
async fn poll(&self) -> Result<TriggerResult, TriggerError>;
fn cron_expression(&self) -> Option<String> {
None
}
}