hooksmith-core
Shared building blocks for the hooksmith family of webhook crates.
This crate is not a webhook client itself. It provides the common trait, HTTP
client, error type, and utilities that every *_hook service crate builds on.
What's inside
WebhookSender trait
The single abstraction every service crate implements. Application code can be generic over the backend:
use WebhookSender;
async
send_batch
A default method that fans out a slice of messages concurrently using
[futures::future::join_all]. One failure does not abort the others — you
get back one Result per message.
let results = sender.send_batch.await;
for result in results
HttpClient
A thin wrapper around [reqwest::Client] with a sensible 30-second default
timeout. Every *_hook crate holds one and calls post_json to fire requests.
use HttpClient;
let client = new;
let resp = client.post_json.await?;
Pass your own reqwest::Client to share a connection pool or customise TLS:
let inner = builder
.timeout
.build?;
let client = with_reqwest;
post_json_with_retry
Retries failed requests with exponential backoff according to a
[RetryPolicy]. Pair it with the tracing feature to get per-attempt
observability at no extra effort.
use ;
use Duration;
let policy = RetryPolicy ;
let resp = client.post_json_with_retry.await?;
RetryPolicy
Controls how post_json_with_retry behaves.
| Field | Type | Default | Description |
|---|---|---|---|
max_attempts |
u32 |
3 |
Total tries including the first (clamped to ≥ 1) |
base_delay |
Duration |
500 ms |
Delay before the first retry (doubles each time) |
jitter |
bool |
true |
Add a random sub-delay to spread concurrent retries |
// Use defaults
let policy = default;
// Customise
let policy = RetryPolicy ;
CoreError
A transport-level error enum that service-specific errors should wrap via
#[from], so generic code can match on network or JSON failures without
knowing which service is in use.
Variants:
| Variant | Wraps | When |
|---|---|---|
Network |
reqwest::Error |
HTTP or connection-level failure |
Json |
serde_json::Error |
Serialisation / deserialisation |
Feature flags
| Flag | What it enables |
|---|---|
mock |
Exposes hooksmith_core::mock::MockSender for use in tests |
tracing |
Emits tracing spans around every post_json call (URL, status, latency) |
mock — MockSender
A WebhookSender that captures messages in memory instead of hitting a real
endpoint. Add it to dev-dependencies so it is only compiled for tests:
[]
= { = "*", = ["mock"] }
use MockSender;
let sender: = new;
sender.send.await.unwrap;
assert_eq!;
assert_eq!;
tracing — observability spans
Enable the tracing feature to have every post_json call automatically
instrumented with an info_span named hooksmith.post_json. The span records:
url— the request URLstatus— HTTP status code (on success)latency_ms— wall-clock time for the requesterror— error string (on failure)
[]
= { = "*", = ["tracing"] }
No other code changes are required — wire up your tracing subscriber as
normal and the spans appear automatically.
Using hooksmith-core in a service crate
-
Add it to your
Cargo.toml:[] = { = "*" } -
Implement
WebhookSender:use ; -
send_batchis inherited for free from the default trait implementation.