mammoth 0.1.1 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c304ab7c88b218cf4a09e3e672a914510636656941248f9dfd6bff00f1ac454
4
- data.tar.gz: 40107e6a3400c92cc72f0c57a41d9b757b49d9bc30e51f8fb7b3a287502db723
3
+ metadata.gz: 19aba46c6ef2ae1099287e37281015b747dde1b32c94cbd1c8ec8a23d6b1a19b
4
+ data.tar.gz: 21430175d42c71e83eaede3f70390a87d760a9ac2d8b9b4dedcfb446feefaaa0
5
5
  SHA512:
6
- metadata.gz: c8f4f13c376eeb33b4768d06883131be409664411501ee3c1d525e508e4109531a58f4dc937d38576aaa9d84c2af6352b30d90b1744597b4c263322c2323dc56
7
- data.tar.gz: 85cab27b802aec51af685afac69e10f0b56682d512b9271ff407b383807dab37d9d0d875624ba3a7d718cf1c684de2fbb106de87ad7635c22aef5f347780e39d
6
+ metadata.gz: b29ea1b4ace38ffa6eb155251dbcd0056e400849aa6a37093d4ecec09cc314089c36523b22b3bbbf898b0247fb6918e3320ef0f14b24d280fed91df2a2287f9a
7
+ data.tar.gz: b2e6f58f77884641970e838a5aaa8c2c1ef0a2531b868a53c3ae8ee450387128b04b39c2661e5fac507c82d05b11739a913285c8f9c2052db137810881073a3e
data/CHANGELOG.md CHANGED
@@ -2,6 +2,60 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.0
6
+
7
+ ### Added
8
+
9
+ - Added transaction-level delivery mode using `TransactionEnvelope`.
10
+ - Added transaction-aware buffering and aggregation of CDC events.
11
+ - Added transaction webhook example demonstrating end-to-end delivery from PostgreSQL logical replication to HTTP webhook.
12
+ - Added source position propagation for transaction deliveries.
13
+ - Added concurrent delivery runtime integration powered by `cdc-concurrent`.
14
+ - Added `DeliveryProcessor` abstraction for runtime execution.
15
+ - Added `TransactionEnvelopeSerializer` for transaction payload serialization.
16
+ - Added rich self-documenting YAML configuration examples.
17
+ - Added configurable webhook HTTP headers through `webhook.headers`.
18
+ - Added environment-backed webhook headers through `webhook.header_env` for secrets such as bearer tokens.
19
+ - Added optional HMAC-SHA256 webhook request signing through `webhook.signing`.
20
+ - Added E2E coverage for duplicate delivery suppression, transaction webhook payloads, dead-letter persistence, and signed/authenticated webhook requests.
21
+ - Added Helm chart rendering for delivery runtime, webhook auth headers, signing, and secret-backed webhook environment values.
22
+
23
+ ### Changed
24
+
25
+ - Transaction delivery now emits a single webhook payload per committed PostgreSQL transaction.
26
+ - CDC events belonging to the same database transaction are now grouped into a single `TransactionEnvelope`.
27
+ - Delivery pipeline now preserves transaction boundaries from ingestion through webhook delivery.
28
+ - Replication slot creation now correctly honors configured temporary/permanent slot settings.
29
+ - Concurrent runtime integration now complies with `cdc-concurrent` processor safety requirements.
30
+ - Webhook delivery now applies configured static headers, env-backed headers, and per-request signature headers before sending payloads.
31
+
32
+ ### Fixed
33
+
34
+ - Fixed transaction delivery incorrectly emitting one transaction payload per CDC event.
35
+ - Fixed missing source position metadata in transaction deliveries.
36
+ - Fixed replication slot option handling for boolean configuration values.
37
+ - Fixed transaction webhook example startup and producer execution flow.
38
+ - Fixed `cdc-concurrent` runtime compatibility and processor validation failures.
39
+ - Fixed quality gate drift by restoring passing coverage, RuboCop, Steep, and YARD validation.
40
+
41
+ ### Examples
42
+
43
+ - Added `examples/transaction_webhook` demonstrating:
44
+
45
+ - PostgreSQL logical replication
46
+ - TransactionEnvelope aggregation
47
+ - Transaction-level webhook delivery
48
+ - Source position propagation
49
+ - Concurrent delivery runtime integration
50
+
51
+ ### Internal
52
+
53
+ - Established the foundation for transaction-aware checkpointing.
54
+ - Established the foundation for ordering policies based on transaction boundaries.
55
+ - Established the foundation for future multi-destination fanout delivery.
56
+ - Added real `cdc-concurrent` runtime coverage outside the unit-test fake runtime.
57
+
58
+
5
59
  ## [0.1.1] - 2026-06-17
6
60
 
7
61
  Documentation and operational guidance release.
data/README.md CHANGED
@@ -13,7 +13,7 @@ PostgreSQL
13
13
 
14
14
  CDC Ecosystem source adapter
15
15
 
16
- CDC::Core::ChangeEvent
16
+ CDC::Core::TransactionEnvelope
17
17
 
18
18
  Mammoth
19
19
 
@@ -24,10 +24,6 @@ Webhook
24
24
  JSON Schema validation, local SQLite operational state, and the CDC Ecosystem's
25
25
  shared vocabulary so operators can inspect, recover, and reason about delivery.
26
26
 
27
- 🦣 Mammoth is intentionally boring infrastructure. It uses YAML configuration,
28
- JSON Schema validation, local SQLite operational state, and the CDC Ecosystem's
29
- shared vocabulary so operators can inspect, recover, and reason about delivery.
30
-
31
27
  ## Documentation
32
28
 
33
29
  Documentation site:
@@ -105,6 +101,50 @@ Mammoth stores operational memory in SQLite:
105
101
  - `checkpoints`
106
102
  - `dead_letters`
107
103
 
104
+ ## Performance
105
+
106
+ Mammoth scales downstream delivery throughput using the `cdc-concurrent` runtime while maintaining a single PostgreSQL logical replication stream.
107
+
108
+ ### Concurrent Delivery Benchmark
109
+
110
+ Environment:
111
+
112
+ * 10,000 transactions
113
+ * 4 events per transaction
114
+ * 40,000 total events
115
+
116
+ #### Fast Downstream (10ms)
117
+
118
+ | Concurrency | Transactions/sec |
119
+ | ----------- | ---------------: |
120
+ | 1 | 96.50 |
121
+ | 25 | 2419.65 |
122
+
123
+ #### Realistic Webhook (50ms)
124
+
125
+ | Concurrency | Transactions/sec |
126
+ | ----------- | ---------------: |
127
+ | 1 | 19.85 |
128
+ | 25 | 495.11 |
129
+
130
+ Observed throughput improved from:
131
+
132
+ - 96.50 → 2419.65 transactions/sec (10ms sink latency)
133
+ - 19.85 → 495.11 transactions/sec (50ms sink latency)
134
+
135
+ when increasing delivery concurrency from 1 to 25.
136
+
137
+ The benchmark demonstrates near-linear scaling of delivery throughput without increasing PostgreSQL replication connections.
138
+
139
+ See:
140
+
141
+ - docs/BENCHMARKS.md
142
+ - examples/transaction_webhook
143
+
144
+ For full benchmark methodology and results see:
145
+
146
+ See [Benchmarks](docs/BENCHMARKS.md).
147
+
108
148
  ## E2E
109
149
 
110
150
  ```bash
@@ -1,30 +1,265 @@
1
1
  # yaml-language-server: $schema=./mammoth.schema.json
2
2
 
3
+ # Mammoth example configuration.
4
+ #
5
+ # This file is intentionally verbose. It is both a runnable starting point and
6
+ # the primary operator-facing documentation for local development, Kubernetes
7
+ # values, and production deployments.
8
+ #
9
+ # Architecture reminder:
10
+ #
11
+ # PostgreSQL
12
+ # ↓
13
+ # one logical replication slot
14
+ # ↓
15
+ # one WAL stream
16
+ # ↓
17
+ # Mammoth delivery runtime
18
+ # ↓
19
+ # one or more downstream deliveries
20
+ #
21
+ # Runtime concurrency affects downstream delivery work only. It does not create
22
+ # additional PostgreSQL replication slots or replication connections.
23
+
3
24
  mammoth:
25
+ # Human-readable Mammoth instance name.
26
+ #
27
+ # Used in logs, status output, metrics, and future operational dashboards.
28
+ # Keep this stable per environment.
29
+ #
30
+ # Examples:
31
+ # local_mammoth
32
+ # staging_mammoth
33
+ # production_mammoth
4
34
  name: local_mammoth
5
35
 
6
36
  postgres:
37
+ # PostgreSQL host reachable from the Mammoth process or pod.
38
+ #
39
+ # For local development this is usually localhost.
40
+ # In Kubernetes this is usually a service DNS name.
7
41
  host: localhost
42
+
43
+ # PostgreSQL port.
8
44
  port: 5432
45
+
46
+ # Source database name.
9
47
  database: app_development
48
+
49
+ # PostgreSQL user used by Mammoth.
50
+ #
51
+ # This user must be able to connect in replication mode and read publication
52
+ # metadata. In many deployments this means a dedicated replication user.
10
53
  username: mammoth
54
+
55
+ # Environment variable containing the PostgreSQL password.
56
+ #
57
+ # The password is intentionally not stored directly in YAML. In Kubernetes,
58
+ # set this variable from a Secret.
11
59
  password_env: MAMMOTH_POSTGRES_PASSWORD
12
60
 
13
61
  replication:
62
+ # PostgreSQL logical replication slot name.
63
+ #
64
+ # Permanent slots survive PostgreSQL restarts and preserve WAL until Mammoth
65
+ # acknowledges progress. Changing this value creates a separate replication
66
+ # position and should be treated as an operational migration.
67
+ #
68
+ # Recommended:
69
+ # development: mammoth_dev
70
+ # staging: mammoth_staging
71
+ # production: mammoth_prod
14
72
  slot: mammoth_prod
73
+
74
+ # PostgreSQL publications to subscribe to.
75
+ #
76
+ # Publications define which table changes PostgreSQL sends to Mammoth.
77
+ # Create them explicitly in production so the database boundary is clear.
78
+ #
79
+ # Example SQL:
80
+ # CREATE PUBLICATION mammoth_publication FOR TABLE users, orders;
15
81
  publications:
16
82
  - mammoth_publication
83
+
84
+ # Optional start LSN for advanced recovery or controlled replay.
85
+ #
86
+ # Leave unset for normal operation. Mammoth will use its checkpoint store and
87
+ # the replication slot position.
88
+ #
89
+ # Example:
90
+ # start_lsn: "0/16B6C50"
91
+ #
92
+ # start_lsn:
93
+
94
+ # Automatically create the replication slot if it does not exist.
95
+ #
96
+ # true:
97
+ # Convenient for development, demos, and first-time bootstrap.
98
+ #
99
+ # false:
100
+ # Recommended for production when slots are DBA-managed infrastructure.
17
101
  auto_create_slot: false
102
+
103
+ # Use a temporary replication slot.
104
+ #
105
+ # false:
106
+ # Recommended for durable Mammoth deployments. The slot survives reconnects
107
+ # and PostgreSQL restarts.
108
+ #
109
+ # true:
110
+ # Useful for experiments only. A temporary slot disappears when the
111
+ # replication session ends and is not suitable for durable delivery.
18
112
  temporary_slot: false
113
+
114
+ # Standby feedback interval in seconds.
115
+ #
116
+ # Mammoth sends periodic feedback while streaming so PostgreSQL knows the
117
+ # consumer is alive and can advance slot state safely.
118
+ #
119
+ # Lower values:
120
+ # faster liveness/feedback visibility, slightly more network chatter
121
+ #
122
+ # Higher values:
123
+ # less chatter, slower visibility into consumer progress
124
+ #
125
+ # Recommended:
126
+ # development: 2.0
127
+ # production: 5.0-10.0
19
128
  feedback_interval: 10.0
20
129
 
130
+ delivery:
131
+ # Delivery granularity.
132
+ #
133
+ # event:
134
+ # Deliver each change event independently. This has lower latency but weaker
135
+ # transaction-level semantics.
136
+ #
137
+ # transaction:
138
+ # Deliver a complete TransactionEnvelope as one payload. This is the safer
139
+ # default because checkpointing can advance only after the whole transaction
140
+ # has been delivered successfully.
141
+ #
142
+ # Recommended:
143
+ # transaction
144
+ unit: transaction
145
+
146
+ ordering:
147
+ # Ordering policy used by the delivery runtime.
148
+ #
149
+ # global:
150
+ # Preserve complete WAL/stream order. Safest, lowest concurrency.
151
+ #
152
+ # transaction:
153
+ # Preserve transaction commit order. Recommended for transaction delivery.
154
+ #
155
+ # relation:
156
+ # Preserve order per table/relation while allowing unrelated tables to run
157
+ # concurrently.
158
+ #
159
+ # primary_key:
160
+ # Preserve order per row identity while allowing unrelated rows to run
161
+ # concurrently.
162
+ #
163
+ # none:
164
+ # Best-effort delivery order. Highest freedom for concurrency, but only use
165
+ # when destinations are idempotent and ordering-insensitive.
166
+ #
167
+ # Recommended:
168
+ # transaction
169
+ scope: transaction
170
+
171
+ runtime:
172
+ # Runtime adapter for downstream delivery work.
173
+ #
174
+ # inline:
175
+ # Execute delivery work synchronously in the caller. Best for debugging and
176
+ # the safest compatibility mode.
177
+ #
178
+ # concurrent:
179
+ # Use CDC::Concurrent::ProcessorPool for I/O-heavy delivery workloads such as
180
+ # webhook HTTP calls, retry sleeps/backoff, and future multi-destination
181
+ # fanout.
182
+ adapter: concurrent
183
+
184
+ # Number of downstream delivery workers.
185
+ #
186
+ # This affects webhook/destination delivery concurrency only.
187
+ # It does NOT create additional replication slots.
188
+ # It does NOT create additional PostgreSQL replication connections.
189
+ #
190
+ # Recommended:
191
+ # development: 1
192
+ # small production: 2-5
193
+ # webhook-heavy production: 10-50, after soak testing
194
+ concurrency: 1
195
+
196
+ # Preserve configured ordering while using the runtime.
197
+ #
198
+ # true:
199
+ # Safer default. Related work is kept in order according to delivery.ordering.
200
+ #
201
+ # false:
202
+ # Higher throughput potential, but only safe for idempotent destinations that
203
+ # do not depend on event order.
204
+ preserve_order: true
205
+
206
+ # Optional runtime timeout in seconds.
207
+ #
208
+ # Leave blank to let destination-specific timeouts control delivery behavior.
209
+ # Useful later for bounding end-to-end processor execution.
210
+ timeout_seconds:
211
+
21
212
  webhook:
213
+ # Destination name used in logs, dead-letter records, and future metrics.
22
214
  name: primary_webhook
215
+
216
+ # Destination URL for delivered CDC payloads.
217
+ #
218
+ # For delivery.unit: transaction, the payload represents a TransactionEnvelope.
219
+ # For delivery.unit: event, the payload represents one change event.
23
220
  url: https://example.com/webhooks/postgres
221
+
222
+ # HTTP timeout in seconds for webhook delivery attempts.
24
223
  timeout_seconds: 5
25
224
 
225
+ # Optional static HTTP headers sent with every webhook request.
226
+ #
227
+ # Use these for non-secret routing or receiver metadata. Secret values should
228
+ # use header_env instead.
229
+ headers:
230
+ X-Mammoth-Source: local_mammoth
231
+
232
+ # Optional HTTP headers whose values are read from environment variables.
233
+ #
234
+ # Example:
235
+ # header_env:
236
+ # Authorization: MAMMOTH_WEBHOOK_AUTHORIZATION
237
+ header_env: {}
238
+
239
+ # Optional HMAC-SHA256 webhook signing.
240
+ #
241
+ # When enabled, Mammoth signs:
242
+ #
243
+ # <timestamp>.<json request body>
244
+ #
245
+ # using the secret from secret_env, then sends the timestamp and signature in
246
+ # configurable headers. The signature value is prefixed with "sha256=".
247
+ #
248
+ # signing:
249
+ # algorithm: hmac_sha256
250
+ # secret_env: MAMMOTH_WEBHOOK_SIGNING_SECRET
251
+ # signature_header: X-Mammoth-Signature
252
+ # timestamp_header: X-Mammoth-Timestamp
253
+
26
254
  retry:
255
+ # Maximum delivery attempts before the event/envelope is moved to the dead
256
+ # letter store.
27
257
  max_attempts: 5
258
+
259
+ # Retry delay schedule in seconds.
260
+ #
261
+ # Mammoth uses this as progressive backoff. If attempts exceed the length of
262
+ # this list, the final value may be reused by the delivery worker.
28
263
  schedule_seconds:
29
264
  - 1
30
265
  - 5
@@ -33,7 +268,21 @@ retry:
33
268
  - 300
34
269
 
35
270
  sqlite:
271
+ # Local operational database path.
272
+ #
273
+ # Mammoth stores checkpoints, delivery attempts, and dead-letter records here.
274
+ # In Kubernetes, back this path with a PersistentVolumeClaim.
36
275
  path: data/mammoth.db
37
276
 
38
277
  logging:
278
+ # Log verbosity.
279
+ #
280
+ # debug:
281
+ # Very chatty; useful while diagnosing delivery or replication behavior.
282
+ #
283
+ # info:
284
+ # Recommended normal default.
285
+ #
286
+ # warn/error:
287
+ # Quieter production modes.
39
288
  level: info