1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Webhook delivery for Rust backed by Postgres or SQLite.
//!
//! HMAC-SHA256 signing, exponential backoff retry, dead letter queue,
//! idempotent sends, event-type filtering, circuit breaker, and SSRF protection —
//! all backed by your existing database. No Redis, no external queue service.
//!
//! # Quick start
//!
//! ```rust,no_run
//! use webhooksmith::WebhookEngine;
//! use serde_json::json;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let engine = WebhookEngine::builder()
//! .database_url("postgres://user:pass@localhost/mydb")
//! .build()
//! .await?;
//!
//! engine.migrate().await?;
//!
//! let endpoint = engine
//! .register("https://partner.example.com/webhooks", "your-signing-secret")
//! .await?;
//!
//! engine.send("order.created", json!({"id": 1001}), endpoint.id).await?;
//!
//! // Blocks until the process exits; use run_graceful() for signal handling
//! engine.run().await;
//! }
//! ```
//!
//! # Transactional outbox
//!
//! Write your business data and the webhook event in the **same database transaction**.
//! If the transaction rolls back, the event never exists.
//!
//! ```rust,ignore
//! # use webhooksmith::WebhookEngine;
//! # use serde_json::json;
//! # use uuid::Uuid;
//! # async fn example(engine: WebhookEngine, endpoint_id: Uuid, order_id: i64) -> Result<(), Box<dyn std::error::Error>> {
//! let mut tx = engine.pool().begin().await?;
//!
//! // Your business logic — use any sqlx query here
//! sqlx::query!("INSERT INTO orders (id) VALUES ($1)", order_id)
//! .execute(&mut *tx).await?;
//!
//! // Only queued if this transaction commits
//! engine.send_in_tx("order.created", json!({"id": order_id}), endpoint_id, &mut tx).await?;
//!
//! tx.commit().await?;
//! # Ok(()) }
//! ```
//!
//! # Features
//!
//! | Feature | Description |
//! |---|---|
//! | `postgres` (default) | Full transactional outbox using `SELECT FOR UPDATE SKIP LOCKED` |
//! | `sqlite` | `SqliteEngine` — same API, no Postgres required |
//!
//! # See also
//!
//! - [`WebhookEngine`] — core engine (Postgres)
//! - `SqliteEngine` — SQLite engine (requires `features = ["sqlite"]`)
//! - [`worker::DeliveryWorker`] — background delivery loop
//! - [Full documentation](https://github.com/biplabku/webhooksmith)
pub
// Re-export for testing and advanced use
pub use ;
pub use WebhookEngine;
pub use ;
pub use ;
pub use event_matches_filter;
pub use ;
pub use SqliteEngine;