pub struct WebhookChannelManager {
pub retry_base: Duration,
pub max_retries: u32,
pub max_backoff: Duration,
pub circuit_threshold: u32,
/* private fields */
}Expand description
Webhook notification channel with built-in retry logic. The
manager keeps an internal map of subscriptions → target URL, and
deliver_all() POSTs the Activity Streams payload to each target.
Sprint 6 C additions (ADR-058):
- Optional RFC 9421 HTTP Message Signatures via [
Self::with_signer]. Retry-Afterhonoured on 429.- 410 Gone treated as
FatalDrop; other 4xx retried as transient. - Full-jitter exponential back-off bounded by
max_backoff. - Simple per-manager circuit breaker — consecutive failures are
counted across
deliver_onecalls; once the threshold is reached further calls short-circuit toWebhookDelivery::TransientRetrywith acircuit openreason until a successful delivery resets the counter.
Fields§
§retry_base: DurationExponential backoff base (starting delay). Default 500ms.
max_retries: u32Max retry attempts on 5xx. Default 3 (preserved for backward
compat; tests that exercise Sprint 6 semantics call
with_max_attempts explicitly).
max_backoff: DurationCap on a single back-off wait. Default 1h.
circuit_threshold: u32Sprint 6 C: consecutive failures before the circuit opens.
Implementations§
Source§impl WebhookChannelManager
impl WebhookChannelManager
pub fn new() -> Self
Sourcepub fn with_client(client: Client) -> Self
pub fn with_client(client: Client) -> Self
Create a manager with a specific reqwest::Client (used in
tests with wiremock).
Sourcepub fn with_max_attempts(self, attempts: u32) -> Self
pub fn with_max_attempts(self, attempts: u32) -> Self
Override the max attempts (1 == no retries). Default 5.
Sourcepub fn with_max_backoff(self, max: Duration) -> Self
pub fn with_max_backoff(self, max: Duration) -> Self
Override the maximum single back-off wait. Default 1h.
Sourcepub fn with_circuit_threshold(self, threshold: u32) -> Self
pub fn with_circuit_threshold(self, threshold: u32) -> Self
Override the consecutive-failure threshold that opens the breaker. Default 10.
Sourcepub fn circuit_open(&self) -> bool
pub fn circuit_open(&self) -> bool
True iff the breaker is currently open.
Sourcepub fn consecutive_failures(&self) -> u32
pub fn consecutive_failures(&self) -> u32
Current consecutive-failure count. Public for observability and tests.
Sourcepub fn reset_circuit(&self)
pub fn reset_circuit(&self)
Reset the consecutive-failure counter (e.g. after operator intervention). Test hook, also exposed for admin UIs.
pub async fn subscribe(&self, topic: &str, target_url: &str) -> Subscription
pub async fn unsubscribe(&self, id: &str)
pub async fn active_subscriptions(&self) -> usize
Sourcepub async fn deliver_one(
&self,
url: &str,
note: &ChangeNotification,
) -> WebhookDelivery
pub async fn deliver_one( &self, url: &str, note: &ChangeNotification, ) -> WebhookDelivery
Deliver a single event to a single webhook URL, with full Sprint 6 C retry / back-off / circuit-breaker semantics.
Sourcepub async fn deliver_all(
&self,
note: &ChangeNotification,
topic_matches: impl Fn(&str) -> bool,
) -> Vec<(String, WebhookDelivery)>
pub async fn deliver_all( &self, note: &ChangeNotification, topic_matches: impl Fn(&str) -> bool, ) -> Vec<(String, WebhookDelivery)>
Deliver the notification to every matching subscription. Returns the per-subscription outcome.
Sourcepub async fn pump_from_storage(
self,
rx: Receiver<StorageEvent>,
pod_base: String,
)
pub async fn pump_from_storage( self, rx: Receiver<StorageEvent>, pod_base: String, )
Attach the manager to a storage event stream. Each event is translated into an Activity Streams notification and delivered to every subscription whose topic is a prefix of the event path.
Trait Implementations§
Source§impl Clone for WebhookChannelManager
impl Clone for WebhookChannelManager
Source§fn clone(&self) -> WebhookChannelManager
fn clone(&self) -> WebhookChannelManager
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Default for WebhookChannelManager
impl Default for WebhookChannelManager
Source§impl Notifications for WebhookChannelManager
impl Notifications for WebhookChannelManager
Source§fn subscribe<'life0, 'async_trait>(
&'life0 self,
subscription: Subscription,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn subscribe<'life0, 'async_trait>(
&'life0 self,
subscription: Subscription,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Source§fn unsubscribe<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn unsubscribe<'life0, 'life1, 'async_trait>(
&'life0 self,
id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn publish<'life0, 'life1, 'async_trait>(
&'life0 self,
topic: &'life1 str,
notification: ChangeNotification,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn publish<'life0, 'life1, 'async_trait>(
&'life0 self,
topic: &'life1 str,
notification: ChangeNotification,
) -> Pin<Box<dyn Future<Output = Result<(), PodError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
topic.