use std::collections::BTreeSet;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::flow::FlowRef;
use crate::step::HumanStepIR;
use crate::vocab::{ErrorClass, HandlerHook};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[schemars(extend(
"if" = { "properties": { "hook": { "const": "onError" } }, "required": ["hook"] },
"else" = { "not": { "required": ["errorClasses"] } }
))]
pub struct HandlerBinding {
pub hook: HandlerHook,
#[serde(skip_serializing_if = "Option::is_none")]
#[schemars(length(min = 1))]
pub error_classes: Option<BTreeSet<ErrorClass>>,
pub action: HandlerAction,
#[schemars(range(min = 1))]
pub max_triggers: u32,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind", rename_all = "camelCase")]
#[schemars(deny_unknown_fields)]
pub enum HandlerAction {
Retry {
policy: RetryPolicy,
},
Continue,
Escalate {
human: Box<HumanStepIR>,
},
Abort,
#[serde(rename_all = "camelCase")]
Repair {
flow_ref: FlowRef,
},
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct RetryPolicy {
#[schemars(range(min = 1))]
pub max_attempts: u32,
pub backoff_ms: BackoffMs,
#[schemars(length(min = 1))]
pub retry_on: BTreeSet<ErrorClass>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(untagged)]
pub enum BackoffMs {
Fixed(#[schemars(range(min = 0))] serde_json::Number),
Schedule(BackoffSchedule),
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(inline)]
pub struct BackoffSchedule {
#[schemars(range(min = 0))]
pub initial: serde_json::Number,
#[schemars(range(min = 1))]
pub factor: serde_json::Number,
#[schemars(range(min = 0))]
pub max: serde_json::Number,
}