pgoutput-client 0.0.0 → 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 +4 -4
- data/CHANGELOG.md +37 -2
- data/LICENSE.txt +6 -6
- data/README.md +346 -19
- data/lib/pgoutput/client/commands.rb +62 -0
- data/lib/pgoutput/client/configuration.rb +187 -0
- data/lib/pgoutput/client/connection.rb +120 -0
- data/lib/pgoutput/client/errors.rb +41 -0
- data/lib/pgoutput/client/feedback.rb +62 -0
- data/lib/pgoutput/client/keepalive.rb +64 -0
- data/lib/pgoutput/client/lsn.rb +54 -0
- data/lib/pgoutput/client/runner.rb +258 -0
- data/lib/pgoutput/client/state.rb +41 -0
- data/lib/pgoutput/client/stream.rb +163 -0
- data/lib/pgoutput/client/version.rb +4 -1
- data/lib/pgoutput/client/xlog_data.rb +71 -0
- data/lib/pgoutput/client.rb +23 -2
- data/lib/pgoutput_client.rb +12 -0
- data/sig/pg.rbs +12 -0
- data/sig/pgoutput/client/commands.rbs +42 -0
- data/sig/pgoutput/client/configuration.rbs +436 -0
- data/sig/pgoutput/client/connection.rbs +91 -0
- data/sig/pgoutput/client/errors.rbs +43 -0
- data/sig/pgoutput/client/feedback.rbs +71 -0
- data/sig/pgoutput/client/keepalive.rbs +55 -0
- data/sig/pgoutput/client/lsn.rbs +36 -0
- data/sig/pgoutput/client/runner.rbs +99 -0
- data/sig/pgoutput/client/state.rbs +29 -0
- data/sig/pgoutput/client/stream.rbs +89 -0
- data/sig/pgoutput/client/version.rbs +8 -0
- data/sig/pgoutput/client/xlog_data.rbs +63 -0
- metadata +50 -11
- data/CODE_OF_CONDUCT.md +0 -10
- data/Rakefile +0 -12
- data/sig/pgoutput/client.rbs +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1413514b4a4dbe4f3c0f4c59744931ed865ca6faea5662f33844c0786a46e287
|
|
4
|
+
data.tar.gz: ebb972e2f0dd5a40f46161d6cd5be70df2f42db42e05862edf16f11e0f9a15ef
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7cb26f20d9a5a86c231956cb801c98b269aeebcf969dc2408b8ded3dbcae9a1b7995f88179480cbdd59c6f99b9d5df9d7910db78f0d84175d74fcc7e1ac6a0f5
|
|
7
|
+
data.tar.gz: 93a66bfe718e050fc636c77e78dcc1dd8c8bce064d64794f982944e9dc7a83ed261e3831a88d91ce1a6acb4c2498a5506135d815a8f6d278f5ff1fda168dc868
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## [0.2.0] - 2026-06-16
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Remove the configurable plugin surface; this transport layer is fixed to `pgoutput`.
|
|
10
|
+
- Wire `Pgoutput::Client::Runner#stop` to the active stream for cooperative shutdown.
|
|
11
|
+
- Back off briefly when the replication socket has no `CopyData` ready instead of busy polling.
|
|
12
|
+
- Retry live stream connection loss with backoff and resume from the latest confirmed WAL position.
|
|
13
|
+
- Avoid recreating an existing replication slot during reconnect attempts.
|
|
14
|
+
- Document the Docker-backed E2E workflow in the README and test skip hint.
|
|
15
|
+
- Document that replay, checkpointing, deduplication, and sink ordering belong to downstream layers.
|
|
16
|
+
- Add a live E2E reconnect test that restarts PostgreSQL mid-stream and verifies resume behavior.
|
|
17
|
+
|
|
18
|
+
---
|
|
2
19
|
|
|
3
20
|
## [0.1.0] - 2026-05-31
|
|
4
21
|
|
|
5
|
-
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- Initial transport-only PostgreSQL logical replication client.
|
|
25
|
+
- Added `Pgoutput::Client::Runner` facade.
|
|
26
|
+
- Added immutable configuration object.
|
|
27
|
+
- Added LSN parse and format helpers.
|
|
28
|
+
- Added XLogData envelope parsing.
|
|
29
|
+
- Added primary keepalive parsing.
|
|
30
|
+
- Added standby feedback payload builder.
|
|
31
|
+
- Added replication command builders.
|
|
32
|
+
- Added `PG::Connection` wrapper.
|
|
33
|
+
- Added logical replication stream loop.
|
|
34
|
+
- Added RBS signatures.
|
|
35
|
+
- Added Minitest test suite.
|
|
36
|
+
- Added README and examples.
|
|
37
|
+
|
|
38
|
+
### Notes
|
|
39
|
+
|
|
40
|
+
This release intentionally does not parse pgoutput protocol messages or decode PostgreSQL values.
|
data/LICENSE.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026 Kenneth C. Demanawa
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -9,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
9
9
|
copies of the Software, and to permit persons to whom the Software is
|
|
10
10
|
furnished to do so, subject to the following conditions:
|
|
11
11
|
|
|
12
|
-
The above copyright notice and this permission notice shall be included in
|
|
13
|
-
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
14
|
|
|
15
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
-
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,43 +1,370 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pgoutput-client
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://badge.fury.io/rb/pgoutput-client)
|
|
4
|
+
[](https://github.com/kanutocd/pgoutput-client/actions)
|
|
5
|
+
[](https://www.ruby-lang.org/en/)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
|
|
9
|
+
A transport-only PostgreSQL logical replication client for receiving raw `pgoutput` payloads in Ruby.
|
|
10
|
+
|
|
11
|
+
`pgoutput-client` connects to PostgreSQL using logical replication, starts a `pgoutput` replication stream, receives `CopyData` messages, handles keepalives, sends standby feedback, and yields raw pgoutput payload bytes to downstream gems such as `pgoutput-parser` and `pgoutput-decoder`.
|
|
12
|
+
|
|
13
|
+
It intentionally does **not** parse row-change messages or decode PostgreSQL values.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Requirements
|
|
18
|
+
|
|
19
|
+
- Ruby 3.4+
|
|
20
|
+
- PostgreSQL 10+
|
|
21
|
+
- `pg` gem
|
|
22
|
+
- PostgreSQL publication and logical replication slot
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Ecosystem Position
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
PostgreSQL logical replication
|
|
30
|
+
│
|
|
31
|
+
▼
|
|
32
|
+
pgoutput-client
|
|
33
|
+
│
|
|
34
|
+
▼
|
|
35
|
+
CopyData / pgoutput payloads
|
|
36
|
+
│
|
|
37
|
+
▼
|
|
38
|
+
pgoutput-parser
|
|
39
|
+
│
|
|
40
|
+
▼
|
|
41
|
+
Protocol messages
|
|
42
|
+
│
|
|
43
|
+
▼
|
|
44
|
+
pgoutput-decoder
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
Decoded row events
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`pgoutput-client` is the transport layer only.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Features
|
|
55
|
+
|
|
56
|
+
- Opens PostgreSQL logical replication connections
|
|
57
|
+
- Builds replication commands
|
|
58
|
+
- Supports `CREATE_REPLICATION_SLOT`
|
|
59
|
+
- Supports `DROP_REPLICATION_SLOT`
|
|
60
|
+
- Supports `START_REPLICATION SLOT ... LOGICAL ...`
|
|
61
|
+
- Parses XLogData envelopes
|
|
62
|
+
- Parses primary keepalive messages
|
|
63
|
+
- Builds standby feedback messages
|
|
64
|
+
- Provides LSN parse/format helpers
|
|
65
|
+
- Yields raw pgoutput payload bytes
|
|
66
|
+
- Includes RBS signatures
|
|
67
|
+
- Includes Minitest coverage
|
|
68
|
+
- No audit, parser, or decoder concerns
|
|
69
|
+
|
|
70
|
+
---
|
|
6
71
|
|
|
7
72
|
## Installation
|
|
8
73
|
|
|
9
|
-
|
|
74
|
+
```ruby
|
|
75
|
+
gem "pgoutput-client"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Then:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
bundle install
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Require:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
require "pgoutput-client"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Quick Start
|
|
93
|
+
|
|
94
|
+
```ruby
|
|
95
|
+
require "pgoutput-client"
|
|
96
|
+
|
|
97
|
+
client =
|
|
98
|
+
Pgoutput::Client::Runner.new(
|
|
99
|
+
database_url: ENV.fetch("DATABASE_URL"),
|
|
100
|
+
slot_name: "my_slot",
|
|
101
|
+
publication_names: ["my_publication"],
|
|
102
|
+
auto_create_slot: true
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
client.start do |payload, metadata|
|
|
106
|
+
puts "WAL end: #{metadata.wal_end_lsn}"
|
|
107
|
+
puts "Raw pgoutput payload bytes: #{payload.bytesize}"
|
|
108
|
+
end
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Using With pgoutput-parser
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
require "pgoutput-client"
|
|
117
|
+
require "pgoutput"
|
|
118
|
+
|
|
119
|
+
client = Pgoutput::Client::Runner.new(
|
|
120
|
+
database_url: ENV.fetch("DATABASE_URL"),
|
|
121
|
+
slot_name: "my_slot",
|
|
122
|
+
publication_names: ["my_publication"]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
tracker = Pgoutput::RelationTracker.new
|
|
126
|
+
|
|
127
|
+
client.start do |payload, metadata|
|
|
128
|
+
message = tracker.process(payload)
|
|
129
|
+
p [metadata.wal_end_lsn, message]
|
|
130
|
+
end
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Using With pgoutput-decoder
|
|
136
|
+
|
|
137
|
+
```ruby
|
|
138
|
+
require "pgoutput-client"
|
|
139
|
+
require "pgoutput"
|
|
140
|
+
require "pgoutput/decoder"
|
|
141
|
+
|
|
142
|
+
tracker = Pgoutput::RelationTracker.new
|
|
143
|
+
decoder = Pgoutput::Decoder.new
|
|
144
|
+
|
|
145
|
+
client.start do |payload, metadata|
|
|
146
|
+
protocol_message = tracker.process(payload)
|
|
147
|
+
event = decoder.decode(protocol_message)
|
|
148
|
+
p [metadata.wal_end_lsn, event]
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## What This Gem Does
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
PostgreSQL replication connection
|
|
158
|
+
│
|
|
159
|
+
▼
|
|
160
|
+
CopyData stream
|
|
161
|
+
│
|
|
162
|
+
▼
|
|
163
|
+
XLogData / Keepalive handling
|
|
164
|
+
│
|
|
165
|
+
▼
|
|
166
|
+
Raw pgoutput payloads
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
It owns:
|
|
170
|
+
|
|
171
|
+
- Replication connection setup
|
|
172
|
+
- Replication command generation
|
|
173
|
+
- CopyData reading
|
|
174
|
+
- XLogData envelope parsing
|
|
175
|
+
- Keepalive handling
|
|
176
|
+
- Standby status feedback
|
|
177
|
+
- LSN conversion
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## What This Gem Does Not Do
|
|
182
|
+
|
|
183
|
+
It does not:
|
|
184
|
+
|
|
185
|
+
- Parse pgoutput row messages
|
|
186
|
+
- Decode PostgreSQL OIDs
|
|
187
|
+
- Build application events
|
|
188
|
+
- Group transactions
|
|
189
|
+
- Run processor pipelines
|
|
190
|
+
- Manage Ractor worker pools
|
|
191
|
+
- Store audit records
|
|
192
|
+
- Own replay, checkpointing, deduplication, or sink ordering
|
|
193
|
+
|
|
194
|
+
Those responsibilities belong to higher layers, especially `cdc-core` and the sink that materializes downstream state.
|
|
195
|
+
|
|
196
|
+
## Failure Semantics
|
|
197
|
+
|
|
198
|
+
If the live replication stream loses its connection, `pgoutput-client` retries a small number of times with a backoff and resumes from the latest confirmed WAL position.
|
|
199
|
+
|
|
200
|
+
It does not decide replay policy, deduplication strategy, checkpoint storage, or exactly-once delivery. Those concerns belong to the downstream CDC runtime and sink layer.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Logical Replication Setup
|
|
205
|
+
|
|
206
|
+
Example PostgreSQL setup:
|
|
207
|
+
|
|
208
|
+
```sql
|
|
209
|
+
ALTER SYSTEM SET wal_level = logical;
|
|
210
|
+
|
|
211
|
+
CREATE PUBLICATION my_publication FOR TABLE users, posts;
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Create a slot automatically:
|
|
10
215
|
|
|
11
|
-
|
|
216
|
+
```ruby
|
|
217
|
+
Pgoutput::Client::Runner.new(
|
|
218
|
+
database_url: ENV.fetch("DATABASE_URL"),
|
|
219
|
+
slot_name: "my_slot",
|
|
220
|
+
publication_names: ["my_publication"],
|
|
221
|
+
auto_create_slot: true
|
|
222
|
+
)
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Or create the slot yourself:
|
|
226
|
+
|
|
227
|
+
```sql
|
|
228
|
+
SELECT * FROM pg_create_logical_replication_slot('my_slot', 'pgoutput');
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Public API
|
|
234
|
+
|
|
235
|
+
### Pgoutput::Client::Runner
|
|
236
|
+
|
|
237
|
+
High-level facade.
|
|
238
|
+
|
|
239
|
+
```ruby
|
|
240
|
+
client = Pgoutput::Client::Runner.new(...)
|
|
241
|
+
client.start { |payload, metadata| ... }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Pgoutput::Client::Configuration
|
|
245
|
+
|
|
246
|
+
Immutable configuration object.
|
|
247
|
+
|
|
248
|
+
### Pgoutput::Client::Connection
|
|
249
|
+
|
|
250
|
+
Thin wrapper around `PG::Connection` for replication commands.
|
|
251
|
+
|
|
252
|
+
### Pgoutput::Client::Stream
|
|
253
|
+
|
|
254
|
+
Consumes CopyData messages and yields pgoutput payloads.
|
|
255
|
+
|
|
256
|
+
### Pgoutput::Client::LSN
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
Pgoutput::Client::LSN.parse("0/16B6C50")
|
|
260
|
+
Pgoutput::Client::LSN.format(23_817_296)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Pgoutput::Client::XLogData
|
|
264
|
+
|
|
265
|
+
Represents a WAL data envelope.
|
|
266
|
+
|
|
267
|
+
### Pgoutput::Client::Keepalive
|
|
268
|
+
|
|
269
|
+
Represents a primary keepalive message.
|
|
270
|
+
|
|
271
|
+
### Pgoutput::Client::Feedback
|
|
272
|
+
|
|
273
|
+
Builds standby status update payloads.
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Ractor Position
|
|
278
|
+
|
|
279
|
+
The replication connection itself is stateful and ordered. It should normally run as a single reader.
|
|
280
|
+
|
|
281
|
+
Downstream parsing, decoding, and processing can be parallelized with Ractors:
|
|
282
|
+
|
|
283
|
+
```text
|
|
284
|
+
pgoutput-client reader
|
|
285
|
+
│
|
|
286
|
+
▼
|
|
287
|
+
Ractor-safe queue
|
|
288
|
+
│
|
|
289
|
+
▼
|
|
290
|
+
parser / decoder / processor pools
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Rake Tasks
|
|
296
|
+
|
|
297
|
+
### Default
|
|
298
|
+
|
|
299
|
+
Run them all
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
bundle exec rake
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Code Linting and Formatting
|
|
12
306
|
|
|
13
307
|
```bash
|
|
14
|
-
bundle
|
|
308
|
+
bundle exec rake rubocop
|
|
15
309
|
```
|
|
16
310
|
|
|
17
|
-
|
|
311
|
+
### Testing
|
|
18
312
|
|
|
19
313
|
```bash
|
|
20
|
-
|
|
314
|
+
bundle exec rake test
|
|
21
315
|
```
|
|
22
316
|
|
|
23
|
-
|
|
317
|
+
With coverage:
|
|
24
318
|
|
|
25
|
-
|
|
319
|
+
```bash
|
|
320
|
+
COVERAGE=true bundle exec rake test
|
|
321
|
+
```
|
|
322
|
+
---
|
|
26
323
|
|
|
27
|
-
|
|
324
|
+
### Type Checking
|
|
28
325
|
|
|
29
|
-
|
|
326
|
+
```bash
|
|
327
|
+
bundle exec rbs:validate
|
|
328
|
+
```
|
|
30
329
|
|
|
31
|
-
|
|
330
|
+
---
|
|
32
331
|
|
|
33
|
-
|
|
332
|
+
### Documentation
|
|
34
333
|
|
|
35
|
-
|
|
334
|
+
```bash
|
|
335
|
+
bundle exec rake yard
|
|
336
|
+
```
|
|
36
337
|
|
|
37
|
-
|
|
338
|
+
### End-to-End PostgreSQL
|
|
38
339
|
|
|
39
|
-
|
|
340
|
+
Run the full Docker-backed E2E flow and clean up afterward:
|
|
40
341
|
|
|
41
|
-
|
|
342
|
+
```bash
|
|
343
|
+
script/test-e2e
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Keep PostgreSQL running after the test for debugging:
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
KEEP_E2E_POSTGRES=1 script/test-e2e
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
You can also run the steps manually:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
script/e2e-up
|
|
356
|
+
PGOUTPUT_CLIENT_E2E=1 bundle exec rake test:e2e
|
|
357
|
+
script/e2e-down
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Equivalent Rake task:
|
|
361
|
+
|
|
362
|
+
```bash
|
|
363
|
+
bundle exec rake e2e:run
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
368
|
+
## License
|
|
42
369
|
|
|
43
|
-
|
|
370
|
+
MIT.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pgoutput
|
|
4
|
+
module Client
|
|
5
|
+
# SQL command builders for PostgreSQL replication-mode commands.
|
|
6
|
+
#
|
|
7
|
+
# PostgreSQL replication commands are issued on a connection opened with the
|
|
8
|
+
# replication parameter enabled. The methods in this module render the small
|
|
9
|
+
# command subset needed by `pgoutput-client` and rely on {Configuration} to
|
|
10
|
+
# validate identifier-like values before interpolation.
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
module Commands
|
|
14
|
+
module_function
|
|
15
|
+
|
|
16
|
+
# Render a `CREATE_REPLICATION_SLOT` command.
|
|
17
|
+
#
|
|
18
|
+
# Temporary slots are requested only when
|
|
19
|
+
# {Configuration#temporary_slot} is true.
|
|
20
|
+
#
|
|
21
|
+
# @example Permanent slot
|
|
22
|
+
# Commands.create_replication_slot(config)
|
|
23
|
+
# # => "CREATE_REPLICATION_SLOT cdc_slot LOGICAL pgoutput"
|
|
24
|
+
#
|
|
25
|
+
# @param configuration [Configuration] replication configuration
|
|
26
|
+
# @return [String] SQL command suitable for `PG::Connection#exec`
|
|
27
|
+
def create_replication_slot(configuration)
|
|
28
|
+
temporary = configuration.temporary_slot ? " TEMPORARY" : ""
|
|
29
|
+
"CREATE_REPLICATION_SLOT #{configuration.slot_name}#{temporary} LOGICAL #{Configuration::DEFAULT_PLUGIN}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Render a `DROP_REPLICATION_SLOT` command.
|
|
33
|
+
#
|
|
34
|
+
# @param configuration [Configuration] replication configuration
|
|
35
|
+
# @return [String] SQL command suitable for `PG::Connection#exec`
|
|
36
|
+
def drop_replication_slot(configuration)
|
|
37
|
+
"DROP_REPLICATION_SLOT #{configuration.slot_name}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Render a `START_REPLICATION SLOT ... LOGICAL ...` command.
|
|
41
|
+
#
|
|
42
|
+
# The command includes the pgoutput options required by PostgreSQL:
|
|
43
|
+
# `proto_version` and `publication_names`. Optional pgoutput switches such
|
|
44
|
+
# as `binary` and `messages` are emitted only when enabled.
|
|
45
|
+
#
|
|
46
|
+
# @param configuration [Configuration] replication configuration
|
|
47
|
+
# @return [String] SQL command suitable for `PG::Connection#exec`
|
|
48
|
+
def start_replication(configuration)
|
|
49
|
+
options = {
|
|
50
|
+
"proto_version" => configuration.proto_version.to_s,
|
|
51
|
+
"publication_names" => configuration.publication_names.join(","),
|
|
52
|
+
"binary" => configuration.binary ? "true" : nil,
|
|
53
|
+
"messages" => configuration.messages ? "true" : nil
|
|
54
|
+
}.compact
|
|
55
|
+
|
|
56
|
+
rendered_options = options.map { |key, value| %("#{key}" '#{value}') }.join(", ")
|
|
57
|
+
|
|
58
|
+
"START_REPLICATION SLOT #{configuration.slot_name} LOGICAL #{configuration.start_lsn_string} (#{rendered_options})"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|