mammoth 1.5.3 → 1.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46b595362901f1421a5859f5bf085eba22ea1cd611d727d957fc652c6fd9716d
4
- data.tar.gz: a3a0cf5f02e354913f93043af7301016ff708e802f44098aa833cd38e7860bf5
3
+ metadata.gz: e8384a9b1f089aa255d05a7139f3af6acc6458ae83c9e6b16ad3c70b90354243
4
+ data.tar.gz: 57d7f1f4a4de5d3086900f11a60bfaaeab6269ede33dffab1bbbed49e8988648
5
5
  SHA512:
6
- metadata.gz: b27e4e3cfca6c73f5a9965847a5423838dae7b178e84ae4cc8a126fe899b3a987f5da5b50c8d8e1cf25d7c698d4fdb26b9f8f3c4a70d1fef98068c126c8edffd
7
- data.tar.gz: 011eddde2e7573e675d10cb87ffdd0a5da02d330b2575ac58c1f13500649fd18811076554e2c0e49de21b20f30b1f9bc92b2ada1d01ec69a69a6b0ac61ebda49
6
+ metadata.gz: c96d457e14aeace5000dbdbe0614008447c9c0dd319c324d235db269fb25a53af573a2b87f4f4c9c0bcd39127975cc919730cb08b632e96972271c8459216a22
7
+ data.tar.gz: 0cbf023b425053a16d74ad5198377b9a4dc11988a85920888c2a8e7bdc83d2986bfc212b703715a2297bb3035d2792916810684d935d7728a01385f022c0b095
data/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@
6
6
 
7
7
  ## Unreleased
8
8
 
9
+ ## 1.5.4 - 2026-08-26
10
+
11
+ - Upgraded runtime depency sqlite3 from 2.9.5 to 2.9.6 because of security/stability reasons
12
+ as outline by this PR https://github.com/kanutocd/mammoth/pull/21 by @dependabot
13
+ - Fixed the Dockerfile security issue that was flagged by Trivy by unpinning the ruby base image's digest hash
14
+ and explicitly include an `apt-get upgrade`
15
+
9
16
  ## 1.5.3 - 2026-07-26
10
17
 
11
18
  ### Fixed
data/README.md CHANGED
@@ -21,9 +21,9 @@
21
21
  [![Tested Against PostgreSQL 14–18](https://img.shields.io/badge/Tested%20Against-PostgreSQL%2014--18-336791?logo=postgresql&logoColor=white)](https://github.com/kanutocd/mammoth/blob/main/.github/workflows/ci.yml#L50)
22
22
  [![License](https://img.shields.io/badge/License-MIT-22C55E)](LICENSE.txt)
23
23
 
24
-
25
- Mammoth is a self-hosted PostgreSQL event relay focused on reliable delivery
26
- of database change events.
24
+ Mammoth is a self-hosted PostgreSQL change-event relay focused on reliable
25
+ delivery of database change events to downstream systems. It turns PostgreSQL
26
+ logical replication streams into observable, recoverable delivery pipelines.
27
27
 
28
28
  This repository contains the **Mammoth Data Plane**, the open-source runtime in
29
29
  the broader Mammoth ecosystem:
@@ -52,6 +52,50 @@ Mammoth is intentionally boring infrastructure. It uses YAML configuration,
52
52
  JSON Schema validation, local SQLite operational state, and the CDC Ecosystem's
53
53
  shared vocabulary so operators can inspect, recover, and reason about delivery.
54
54
 
55
+ ## Why Mammoth?
56
+
57
+ Mammoth is designed for applications where PostgreSQL is the system of record,
58
+ including Rails applications that need reliable reactions to database state
59
+ changes without coupling every workflow to request handling.
60
+
61
+ Applications increasingly need to react to changes in their primary database:
62
+
63
+ - update search indexes after data changes
64
+ - synchronize external systems
65
+ - trigger integrations and asynchronous workflows
66
+ - build analytics pipelines
67
+ - maintain audit and event histories
68
+
69
+ Many systems start with polling, application callbacks, or database triggers.
70
+ As applications grow, these approaches can become increasingly difficult to
71
+ operate, recover from failures, and reason about.
72
+
73
+ Mammoth uses PostgreSQL logical replication as the authoritative change stream
74
+ and provides a reliable delivery layer between PostgreSQL and downstream
75
+ consumers.
76
+
77
+ The goal is simple: make database change delivery explicit, observable, and
78
+ recoverable.
79
+
80
+ ## What makes Mammoth different?
81
+
82
+ Mammoth deliberately focuses on the delivery boundary between PostgreSQL and
83
+ downstream consumers rather than trying to become a general-purpose streaming
84
+ platform.
85
+
86
+ It treats change delivery as an operational concern:
87
+
88
+ - transactional change-event handling
89
+ - durable delivery state
90
+ - explicit checkpoint management
91
+ - replayable failures
92
+ - observable runtime behavior
93
+
94
+ Unlike application callbacks, Mammoth does not require workflows to execute
95
+ inside request handling. Unlike broad streaming platforms, it provides a
96
+ focused PostgreSQL-native model for teams that need reliable change delivery
97
+ without adopting a larger streaming infrastructure stack.
98
+
55
99
  ## Mammoth ecosystem
56
100
 
57
101
  The Data Plane is one component of the broader Mammoth ecosystem. The companion
@@ -62,17 +106,56 @@ See the [Mammoth ecosystem overview](docs/ECOSYSTEM.md) for public scope,
62
106
  integration boundaries, and roadmap status. Planned capabilities are
63
107
  directional and do not represent a release commitment.
64
108
 
109
+ ## Reference Implementation
110
+
111
+ The [Spherical Mammoth](https://github.com/kanutocd/spherical-mammoth)
112
+ repository is the production-shaped, cloud-native reference environment for
113
+ deploying, validating, and operating the Mammoth Data Plane.
114
+
115
+ It demonstrates how Mammoth integrates into a complete application environment:
116
+
117
+ ```text
118
+ Application services
119
+
120
+ PostgreSQL transactional state
121
+
122
+ PostgreSQL logical replication
123
+
124
+ Mammoth Data Plane
125
+
126
+ Webhook delivery
127
+
128
+ Independent downstream consumers
129
+ ```
130
+
131
+ **Spherical Mammoth provides:**
132
+
133
+ - a realistic SaaS-style application workflow
134
+ - PostgreSQL-backed business state
135
+ - Ory Kratos identity lifecycle integration
136
+ - polyglot downstream consumers
137
+ - Docker Compose and Kubernetes deployment paths
138
+ - Helm-based deployment
139
+ - OpenTofu-managed cloud infrastructure examples
140
+ - CDC validation and failure scenarios
141
+
142
+ The repository is intentionally separate from Mammoth OSS. Mammoth provides the
143
+ CDC relay data plane; Spherical Mammoth demonstrates how that data plane can be
144
+ deployed, exercised, and operated in a cloud-native environment.
145
+
146
+ See:
147
+
148
+ - [Spherical Mammoth](https://github.com/kanutocd/spherical-mammoth)
149
+ - [Cloud-native deployment guide](https://github.com/kanutocd/spherical-mammoth/blob/main/docs/runbooks/cloud-native-mammoth.md)
150
+
151
+
65
152
  ## Supported PostgreSQL versions
66
153
 
67
- Mammoth supports PostgreSQL 14 through PostgreSQL 18, inclusive. These are the
68
- PostgreSQL major versions currently maintained by the PostgreSQL community and
69
- covered by Mammoth's real logical-replication E2E compatibility matrix.
154
+ Mammoth supports PostgreSQL 14 through PostgreSQL 18, inclusive. These versions are currently maintained by the PostgreSQL community and covered by Mammoth's logical-replication E2E compatibility matrix.
70
155
 
71
- Mammoth supports PostgreSQL major versions that are both maintained by the
72
- PostgreSQL community and included in Mammoth's compatibility test matrix. New
73
- PostgreSQL majors are unsupported until explicitly tested and documented. EOL
74
- versions may be removed from the supported range in a subsequent Mammoth minor
75
- release with release-note notice.
156
+ New PostgreSQL majors are unsupported until explicitly tested and documented.
157
+ EOL versions may be removed from the supported range in a subsequent Mammoth
158
+ minor release with release-note notice.
76
159
 
77
160
  PostgreSQL 19 is a development release and is not supported.
78
161
 
@@ -120,7 +203,7 @@ Mammoth 1.x includes:
120
203
  - JSON Schema-backed configuration validation
121
204
  - SQLite operational memory bootstrap
122
205
  - checkpoint persistence
123
- - dead letter persistence
206
+ - dead-letter persistence
124
207
  - delivered-envelope ledger persistence
125
208
  - webhook delivery sink
126
209
  - webhook fanout to multiple destinations
@@ -163,7 +246,7 @@ modes, not isolated API snippets.
163
246
  | [`schema_evolution`](examples/schema_evolution) | Consumer-first additive schema evolution without implying DDL delivery. |
164
247
  | [`destination_idempotency`](examples/destination_idempotency) | Atomic destination-side duplicate suppression across isolated relay ledgers. |
165
248
  | [`failing_webhook_retry`](examples/failing_webhook_retry) | Retry exhaustion and durable dead-letter persistence. |
166
- | [`operational_state`](examples/operational_state) | Inspectable checkpoints, delivered ledgers, and dead letters. |
249
+ | [`operational_state`](examples/operational_state) | Inspectable checkpoints, delivered ledgers, and dead-letters. |
167
250
  | [`kubernetes_helm`](examples/kubernetes_helm) | Single-consumer Kubernetes deployment using the public Helm chart. |
168
251
 
169
252
  See [`examples/README.md`](examples/README.md) for the complete index, boundary
@@ -186,36 +269,40 @@ and transaction JSON contracts, column-change semantics, and event-ID behavior.
186
269
 
187
270
  ## Boundary
188
271
 
189
- Mammoth begins at CDC-core work items and ends at webhook fanout delivery.
272
+ Mammoth begins at CDC Core work items and ends at webhook fanout delivery.
190
273
 
191
274
  Mammoth does not own pgoutput protocol parsing, value decoding, source
192
- normalization, or core dispatch vocabulary. Those belong to upstream CDC
193
- Ecosystem components. Mammoth selects and composes a delivery runtime while
194
- delegating its scheduling mechanics to the runtime layer. The runtime registry
195
- wraps the selected adapter with configured batch accumulation; `Application`
196
- only streams core work and coordinates lifecycle flush and shutdown calls.
275
+ normalization, or core dispatch vocabulary. Those responsibilities belong to
276
+ upstream CDC Ecosystem components. Mammoth selects and composes a delivery
277
+ runtime while delegating scheduling mechanics to the runtime layer.
278
+ The runtime registry wraps the selected adapter with configured batch accumulation;
279
+ `Application` only streams core work and coordinates lifecycle flush and
280
+ shutdown calls.
197
281
 
198
282
  For the live PostgreSQL stream, `pgoutput-source-adapter` incrementally owns
199
283
  `Begin`/`Commit` buffering and emits exact `CDC::Core::ChangeEvent` or
200
284
  `CDC::Core::TransactionEnvelope` work items. Mammoth only composes the
201
- transport, parser, decoder, and source adapter and forwards the resulting core
202
- work to delivery. Mammoth's publication preflight supplies ordered,
285
+ transport, parser, decoder, and source adapter, then forwards the resulting
286
+ core work to delivery. Mammoth's publication preflight supplies ordered,
203
287
  catalog-derived replica-identity columns to the adapter, which owns composite
204
288
  and non-`id` key extraction.
205
289
 
206
290
  At the downstream boundary, `Mammoth::DeliveryProcessor` implements
207
291
  `CDC::Core::Processor` and returns `CDC::Core::ProcessorResult`. Inline and
208
292
  concurrent runtimes notify a `CDC::Core::Observer`; Mammoth's default observer
209
- maps the canonical started, succeeded, failed, and skipped notifications to
293
+ maps canonical started, succeeded, failed, and skipped notifications to
210
294
  Prometheus counters.
211
295
 
212
- `Mammoth::ReplicationConsumer` accepts only exact core events and transaction
213
- envelopes. `deliver-sample` input crosses
214
- `PersistedPayloadDeserializer` before entering the live delivery path, so its
215
- stored hash does not masquerade as CDC-core work. Dead-letter replay is a
216
- separate destination boundary: Mammoth sends the exact prepared JSON persisted
217
- for that destination and does not reconstruct CDC work or reapply the current
218
- payload policy.
296
+ `Mammoth::ReplicationConsumer` accepts only CDC Core event and transaction
297
+ envelope types.
298
+
299
+ `deliver-sample` input passes through `PersistedPayloadDeserializer` before
300
+ entering the live delivery path, ensuring stored hashes do not masquerade as
301
+ CDC Core work.
302
+
303
+ Dead-letter replay is a separate destination boundary: Mammoth sends the exact
304
+ prepared JSON persisted for that destination and does not reconstruct CDC work
305
+ or reapply the current payload policy.
219
306
 
220
307
  ## Extensions
221
308
 
@@ -341,10 +428,9 @@ A reference benchmark run on Ruby 4.0.5 produced:
341
428
  | SQLite delivered-ledger writes | **1,630 writes/sec** |
342
429
  | Dead-letter replay mechanics | **1,030 entries/sec** |
343
430
 
344
- At concurrency 50 with a synthetic 25 ms destination, Mammoth processed
345
- **1,862 transactions/sec** against a theoretical ceiling of 2,000, while
346
- maintaining **28.4 ms P95 latency**. This indicates low scheduling overhead for
347
- I/O-bound downstream delivery.
431
+ Mammoth processed **1,862 transactions/sec** against a calculated workload
432
+ ceiling of 2,000 transactions/sec, while maintaining **28.4 ms P95 latency**.
433
+ This indicates low scheduling overhead for I/O-bound downstream delivery.
348
434
 
349
435
  These are local, single-trial reference measurements, not universal capacity
350
436
  claims or comparisons with other CDC platforms. The benchmarks isolate specific
@@ -135,14 +135,22 @@ module Mammoth
135
135
  return value.map { |item| canonicalize(item) } if value.is_a?(Array)
136
136
  return value unless value.is_a?(Hash)
137
137
 
138
- value.keys.sort.to_h { |key| [key, canonicalize(value.fetch(key))] }
138
+ value.keys.sort.each_with_object(
139
+ {} # : Hash[untyped, untyped]
140
+ ) do |key, result|
141
+ result[key] = canonicalize(value.fetch(key))
142
+ end
139
143
  end
140
144
 
141
145
  def stringify_keys(value)
142
146
  return value.map { |item| stringify_keys(item) } if value.is_a?(Array)
143
147
  return value unless value.is_a?(Hash)
144
148
 
145
- value.to_h { |key, item| [key.to_s, stringify_keys(item)] }
149
+ value.each_with_object(
150
+ {} # : Hash[String, untyped]
151
+ ) do |(key, item), result|
152
+ result[key.to_s] = stringify_keys(item)
153
+ end
146
154
  end
147
155
 
148
156
  def deep_freeze(value)
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Mammoth
4
4
  # Current Mammoth gem version.
5
- VERSION = "1.5.3"
5
+ VERSION = "1.5.4"
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mammoth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken C. Demanawa