Skip to main content

ApprovalConfig

Struct ApprovalConfig 

Source
pub struct ApprovalConfig { /* private fields */ }
Expand description

Configuration for a human approval step.

When the workflow reaches an approval step, the run transitions to AwaitingApproval and waits for a human to approve or reject via the API.

A gate can carry an SLA: with_deadline arms a timer persisted alongside the step, and on_timeout says what happens when it fires. The timer lives in the database, so it survives an API or worker restart.

A gate can also require several approvers: requiring takes the Approvers the handler computed in Rust, from its typed input and earlier step outputs. They decide how many distinct approvals the gate needs and which groups may vote. A config without approvers is resolved by one approval from anyone allowed to answer the gate.

§Examples

use ironflow_engine::config::{ApprovalConfig, Approvers};

let config = ApprovalConfig::new("Deploy to production?");
assert_eq!(config.message(), "Deploy to production?");
assert!(config.timeout_seconds().is_none());

let payment = ApprovalConfig::new("Release the payment?")
    .requiring(Approvers::at_least(2).from_groups(["finance"]).because("amount > 10k"));
assert_eq!(payment.approvers().map(Approvers::required), Some(2));

Implementations§

Source§

impl ApprovalConfig

Source

pub fn new(message: &str) -> Self

Create a new approval config with the given message.

§Examples
use ironflow_engine::config::ApprovalConfig;

let config = ApprovalConfig::new("Approve this deployment?");
assert_eq!(config.message(), "Approve this deployment?");
Source

pub fn with_timeout_seconds(self, seconds: u64) -> Self

Set an auto-reject timeout in seconds.

If no approval or rejection is received within this duration, the run is automatically rejected (marked as Failed).

This is the legacy spelling of with_deadline_secs with an implicit EscalationPolicy::AutoReject. It is now actually enforced by the escalator; a config that sets both keeps the explicit deadline.

§Examples
use ironflow_engine::config::{ApprovalConfig, EscalationPolicy};

let config = ApprovalConfig::new("Approve?")
    .with_timeout_seconds(3600);
assert_eq!(config.timeout_seconds(), Some(3600));
assert_eq!(config.effective_deadline_secs(), Some(3600));
assert_eq!(config.effective_policy(), EscalationPolicy::AutoReject);
Source

pub fn with_deadline(self, deadline: Duration) -> Self

Set the SLA deadline of this gate.

Sub-second precision is dropped: the deadline is stored in whole seconds.

§Panics

Panics if deadline rounds down to zero seconds.

§Examples
use std::time::Duration;
use ironflow_engine::config::ApprovalConfig;

let config = ApprovalConfig::new("Approve?")
    .with_deadline(Duration::from_secs(1800));
assert_eq!(config.deadline(), Some(Duration::from_secs(1800)));
Source

pub fn with_deadline_secs(self, secs: u64) -> Self

Set the SLA deadline of this gate, in seconds.

§Panics

Panics if secs is zero: a gate that expires the instant it opens can never be approved by a human.

§Examples
use ironflow_engine::config::ApprovalConfig;

let config = ApprovalConfig::new("Approve?").with_deadline_secs(1800);
assert_eq!(config.deadline_secs(), Some(1800));
Source

pub fn on_timeout(self, policy: EscalationPolicy) -> Self

Set the policy applied when the deadline fires.

§Examples
use ironflow_engine::config::{ApprovalConfig, EscalationPolicy};

let config = ApprovalConfig::new("Approve?")
    .with_deadline_secs(3600)
    .on_timeout(EscalationPolicy::AutoApprove);
assert_eq!(config.effective_policy(), EscalationPolicy::AutoApprove);
Source

pub fn assigned_to(self, assignee: Assignee) -> Self

Assign the gate to a user or group.

§Panics

Panics if the assignee name is empty or only whitespace.

§Examples
use ironflow_engine::config::ApprovalConfig;
use ironflow_store::entities::Assignee;

let config = ApprovalConfig::new("Approve?").assigned_to(Assignee::group("release-managers"));
assert_eq!(config.assignee(), Some(&Assignee::group("release-managers")));
Source

pub fn requiring(self, approvers: Approvers) -> Self

Require the given approvers. A later call replaces an earlier one.

The engine records them on the gate when it opens, as an ApprovalRequirement; that record stays the source of truth on replay and resume.

§Examples
use ironflow_engine::config::{ApprovalConfig, Approvers};

let config = ApprovalConfig::new("Approve?")
    .requiring(Approvers::at_least(3).from_groups(["finance", "board"]));
assert_eq!(config.approvers().map(Approvers::required), Some(3));
Source

pub fn approvers(&self) -> Option<&Approvers>

The approvers this gate requires, if any were set.

§Examples
use ironflow_engine::config::ApprovalConfig;

assert!(ApprovalConfig::new("Approve?").approvers().is_none());
Source

pub fn message(&self) -> &str

The approval message displayed to reviewers.

Source

pub fn timeout_seconds(&self) -> Option<u64>

Optional auto-reject timeout in seconds.

Source

pub fn deadline(&self) -> Option<Duration>

The configured SLA deadline, if any.

§Examples
use std::time::Duration;
use ironflow_engine::config::ApprovalConfig;

let config = ApprovalConfig::new("Approve?").with_deadline_secs(60);
assert_eq!(config.deadline(), Some(Duration::from_secs(60)));
Source

pub fn deadline_secs(&self) -> Option<u64>

The configured SLA deadline in seconds, if any.

Source

pub fn on_timeout_policy(&self) -> Option<&EscalationPolicy>

The configured escalation policy, if any.

Source

pub fn assignee(&self) -> Option<&Assignee>

The user or group the gate is assigned to, if any.

Source

pub fn effective_deadline_secs(&self) -> Option<u64>

The deadline actually enforced, in seconds.

with_deadline_secs wins; the legacy with_timeout_seconds is honoured as a fallback so configs written before escalation existed finally behave the way their documentation always promised.

§Examples
use ironflow_engine::config::ApprovalConfig;

let legacy = ApprovalConfig::new("Approve?").with_timeout_seconds(7200);
assert_eq!(legacy.effective_deadline_secs(), Some(7200));

let both = legacy.with_deadline_secs(60);
assert_eq!(both.effective_deadline_secs(), Some(60));

assert_eq!(ApprovalConfig::new("Approve?").effective_deadline_secs(), None);
Source

pub fn effective_policy(&self) -> EscalationPolicy

The policy applied when the deadline fires. Defaults to EscalationPolicy::AutoReject, matching the documented meaning of timeout_seconds.

§Examples
use ironflow_engine::config::{ApprovalConfig, EscalationPolicy};

let config = ApprovalConfig::new("Approve?").with_deadline_secs(60);
assert_eq!(config.effective_policy(), EscalationPolicy::AutoReject);

Trait Implementations§

Source§

impl Clone for ApprovalConfig

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ApprovalConfig

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for ApprovalConfig

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for ApprovalConfig

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more