pub struct Webhooks { /* private fields */ }Expand description
A module that delivers signed outbound webhooks.
Implementations§
Source§impl Webhooks
impl Webhooks
Sourcepub fn max_attempts(self, max_attempts: u32) -> Self
pub fn max_attempts(self, max_attempts: u32) -> Self
Dead-letter a delivery after this many failed attempts instead of
five. Values outside 1..=1_000 clamp to the nearest bound — the
same range WEBHOOKS_MAX_ATTEMPTS must pass validation with.
WEBHOOKS_MAX_ATTEMPTS overrides this when set.
Sourcepub async fn create_endpoint(
&self,
db: &dyn Database,
subject: &str,
url: &str,
event_types: &[&str],
now: &str,
) -> Result<CreatedEndpoint, EndpointError>
pub async fn create_endpoint( &self, db: &dyn Database, subject: &str, url: &str, event_types: &[&str], now: &str, ) -> Result<CreatedEndpoint, EndpointError>
Registers one delivery endpoint for subject and returns its
signing secret — the only time the secret is ever handed back.
List the endpoints later and the secret is not in the answer.
event_types is a filter; an empty slice means “everything”
(*). A URL that is not http(s), or a filter naming an event type
that could never ride a header, is refused here rather than failed
at every delivery.
§Errors
EndpointError for a malformed URL or subject, or a filter
naming an unusable event type, and DbError when the insert
fails.
Sourcepub async fn endpoints(
&self,
db: &dyn Database,
subject: &str,
) -> Result<Vec<Endpoint>, DbError>
pub async fn endpoints( &self, db: &dyn Database, subject: &str, ) -> Result<Vec<Endpoint>, DbError>
Sourcepub async fn delete_endpoint(
&self,
db: &dyn Database,
subject: &str,
endpoint_id: &str,
) -> Result<bool, DbError>
pub async fn delete_endpoint( &self, db: &dyn Database, subject: &str, endpoint_id: &str, ) -> Result<bool, DbError>
Sourcepub async fn publish(
&self,
db: &dyn Database,
subject: &str,
event_type: &str,
data: &Value,
now: &str,
) -> Result<Published, PublishError>
pub async fn publish( &self, db: &dyn Database, subject: &str, event_type: &str, data: &Value, now: &str, ) -> Result<Published, PublishError>
Fans one event out to every endpoint of subject whose filter
matches event_type, and returns the outbox INSERTs — append
Published::into_statements to the caller’s own
db.batch_atomic(..), so the event is durable exactly when the
state change that caused it is. Nothing is written until that
batch runs.
An event no endpoint matches is Published::endpoints == 0 and
nothing else — not an error: “nobody subscribed to that” is an
ordinary answer.
§Errors
PublishError::InvalidEventType for an event type that could
never ride the Cratefield-Event-Type header (refused before any
read, so it cannot burn attempts later), and DbError when the
endpoint read fails.
Sourcepub async fn drain_with(
&self,
ctx: &ModuleContext,
) -> Result<DrainReport, DeliveryError>
pub async fn drain_with( &self, ctx: &ModuleContext, ) -> Result<DrainReport, DeliveryError>
Delivers every due outbox row this pass can lease, through the
ports of ctx. Call it from the venture’s scheduled entry
point — a cron invocation builds no router, so the context must be
the one the runtime hands in, not one parked at router-build time.
Each row is signed and delivered once per pass: 2xx completes it,
anything else retries with exponential backoff (410 Gone and
SSRF-blocked destinations dead-letter immediately), and
MAX_ATTEMPTS failures dead-letter it for
Webhooks::replay. A per-row failure never aborts the pass.
§Errors
DeliveryError when a port is missing or the claim fails.
Sourcepub async fn replay(
&self,
db: &dyn Database,
subject: &str,
dead_letter_id: &str,
now: &str,
) -> Result<bool, DbError>
pub async fn replay( &self, db: &dyn Database, subject: &str, dead_letter_id: &str, now: &str, ) -> Result<bool, DbError>
Re-enqueues one dead letter of subject — attempts reset to zero —
and removes it, in one batch. The delivery log keeps the history.
false — the letter left exactly where it was — when the id names
no dead letter of this subject, or when the letter’s endpoint
is gone: a replay into a deleted endpoint would consume the letter
and then be dropped by the drain, destroying the event for good.
§Errors
DbError when the read or the batch fails.
Sourcepub async fn deliveries(
&self,
db: &dyn Database,
subject: &str,
limit: u64,
) -> Result<Vec<Delivery>, DbError>
pub async fn deliveries( &self, db: &dyn Database, subject: &str, limit: u64, ) -> Result<Vec<Delivery>, DbError>
Sourcepub async fn dead_letters(
&self,
db: &dyn Database,
subject: &str,
limit: u64,
) -> Result<Vec<DeadLetter>, DbError>
pub async fn dead_letters( &self, db: &dyn Database, subject: &str, limit: u64, ) -> Result<Vec<DeadLetter>, DbError>
A subject’s dead letters, oldest first — the ids
Webhooks::replay takes.
§Errors
DbError when the read fails.
Trait Implementations§
Source§impl Module for Webhooks
impl Module for Webhooks
Source§fn personal_data(&self) -> &'static [PersonalDataSet]
fn personal_data(&self) -> &'static [PersonalDataSet]
Every table keys its rows on the subject the event (or endpoint)
belongs to, so erasure reaches all four; the endpoint secret is
credential material and is exported redacted.
Source§fn router(&self, _ctx: ModuleContext) -> Router
fn router(&self, _ctx: ModuleContext) -> Router
Deliberately empty: see the crate documentation — the Rust API is this module’s surface, and a management route would need an auth decision this crate does not make.
Source§fn scheduled<'a>(
&'a self,
ctx: &'a ModuleContext,
cron: &'a str,
) -> BoxFuture<'a, Result<(), AnyError>>
fn scheduled<'a>( &'a self, ctx: &'a ModuleContext, cron: &'a str, ) -> BoxFuture<'a, Result<(), AnyError>>
The recovery half of the outbox contract: whatever a caller’s
immediate drain never got to is delivered on the next tick, and
the dead letters pile up here for Webhooks::replay.
Source§fn requires(&self) -> &'static [Port]
fn requires(&self) -> &'static [Port]
Source§fn tables(&self) -> &'static [&'static str]
fn tables(&self) -> &'static [&'static str]
Source§fn migrations(&self) -> Migrations
fn migrations(&self) -> Migrations
Source§fn validate_config(&self, cfg: &dyn Config) -> Result<(), ConfigError>
fn validate_config(&self, cfg: &dyn Config) -> Result<(), ConfigError>
Source§fn harness_api(&self) -> u32
fn harness_api(&self) -> u32
Harness::build.Source§fn depends_on(&self) -> &'static [&'static str]
fn depends_on(&self) -> &'static [&'static str]
Source§fn emits(&self) -> &'static [&'static str]
fn emits(&self) -> &'static [&'static str]
"<module>.<event>"), listed by
/__health.Source§fn public_writes(&self) -> bool
fn public_writes(&self) -> bool
Source§fn public_write_policy(&self) -> RoutePolicy
fn public_write_policy(&self) -> RoutePolicy
RoutePolicy on
(issue #143). Read moreSource§fn signature_verification(&self) -> SignatureVerification
fn signature_verification(&self) -> SignatureVerification
RoutePolicy::Signature
deliveries (issue #533): how a webhook handler checks a machine
signature before acting. Read moreSource§fn max_body_bytes(&self, _cfg: &dyn Config) -> usize
fn max_body_bytes(&self, _cfg: &dyn Config) -> usize
Source§fn self_check(&self) -> Vec<String>
fn self_check(&self) -> Vec<String>
Source§fn well_known(&self) -> Option<Router>
fn well_known(&self) -> Option<Router>
/.well-known, for
spec-mandated discovery documents (OIDC openid-configuration,
jwks.json) that must live outside /v1 (issue #46). Paths are
relative to the prefix: register /jwks.json, not
/.well-known/jwks.json. Read moreSource§fn surface(&self) -> Surface
fn surface(&self) -> Surface
Action::input::<Body>()), so the
declaration cannot drift from the route. Harness::build
validates it; GET /__surface serves the composition. Default:
nothing, and a module that declares nothing renders nothing.