webhookgate-sdk 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,10 @@ WebhookGate guarantees **no duplicate webhook side effects**.
|
|
|
4
4
|
|
|
5
5
|
https://webhookgate.com
|
|
6
6
|
|
|
7
|
+
WebhookGate exists to draw a hard line in reality:
|
|
8
|
+
|
|
9
|
+
> **Past this point, duplicate side effects cannot exist.**
|
|
10
|
+
|
|
7
11
|
It does this by combining:
|
|
8
12
|
- **durable webhook intake and de-duplication** at the gateway layer, and
|
|
9
13
|
- a **consumer-side idempotency SDK** that makes duplicate side effects **structurally impossible** within the consumer.
|
|
@@ -14,7 +18,7 @@ WebhookGate sits in front of webhook consumers and ensures that each `(provider,
|
|
|
14
18
|
|
|
15
19
|
## Documentation (problem-first)
|
|
16
20
|
|
|
17
|
-
If you want to understand *why* WebhookGate exists — not just how to use it —
|
|
21
|
+
If you want to understand *why* WebhookGate exists — not just how to use it — start here:
|
|
18
22
|
|
|
19
23
|
- **Why Webhook Retries Cause Duplicate Side Effects**
|
|
20
24
|
https://webhookgate.com/docs/why-retries-cause-duplicates
|
|
@@ -25,24 +29,27 @@ If you want to understand *why* WebhookGate exists — not just how to use it
|
|
|
25
29
|
- **What a Real Guarantee Requires**
|
|
26
30
|
https://webhookgate.com/docs/what-a-real-guarantee-requires
|
|
27
31
|
|
|
28
|
-
These explain the distributed-systems constraints that make ad-hoc idempotency fragile,
|
|
32
|
+
These documents explain the distributed-systems constraints that make ad-hoc idempotency fragile,
|
|
29
33
|
and the architectural boundaries required to make duplicate side effects impossible.
|
|
30
34
|
|
|
31
35
|
---
|
|
32
36
|
|
|
33
37
|
## What WebhookGate guarantees (MVP)
|
|
34
38
|
|
|
35
|
-
WebhookGate provides a durable webhook
|
|
39
|
+
WebhookGate provides a durable webhook **inbox** in front of your consumer.
|
|
36
40
|
|
|
37
41
|
### Gateway guarantees
|
|
38
42
|
|
|
39
43
|
- **Exactly-once acceptance** per `(provider, eventId)`
|
|
40
44
|
- **De-duplication at intake**: repeated deliveries of the same event are not re-accepted
|
|
41
|
-
- **Durable delivery jobs + transport retries
|
|
45
|
+
- **Durable delivery jobs + transport retries**
|
|
42
46
|
- **Deterministic Idempotency-Key propagation** on every downstream delivery
|
|
43
47
|
|
|
44
|
-
The gateway delivers events **at-least-once** downstream, always with the same
|
|
45
|
-
|
|
48
|
+
The gateway delivers events **at-least-once** downstream, always with the same Idempotency-Key, even across retries, crashes, or restarts.
|
|
49
|
+
|
|
50
|
+
> Intake is exactly-once.
|
|
51
|
+
> Delivery is at-least-once.
|
|
52
|
+
> Side effects are at-most-once.
|
|
46
53
|
|
|
47
54
|
---
|
|
48
55
|
|
|
@@ -54,23 +61,24 @@ The consumer SDK converts delivery guarantees into **hard correctness**.
|
|
|
54
61
|
|
|
55
62
|
- **At-most-once execution** of the handler per Idempotency-Key
|
|
56
63
|
- **Duplicate deliveries never re-run side effects**
|
|
57
|
-
- **Crash-safe behavior**: if the process crashes mid-handler, the handler is never re-entered
|
|
58
|
-
- **
|
|
59
|
-
- **Transactional DB effects** for database operations performed via the provided
|
|
64
|
+
- **Crash-safe behavior**: if the process crashes mid-handler, the handler is never re-entered
|
|
65
|
+
- **Terminal failure semantics**: if the handler throws, the idempotency row transitions to 'failed' and is never re-entered automatically
|
|
66
|
+
- **Transactional DB effects** for database operations performed via the provided DB client
|
|
60
67
|
|
|
61
68
|
Once a key is successfully claimed, the handler will **never** be executed again — even if the process crashes, restarts, or receives the same event repeatedly.
|
|
62
69
|
|
|
63
|
-
> Result: side effects are never duplicated
|
|
70
|
+
> Result: **side effects are never duplicated**.
|
|
64
71
|
|
|
65
72
|
---
|
|
66
73
|
|
|
67
74
|
## Exactly-once effects (clarified)
|
|
68
75
|
|
|
69
|
-
WebhookGate guarantees that your handler runs at most once per Idempotency-Key.
|
|
76
|
+
WebhookGate guarantees that your handler runs **at most once** per Idempotency-Key.
|
|
70
77
|
|
|
71
78
|
If your handler calls external systems (payments, email providers, APIs), those systems must respect idempotency keys to achieve end-to-end exactly-once effects across system boundaries.
|
|
72
79
|
|
|
73
80
|
This design deliberately favors **safety over re-execution**:
|
|
81
|
+
|
|
74
82
|
WebhookGate will never risk double-charging, double-emailing, or double-writing.
|
|
75
83
|
|
|
76
84
|
---
|
|
@@ -99,36 +107,70 @@ app.post(
|
|
|
99
107
|
);
|
|
100
108
|
```
|
|
101
109
|
|
|
110
|
+
There are no flags, retries, or callbacks to manage.
|
|
111
|
+
|
|
112
|
+
If safety cannot be proven, execution is refused (fail-closed).
|
|
113
|
+
|
|
102
114
|
---
|
|
103
115
|
|
|
104
|
-
## Proof:
|
|
116
|
+
## Proof: no duplicate side effects (60 seconds)
|
|
105
117
|
|
|
106
|
-
1. Start Postgres
|
|
107
|
-
2. Install dependencies
|
|
118
|
+
1. Start Postgres
|
|
119
|
+
2. Install dependencies
|
|
120
|
+
```bash
|
|
108
121
|
npm install
|
|
109
|
-
|
|
122
|
+
```
|
|
123
|
+
3. Start the consumer
|
|
124
|
+
```bash
|
|
110
125
|
npm run consumer
|
|
111
|
-
|
|
126
|
+
```
|
|
127
|
+
4. Start the gateway
|
|
128
|
+
```bash
|
|
112
129
|
npm run dev
|
|
113
|
-
|
|
130
|
+
```
|
|
131
|
+
5. Send a replay storm
|
|
132
|
+
```bash
|
|
114
133
|
npm run chaos -- evt_test_1
|
|
134
|
+
```
|
|
115
135
|
|
|
116
|
-
Result
|
|
136
|
+
**Result**
|
|
117
137
|
- Gateway receives 50 duplicate events
|
|
118
|
-
- Consumer executes the handler once
|
|
119
|
-
-
|
|
138
|
+
- Consumer executes the handler **once**
|
|
139
|
+
- `/stats` shows `charges = 1`
|
|
140
|
+
|
|
141
|
+
### Crash test
|
|
120
142
|
|
|
121
|
-
|
|
122
|
-
- Start consumer with CRASH_ONCE=true
|
|
143
|
+
- Start consumer with `CRASH_ONCE=true`
|
|
123
144
|
- Re-run chaos
|
|
124
145
|
- Restart consumer
|
|
125
|
-
|
|
146
|
+
|
|
147
|
+
**Charges still = 1**
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Relationship to webhook-replay
|
|
152
|
+
|
|
153
|
+
- **webhook-replay** detects unsafe handlers (local / CI)
|
|
154
|
+
- **WebhookGate** enforces safety in production
|
|
155
|
+
|
|
156
|
+
If `webhook-replay` reports:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
❌ UNSAFE UNDER RETRY
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
WebhookGate is the production fix.
|
|
126
163
|
|
|
127
164
|
---
|
|
128
165
|
|
|
129
166
|
## When you need production-grade durability
|
|
130
167
|
|
|
131
|
-
|
|
168
|
+
Local correctness is not enough once retries, crashes, and distributed failure enter the picture.
|
|
169
|
+
|
|
170
|
+
WebhookGate adds:
|
|
171
|
+
- durable intake
|
|
172
|
+
- replay protection
|
|
173
|
+
- enforcement instead of best-effort guarantees
|
|
132
174
|
|
|
133
175
|
Learn more:
|
|
134
176
|
- Overview: https://webhookgate.com
|