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
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
module Pgoutput
|
|
2
|
+
module Client
|
|
3
|
+
# Immutable configuration for a PostgreSQL logical replication stream.
|
|
4
|
+
#
|
|
5
|
+
# A configuration describes how `pgoutput-client` should connect to
|
|
6
|
+
# PostgreSQL and how it should request logical replication from the server.
|
|
7
|
+
# It deliberately contains transport-level settings only; parsing pgoutput
|
|
8
|
+
# records and decoding PostgreSQL values belong to downstream layers.
|
|
9
|
+
#
|
|
10
|
+
# The object freezes itself and its string/array attributes during
|
|
11
|
+
# initialization so it can be safely shared by transport components without
|
|
12
|
+
# defensive copying.
|
|
13
|
+
#
|
|
14
|
+
# @example Minimal configuration
|
|
15
|
+
# config = Pgoutput::Client::Configuration.new(
|
|
16
|
+
# database_url: "postgres://localhost/app",
|
|
17
|
+
# slot_name: "cdc_slot",
|
|
18
|
+
# publication_names: "app_publication"
|
|
19
|
+
# )
|
|
20
|
+
#
|
|
21
|
+
# @example Start from a known LSN and request binary values from pgoutput
|
|
22
|
+
# config = Pgoutput::Client::Configuration.new(
|
|
23
|
+
# database_url: ENV.fetch("DATABASE_URL"),
|
|
24
|
+
# slot_name: "cdc_slot",
|
|
25
|
+
# publication_names: %w[app_publication],
|
|
26
|
+
# start_lsn: "0/16B6C50",
|
|
27
|
+
# binary: true
|
|
28
|
+
# )
|
|
29
|
+
#
|
|
30
|
+
# @api public
|
|
31
|
+
class Configuration
|
|
32
|
+
@database_url: untyped
|
|
33
|
+
|
|
34
|
+
@slot_name: untyped
|
|
35
|
+
|
|
36
|
+
@publication_names: untyped
|
|
37
|
+
|
|
38
|
+
@start_lsn: untyped
|
|
39
|
+
|
|
40
|
+
@proto_version: untyped
|
|
41
|
+
|
|
42
|
+
@binary: untyped
|
|
43
|
+
|
|
44
|
+
@messages: untyped
|
|
45
|
+
|
|
46
|
+
@auto_create_slot: untyped
|
|
47
|
+
|
|
48
|
+
@temporary_slot: untyped
|
|
49
|
+
|
|
50
|
+
@feedback_interval: untyped
|
|
51
|
+
|
|
52
|
+
# Fixed logical decoding output plugin.
|
|
53
|
+
#
|
|
54
|
+
# @return [String]
|
|
55
|
+
DEFAULT_PLUGIN: "pgoutput"
|
|
56
|
+
|
|
57
|
+
# Default pgoutput protocol version.
|
|
58
|
+
#
|
|
59
|
+
# @return [Integer]
|
|
60
|
+
DEFAULT_PROTO_VERSION: 1
|
|
61
|
+
|
|
62
|
+
# Default interval, in seconds, between standby status feedback messages.
|
|
63
|
+
#
|
|
64
|
+
# @return [Float]
|
|
65
|
+
DEFAULT_FEEDBACK_INTERVAL: ::Float
|
|
66
|
+
|
|
67
|
+
# @!attribute [r] database_url
|
|
68
|
+
# PostgreSQL connection URL.
|
|
69
|
+
# @return [String]
|
|
70
|
+
# @!attribute [r] slot_name
|
|
71
|
+
# Logical replication slot name.
|
|
72
|
+
# @return [String]
|
|
73
|
+
# @!attribute [r] publication_names
|
|
74
|
+
# Publication names requested from pgoutput.
|
|
75
|
+
# @return [Array<String>]
|
|
76
|
+
# @!attribute [r] start_lsn
|
|
77
|
+
# Optional normalized starting LSN.
|
|
78
|
+
# @return [String, nil]
|
|
79
|
+
# @!attribute [r] proto_version
|
|
80
|
+
# pgoutput protocol version.
|
|
81
|
+
# @return [Integer]
|
|
82
|
+
# @!attribute [r] binary
|
|
83
|
+
# Whether to request binary column values from pgoutput.
|
|
84
|
+
# @return [Boolean]
|
|
85
|
+
# @!attribute [r] messages
|
|
86
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
87
|
+
# @return [Boolean]
|
|
88
|
+
# @!attribute [r] auto_create_slot
|
|
89
|
+
# Whether the client should create the slot before streaming.
|
|
90
|
+
# @return [Boolean]
|
|
91
|
+
# @!attribute [r] temporary_slot
|
|
92
|
+
# Whether a newly created slot should be temporary.
|
|
93
|
+
# @return [Boolean]
|
|
94
|
+
# @!attribute [r] feedback_interval
|
|
95
|
+
# Standby feedback interval in seconds.
|
|
96
|
+
# @return [Float]
|
|
97
|
+
attr_reader database_url: untyped
|
|
98
|
+
|
|
99
|
+
# @!attribute [r] database_url
|
|
100
|
+
# PostgreSQL connection URL.
|
|
101
|
+
# @return [String]
|
|
102
|
+
# @!attribute [r] slot_name
|
|
103
|
+
# Logical replication slot name.
|
|
104
|
+
# @return [String]
|
|
105
|
+
# @!attribute [r] publication_names
|
|
106
|
+
# Publication names requested from pgoutput.
|
|
107
|
+
# @return [Array<String>]
|
|
108
|
+
# @!attribute [r] start_lsn
|
|
109
|
+
# Optional normalized starting LSN.
|
|
110
|
+
# @return [String, nil]
|
|
111
|
+
# @!attribute [r] proto_version
|
|
112
|
+
# pgoutput protocol version.
|
|
113
|
+
# @return [Integer]
|
|
114
|
+
# @!attribute [r] binary
|
|
115
|
+
# Whether to request binary column values from pgoutput.
|
|
116
|
+
# @return [Boolean]
|
|
117
|
+
# @!attribute [r] messages
|
|
118
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
119
|
+
# @return [Boolean]
|
|
120
|
+
# @!attribute [r] auto_create_slot
|
|
121
|
+
# Whether the client should create the slot before streaming.
|
|
122
|
+
# @return [Boolean]
|
|
123
|
+
# @!attribute [r] temporary_slot
|
|
124
|
+
# Whether a newly created slot should be temporary.
|
|
125
|
+
# @return [Boolean]
|
|
126
|
+
# @!attribute [r] feedback_interval
|
|
127
|
+
# Standby feedback interval in seconds.
|
|
128
|
+
# @return [Float]
|
|
129
|
+
attr_reader slot_name: untyped
|
|
130
|
+
|
|
131
|
+
# @!attribute [r] database_url
|
|
132
|
+
# PostgreSQL connection URL.
|
|
133
|
+
# @return [String]
|
|
134
|
+
# @!attribute [r] slot_name
|
|
135
|
+
# Logical replication slot name.
|
|
136
|
+
# @return [String]
|
|
137
|
+
# @!attribute [r] publication_names
|
|
138
|
+
# Publication names requested from pgoutput.
|
|
139
|
+
# @return [Array<String>]
|
|
140
|
+
# @!attribute [r] start_lsn
|
|
141
|
+
# Optional normalized starting LSN.
|
|
142
|
+
# @return [String, nil]
|
|
143
|
+
# @!attribute [r] proto_version
|
|
144
|
+
# pgoutput protocol version.
|
|
145
|
+
# @return [Integer]
|
|
146
|
+
# @!attribute [r] binary
|
|
147
|
+
# Whether to request binary column values from pgoutput.
|
|
148
|
+
# @return [Boolean]
|
|
149
|
+
# @!attribute [r] messages
|
|
150
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
151
|
+
# @return [Boolean]
|
|
152
|
+
# @!attribute [r] auto_create_slot
|
|
153
|
+
# Whether the client should create the slot before streaming.
|
|
154
|
+
# @return [Boolean]
|
|
155
|
+
# @!attribute [r] temporary_slot
|
|
156
|
+
# Whether a newly created slot should be temporary.
|
|
157
|
+
# @return [Boolean]
|
|
158
|
+
# @!attribute [r] feedback_interval
|
|
159
|
+
# Standby feedback interval in seconds.
|
|
160
|
+
# @return [Float]
|
|
161
|
+
attr_reader publication_names: untyped
|
|
162
|
+
|
|
163
|
+
# @!attribute [r] database_url
|
|
164
|
+
# PostgreSQL connection URL.
|
|
165
|
+
# @return [String]
|
|
166
|
+
# @!attribute [r] slot_name
|
|
167
|
+
# Logical replication slot name.
|
|
168
|
+
# @return [String]
|
|
169
|
+
# @!attribute [r] publication_names
|
|
170
|
+
# Publication names requested from pgoutput.
|
|
171
|
+
# @return [Array<String>]
|
|
172
|
+
# @!attribute [r] start_lsn
|
|
173
|
+
# Optional normalized starting LSN.
|
|
174
|
+
# @return [String, nil]
|
|
175
|
+
# @!attribute [r] proto_version
|
|
176
|
+
# pgoutput protocol version.
|
|
177
|
+
# @return [Integer]
|
|
178
|
+
# @!attribute [r] binary
|
|
179
|
+
# Whether to request binary column values from pgoutput.
|
|
180
|
+
# @return [Boolean]
|
|
181
|
+
# @!attribute [r] messages
|
|
182
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
183
|
+
# @return [Boolean]
|
|
184
|
+
# @!attribute [r] auto_create_slot
|
|
185
|
+
# Whether the client should create the slot before streaming.
|
|
186
|
+
# @return [Boolean]
|
|
187
|
+
# @!attribute [r] temporary_slot
|
|
188
|
+
# Whether a newly created slot should be temporary.
|
|
189
|
+
# @return [Boolean]
|
|
190
|
+
# @!attribute [r] feedback_interval
|
|
191
|
+
# Standby feedback interval in seconds.
|
|
192
|
+
# @return [Float]
|
|
193
|
+
attr_reader start_lsn: untyped
|
|
194
|
+
|
|
195
|
+
# @!attribute [r] database_url
|
|
196
|
+
# PostgreSQL connection URL.
|
|
197
|
+
# @return [String]
|
|
198
|
+
# @!attribute [r] slot_name
|
|
199
|
+
# Logical replication slot name.
|
|
200
|
+
# @return [String]
|
|
201
|
+
# @!attribute [r] publication_names
|
|
202
|
+
# Publication names requested from pgoutput.
|
|
203
|
+
# @return [Array<String>]
|
|
204
|
+
# @!attribute [r] start_lsn
|
|
205
|
+
# Optional normalized starting LSN.
|
|
206
|
+
# @return [String, nil]
|
|
207
|
+
# @!attribute [r] proto_version
|
|
208
|
+
# pgoutput protocol version.
|
|
209
|
+
# @return [Integer]
|
|
210
|
+
# @!attribute [r] binary
|
|
211
|
+
# Whether to request binary column values from pgoutput.
|
|
212
|
+
# @return [Boolean]
|
|
213
|
+
# @!attribute [r] messages
|
|
214
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
215
|
+
# @return [Boolean]
|
|
216
|
+
# @!attribute [r] auto_create_slot
|
|
217
|
+
# Whether the client should create the slot before streaming.
|
|
218
|
+
# @return [Boolean]
|
|
219
|
+
# @!attribute [r] temporary_slot
|
|
220
|
+
# Whether a newly created slot should be temporary.
|
|
221
|
+
# @return [Boolean]
|
|
222
|
+
# @!attribute [r] feedback_interval
|
|
223
|
+
# Standby feedback interval in seconds.
|
|
224
|
+
# @return [Float]
|
|
225
|
+
attr_reader proto_version: untyped
|
|
226
|
+
|
|
227
|
+
# @!attribute [r] database_url
|
|
228
|
+
# PostgreSQL connection URL.
|
|
229
|
+
# @return [String]
|
|
230
|
+
# @!attribute [r] slot_name
|
|
231
|
+
# Logical replication slot name.
|
|
232
|
+
# @return [String]
|
|
233
|
+
# @!attribute [r] publication_names
|
|
234
|
+
# Publication names requested from pgoutput.
|
|
235
|
+
# @return [Array<String>]
|
|
236
|
+
# @!attribute [r] start_lsn
|
|
237
|
+
# Optional normalized starting LSN.
|
|
238
|
+
# @return [String, nil]
|
|
239
|
+
# @!attribute [r] proto_version
|
|
240
|
+
# pgoutput protocol version.
|
|
241
|
+
# @return [Integer]
|
|
242
|
+
# @!attribute [r] binary
|
|
243
|
+
# Whether to request binary column values from pgoutput.
|
|
244
|
+
# @return [Boolean]
|
|
245
|
+
# @!attribute [r] messages
|
|
246
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
247
|
+
# @return [Boolean]
|
|
248
|
+
# @!attribute [r] auto_create_slot
|
|
249
|
+
# Whether the client should create the slot before streaming.
|
|
250
|
+
# @return [Boolean]
|
|
251
|
+
# @!attribute [r] temporary_slot
|
|
252
|
+
# Whether a newly created slot should be temporary.
|
|
253
|
+
# @return [Boolean]
|
|
254
|
+
# @!attribute [r] feedback_interval
|
|
255
|
+
# Standby feedback interval in seconds.
|
|
256
|
+
# @return [Float]
|
|
257
|
+
attr_reader binary: untyped
|
|
258
|
+
|
|
259
|
+
# @!attribute [r] database_url
|
|
260
|
+
# PostgreSQL connection URL.
|
|
261
|
+
# @return [String]
|
|
262
|
+
# @!attribute [r] slot_name
|
|
263
|
+
# Logical replication slot name.
|
|
264
|
+
# @return [String]
|
|
265
|
+
# @!attribute [r] publication_names
|
|
266
|
+
# Publication names requested from pgoutput.
|
|
267
|
+
# @return [Array<String>]
|
|
268
|
+
# @!attribute [r] start_lsn
|
|
269
|
+
# Optional normalized starting LSN.
|
|
270
|
+
# @return [String, nil]
|
|
271
|
+
# @!attribute [r] proto_version
|
|
272
|
+
# pgoutput protocol version.
|
|
273
|
+
# @return [Integer]
|
|
274
|
+
# @!attribute [r] binary
|
|
275
|
+
# Whether to request binary column values from pgoutput.
|
|
276
|
+
# @return [Boolean]
|
|
277
|
+
# @!attribute [r] messages
|
|
278
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
279
|
+
# @return [Boolean]
|
|
280
|
+
# @!attribute [r] auto_create_slot
|
|
281
|
+
# Whether the client should create the slot before streaming.
|
|
282
|
+
# @return [Boolean]
|
|
283
|
+
# @!attribute [r] temporary_slot
|
|
284
|
+
# Whether a newly created slot should be temporary.
|
|
285
|
+
# @return [Boolean]
|
|
286
|
+
# @!attribute [r] feedback_interval
|
|
287
|
+
# Standby feedback interval in seconds.
|
|
288
|
+
# @return [Float]
|
|
289
|
+
attr_reader messages: untyped
|
|
290
|
+
|
|
291
|
+
# @!attribute [r] database_url
|
|
292
|
+
# PostgreSQL connection URL.
|
|
293
|
+
# @return [String]
|
|
294
|
+
# @!attribute [r] slot_name
|
|
295
|
+
# Logical replication slot name.
|
|
296
|
+
# @return [String]
|
|
297
|
+
# @!attribute [r] publication_names
|
|
298
|
+
# Publication names requested from pgoutput.
|
|
299
|
+
# @return [Array<String>]
|
|
300
|
+
# @!attribute [r] start_lsn
|
|
301
|
+
# Optional normalized starting LSN.
|
|
302
|
+
# @return [String, nil]
|
|
303
|
+
# @!attribute [r] proto_version
|
|
304
|
+
# pgoutput protocol version.
|
|
305
|
+
# @return [Integer]
|
|
306
|
+
# @!attribute [r] binary
|
|
307
|
+
# Whether to request binary column values from pgoutput.
|
|
308
|
+
# @return [Boolean]
|
|
309
|
+
# @!attribute [r] messages
|
|
310
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
311
|
+
# @return [Boolean]
|
|
312
|
+
# @!attribute [r] auto_create_slot
|
|
313
|
+
# Whether the client should create the slot before streaming.
|
|
314
|
+
# @return [Boolean]
|
|
315
|
+
# @!attribute [r] temporary_slot
|
|
316
|
+
# Whether a newly created slot should be temporary.
|
|
317
|
+
# @return [Boolean]
|
|
318
|
+
# @!attribute [r] feedback_interval
|
|
319
|
+
# Standby feedback interval in seconds.
|
|
320
|
+
# @return [Float]
|
|
321
|
+
attr_reader auto_create_slot: untyped
|
|
322
|
+
|
|
323
|
+
# @!attribute [r] database_url
|
|
324
|
+
# PostgreSQL connection URL.
|
|
325
|
+
# @return [String]
|
|
326
|
+
# @!attribute [r] slot_name
|
|
327
|
+
# Logical replication slot name.
|
|
328
|
+
# @return [String]
|
|
329
|
+
# @!attribute [r] publication_names
|
|
330
|
+
# Publication names requested from pgoutput.
|
|
331
|
+
# @return [Array<String>]
|
|
332
|
+
# @!attribute [r] start_lsn
|
|
333
|
+
# Optional normalized starting LSN.
|
|
334
|
+
# @return [String, nil]
|
|
335
|
+
# @!attribute [r] proto_version
|
|
336
|
+
# pgoutput protocol version.
|
|
337
|
+
# @return [Integer]
|
|
338
|
+
# @!attribute [r] binary
|
|
339
|
+
# Whether to request binary column values from pgoutput.
|
|
340
|
+
# @return [Boolean]
|
|
341
|
+
# @!attribute [r] messages
|
|
342
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
343
|
+
# @return [Boolean]
|
|
344
|
+
# @!attribute [r] auto_create_slot
|
|
345
|
+
# Whether the client should create the slot before streaming.
|
|
346
|
+
# @return [Boolean]
|
|
347
|
+
# @!attribute [r] temporary_slot
|
|
348
|
+
# Whether a newly created slot should be temporary.
|
|
349
|
+
# @return [Boolean]
|
|
350
|
+
# @!attribute [r] feedback_interval
|
|
351
|
+
# Standby feedback interval in seconds.
|
|
352
|
+
# @return [Float]
|
|
353
|
+
attr_reader temporary_slot: untyped
|
|
354
|
+
|
|
355
|
+
# @!attribute [r] database_url
|
|
356
|
+
# PostgreSQL connection URL.
|
|
357
|
+
# @return [String]
|
|
358
|
+
# @!attribute [r] slot_name
|
|
359
|
+
# Logical replication slot name.
|
|
360
|
+
# @return [String]
|
|
361
|
+
# @!attribute [r] publication_names
|
|
362
|
+
# Publication names requested from pgoutput.
|
|
363
|
+
# @return [Array<String>]
|
|
364
|
+
# @!attribute [r] start_lsn
|
|
365
|
+
# Optional normalized starting LSN.
|
|
366
|
+
# @return [String, nil]
|
|
367
|
+
# @!attribute [r] proto_version
|
|
368
|
+
# pgoutput protocol version.
|
|
369
|
+
# @return [Integer]
|
|
370
|
+
# @!attribute [r] binary
|
|
371
|
+
# Whether to request binary column values from pgoutput.
|
|
372
|
+
# @return [Boolean]
|
|
373
|
+
# @!attribute [r] messages
|
|
374
|
+
# Whether to request logical decoding messages from pgoutput.
|
|
375
|
+
# @return [Boolean]
|
|
376
|
+
# @!attribute [r] auto_create_slot
|
|
377
|
+
# Whether the client should create the slot before streaming.
|
|
378
|
+
# @return [Boolean]
|
|
379
|
+
# @!attribute [r] temporary_slot
|
|
380
|
+
# Whether a newly created slot should be temporary.
|
|
381
|
+
# @return [Boolean]
|
|
382
|
+
# @!attribute [r] feedback_interval
|
|
383
|
+
# Standby feedback interval in seconds.
|
|
384
|
+
# @return [Float]
|
|
385
|
+
attr_reader feedback_interval: untyped
|
|
386
|
+
|
|
387
|
+
# Build and validate a logical replication stream configuration.
|
|
388
|
+
#
|
|
389
|
+
# `slot_name` and every publication name are intentionally limited to
|
|
390
|
+
# simple PostgreSQL identifier-like strings. This keeps command rendering
|
|
391
|
+
# small and predictable while avoiding quoting rules in this transport
|
|
392
|
+
# layer.
|
|
393
|
+
#
|
|
394
|
+
# Boolean options are normalized with Ruby truthiness. `nil` and `false`
|
|
395
|
+
# become `false`; all other values become `true`.
|
|
396
|
+
#
|
|
397
|
+
# @param database_url [#to_s] PostgreSQL connection URL
|
|
398
|
+
# @param slot_name [#to_s] logical replication slot name
|
|
399
|
+
# @param publication_names [Array<#to_s>, #to_s] one or more publication
|
|
400
|
+
# names to pass to pgoutput
|
|
401
|
+
# @param start_lsn [String, Integer, nil] starting LSN as a PostgreSQL LSN
|
|
402
|
+
# string, an integer WAL position, or `nil` for `0/0`
|
|
403
|
+
# @param proto_version [#to_int, #to_s] pgoutput protocol version
|
|
404
|
+
# @param binary [Object] truthy to request binary column values
|
|
405
|
+
# @param messages [Object] truthy to request logical decoding messages
|
|
406
|
+
# @param auto_create_slot [Object] truthy to create the slot before
|
|
407
|
+
# starting replication
|
|
408
|
+
# @param temporary_slot [Object] truthy to create a temporary replication
|
|
409
|
+
# slot when `auto_create_slot` is enabled
|
|
410
|
+
# @param feedback_interval [#to_f, #to_s] seconds between periodic standby
|
|
411
|
+
# feedback messages
|
|
412
|
+
# @return [void]
|
|
413
|
+
# @raise [ConfigurationError] if publication names are empty or numeric
|
|
414
|
+
# settings are invalid
|
|
415
|
+
# @raise [ArgumentError] if `start_lsn`, `proto_version`, or
|
|
416
|
+
# `feedback_interval` cannot be coerced
|
|
417
|
+
def initialize: (database_url: untyped, slot_name: untyped, publication_names: untyped, ?start_lsn: untyped?, ?proto_version: untyped, ?binary: bool, ?messages: bool, ?auto_create_slot: bool, ?temporary_slot: bool, ?feedback_interval: untyped) -> void
|
|
418
|
+
|
|
419
|
+
# Starting LSN to render in `START_REPLICATION`.
|
|
420
|
+
#
|
|
421
|
+
# @return [String] normalized LSN string, defaulting to `"0/0"`
|
|
422
|
+
def start_lsn_string: () -> untyped
|
|
423
|
+
|
|
424
|
+
private
|
|
425
|
+
|
|
426
|
+
def validate!: () -> untyped
|
|
427
|
+
|
|
428
|
+
def normalize_lsn: (untyped value) -> (nil | untyped)
|
|
429
|
+
|
|
430
|
+
def validate_identifier: (untyped value, untyped field) -> untyped
|
|
431
|
+
|
|
432
|
+
# Boolean type checking helper
|
|
433
|
+
def boolean: (untyped value, untyped name) -> (true | false | untyped)
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module Pgoutput
|
|
2
|
+
module Client
|
|
3
|
+
# Thin wrapper around `PG::Connection` for logical replication operations.
|
|
4
|
+
#
|
|
5
|
+
# `Connection` hides the small amount of PostgreSQL driver plumbing needed by
|
|
6
|
+
# the rest of the transport layer. It opens the connection in replication
|
|
7
|
+
# mode, renders replication commands through {Commands}, and translates
|
|
8
|
+
# `PG::Error` exceptions into {ConnectionError}.
|
|
9
|
+
#
|
|
10
|
+
# @api private
|
|
11
|
+
class Connection
|
|
12
|
+
@configuration: untyped
|
|
13
|
+
|
|
14
|
+
@pg_connection: untyped
|
|
15
|
+
|
|
16
|
+
# Configuration associated with this connection.
|
|
17
|
+
#
|
|
18
|
+
# @return [Configuration]
|
|
19
|
+
attr_reader configuration: untyped
|
|
20
|
+
|
|
21
|
+
# Open a PostgreSQL connection in database replication mode.
|
|
22
|
+
#
|
|
23
|
+
# @param configuration [Configuration] replication configuration
|
|
24
|
+
# @return [Connection] wrapper around an open `PG::Connection`
|
|
25
|
+
# @raise [ConnectionError] if the `pg` gem cannot connect
|
|
26
|
+
def self.open: (untyped configuration) -> untyped
|
|
27
|
+
|
|
28
|
+
# Build a connection wrapper.
|
|
29
|
+
#
|
|
30
|
+
# This constructor is public primarily for tests and alternative connection
|
|
31
|
+
# factories. Normal callers should use {.open}.
|
|
32
|
+
#
|
|
33
|
+
# @param configuration [Configuration] replication configuration
|
|
34
|
+
# @param pg_connection [PG::Connection] connected PostgreSQL driver object
|
|
35
|
+
# @return [void]
|
|
36
|
+
def initialize: (configuration: untyped, pg_connection: untyped) -> void
|
|
37
|
+
|
|
38
|
+
# Execute PostgreSQL's `IDENTIFY_SYSTEM` replication command.
|
|
39
|
+
#
|
|
40
|
+
# @return [PG::Result] server identity result
|
|
41
|
+
# @raise [ConnectionError] if PostgreSQL rejects the command
|
|
42
|
+
def identify_system: () -> untyped
|
|
43
|
+
|
|
44
|
+
# Create the configured logical replication slot.
|
|
45
|
+
#
|
|
46
|
+
# @return [PG::Result] command result
|
|
47
|
+
# @raise [ConnectionError] if PostgreSQL rejects the command
|
|
48
|
+
def create_replication_slot: () -> untyped
|
|
49
|
+
|
|
50
|
+
# Drop the configured logical replication slot.
|
|
51
|
+
#
|
|
52
|
+
# @return [PG::Result] command result
|
|
53
|
+
# @raise [ConnectionError] if PostgreSQL rejects the command
|
|
54
|
+
def drop_replication_slot: () -> untyped
|
|
55
|
+
|
|
56
|
+
# Start streaming logical replication from the configured slot and LSN.
|
|
57
|
+
#
|
|
58
|
+
# @return [PG::Result] command result
|
|
59
|
+
# @raise [ConnectionError] if PostgreSQL rejects the command
|
|
60
|
+
def start_replication: () -> untyped
|
|
61
|
+
|
|
62
|
+
# Receive one CopyData payload from the server.
|
|
63
|
+
#
|
|
64
|
+
# The call is non-blocking because the underlying `pg` call receives
|
|
65
|
+
# `false` for its blocking argument. `nil` means no complete CopyData
|
|
66
|
+
# payload is currently available.
|
|
67
|
+
#
|
|
68
|
+
# @return [String, nil] raw CopyData payload or `nil`
|
|
69
|
+
# @raise [ConnectionError] if receiving fails
|
|
70
|
+
def get_copy_data: () -> untyped
|
|
71
|
+
|
|
72
|
+
# Send one CopyData payload to the server.
|
|
73
|
+
#
|
|
74
|
+
# Used for standby status feedback messages.
|
|
75
|
+
#
|
|
76
|
+
# @param payload [String] raw CopyData payload
|
|
77
|
+
# @return [void]
|
|
78
|
+
# @raise [ConnectionError] if sending fails
|
|
79
|
+
def put_copy_data: (untyped payload) -> untyped
|
|
80
|
+
|
|
81
|
+
# Close the PostgreSQL connection if it is still open.
|
|
82
|
+
#
|
|
83
|
+
# @return [void]
|
|
84
|
+
def close: () -> (untyped | nil)
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def exec: (untyped sql) -> untyped
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Pgoutput
|
|
2
|
+
module Client
|
|
3
|
+
# Base error class for all pgoutput-client failures.
|
|
4
|
+
#
|
|
5
|
+
# Rescue this class when callers want to handle any error raised by the
|
|
6
|
+
# transport layer without also rescuing unrelated Ruby or PostgreSQL driver
|
|
7
|
+
# exceptions.
|
|
8
|
+
#
|
|
9
|
+
# @api public
|
|
10
|
+
class Error < StandardError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Raised when stream configuration is invalid.
|
|
14
|
+
#
|
|
15
|
+
# Examples include an empty publication list, invalid replication slot name,
|
|
16
|
+
# invalid publication name, non-positive protocol version, or non-positive
|
|
17
|
+
# feedback interval.
|
|
18
|
+
#
|
|
19
|
+
# @api public
|
|
20
|
+
class ConfigurationError < Error
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Raised when a replication protocol envelope cannot be parsed.
|
|
24
|
+
#
|
|
25
|
+
# This error represents malformed or unexpected CopyData payloads at the
|
|
26
|
+
# transport-envelope level. It does not describe pgoutput plugin payload
|
|
27
|
+
# parsing errors; those belong to the parser layer.
|
|
28
|
+
#
|
|
29
|
+
# @api public
|
|
30
|
+
class ProtocolError < Error
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Raised when a PostgreSQL replication connection operation fails.
|
|
34
|
+
#
|
|
35
|
+
# `Connection` converts `PG::Error` instances into this error so public
|
|
36
|
+
# callers do not need to depend on the PostgreSQL driver's exception classes
|
|
37
|
+
# for transport-level handling.
|
|
38
|
+
#
|
|
39
|
+
# @api public
|
|
40
|
+
class ConnectionError < Error
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
module Pgoutput
|
|
2
|
+
module Client
|
|
3
|
+
class FeedbackData < Data
|
|
4
|
+
attr_reader received_lsn: Integer
|
|
5
|
+
attr_reader flushed_lsn: Integer
|
|
6
|
+
attr_reader applied_lsn: Integer
|
|
7
|
+
attr_reader client_clock: Integer
|
|
8
|
+
attr_reader reply_requested: bool
|
|
9
|
+
|
|
10
|
+
def self.new: (
|
|
11
|
+
Integer received_lsn,
|
|
12
|
+
Integer flushed_lsn,
|
|
13
|
+
Integer applied_lsn,
|
|
14
|
+
Integer client_clock,
|
|
15
|
+
bool reply_requested
|
|
16
|
+
) -> instance
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Standby status feedback message builder.
|
|
20
|
+
#
|
|
21
|
+
# Logical replication clients periodically send standby status updates to
|
|
22
|
+
# tell PostgreSQL which WAL location has been received, flushed, and applied.
|
|
23
|
+
# `Feedback` models that update and can serialize itself into the CopyData
|
|
24
|
+
# payload expected by the replication protocol.
|
|
25
|
+
#
|
|
26
|
+
# @attr_reader received_lsn [Integer] latest WAL location received by the client
|
|
27
|
+
# @attr_reader flushed_lsn [Integer] latest WAL location flushed by the client
|
|
28
|
+
# @attr_reader applied_lsn [Integer] latest WAL location applied by the client
|
|
29
|
+
# @attr_reader client_clock [Integer] PostgreSQL timestamp in microseconds since 2000-01-01 UTC
|
|
30
|
+
# @attr_reader reply_requested [Boolean] whether this feedback is responding to an immediate-reply request
|
|
31
|
+
class Feedback < FeedbackData
|
|
32
|
+
def self.build: (
|
|
33
|
+
Integer received_lsn,
|
|
34
|
+
Integer flushed_lsn,
|
|
35
|
+
Integer applied_lsn,
|
|
36
|
+
?reply_requested: bool
|
|
37
|
+
) -> Feedback
|
|
38
|
+
|
|
39
|
+
# Build feedback using the current wall-clock time.
|
|
40
|
+
#
|
|
41
|
+
# By default, flushed and applied LSNs follow the received LSN. Callers can
|
|
42
|
+
# pass lower values if they need to distinguish receipt from durable flush
|
|
43
|
+
# or application progress.
|
|
44
|
+
#
|
|
45
|
+
# @param received_lsn [Integer] latest WAL location received by the client
|
|
46
|
+
# @param flushed_lsn [Integer] latest WAL location flushed by the client
|
|
47
|
+
# @param applied_lsn [Integer] latest WAL location applied by the client
|
|
48
|
+
# @param reply_requested [Boolean] whether this is an immediate reply
|
|
49
|
+
# @return [Feedback] immutable feedback value
|
|
50
|
+
def self.now: (received_lsn: untyped, ?flushed_lsn: untyped, ?applied_lsn: untyped, ?reply_requested: bool) -> untyped
|
|
51
|
+
|
|
52
|
+
# Build a protocol CopyData payload for standby status update.
|
|
53
|
+
#
|
|
54
|
+
# The payload begins with the standby status update tag `r`, followed by
|
|
55
|
+
# three unsigned 64-bit LSN fields, the PostgreSQL timestamp, and a
|
|
56
|
+
# one-byte reply-requested flag.
|
|
57
|
+
#
|
|
58
|
+
# @return [String] frozen binary CopyData payload
|
|
59
|
+
def to_copy_data: () -> untyped
|
|
60
|
+
|
|
61
|
+
# Current PostgreSQL protocol timestamp.
|
|
62
|
+
#
|
|
63
|
+
# PostgreSQL timestamps in replication messages are expressed as
|
|
64
|
+
# microseconds since 2000-01-01 00:00:00 UTC, not Unix epoch
|
|
65
|
+
# microseconds.
|
|
66
|
+
#
|
|
67
|
+
# @return [Integer] microseconds since 2000-01-01 UTC
|
|
68
|
+
def self.current_pg_time: () -> untyped
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Pgoutput
|
|
2
|
+
module Client
|
|
3
|
+
class KeepaliveData < Data
|
|
4
|
+
attr_reader wal_end: Integer
|
|
5
|
+
attr_reader server_clock: Integer
|
|
6
|
+
attr_reader reply_requested: bool
|
|
7
|
+
|
|
8
|
+
def self.new: (
|
|
9
|
+
Integer wal_end,
|
|
10
|
+
Integer server_clock,
|
|
11
|
+
bool reply_requested
|
|
12
|
+
) -> instance
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Immutable primary keepalive replication message.
|
|
16
|
+
#
|
|
17
|
+
# PostgreSQL sends keepalive CopyData payloads while a replication stream is
|
|
18
|
+
# active. The payload layout is:
|
|
19
|
+
#
|
|
20
|
+
# ```text
|
|
21
|
+
# Byte 0 : message tag `k`
|
|
22
|
+
# Bytes 1-8 : current server WAL end, unsigned 64-bit big-endian
|
|
23
|
+
# Bytes 9-16 : server clock, PostgreSQL timestamp format
|
|
24
|
+
# Byte 17 : reply-requested flag, 1 for immediate feedback
|
|
25
|
+
# ```
|
|
26
|
+
#
|
|
27
|
+
# The stream layer uses this message to advance its known WAL position and to
|
|
28
|
+
# decide whether to send standby status feedback immediately.
|
|
29
|
+
#
|
|
30
|
+
# @attr_reader wal_end [Integer] latest server WAL position
|
|
31
|
+
# @attr_reader server_clock [Integer] PostgreSQL server timestamp in
|
|
32
|
+
# microseconds since 2000-01-01 UTC
|
|
33
|
+
# @attr_reader reply_requested [Boolean] whether PostgreSQL requested
|
|
34
|
+
# immediate feedback
|
|
35
|
+
class Keepalive < KeepaliveData
|
|
36
|
+
# Parse a keepalive CopyData payload.
|
|
37
|
+
#
|
|
38
|
+
# @param bytes [String] raw CopyData payload beginning with `k`
|
|
39
|
+
# @return [Keepalive] immutable parsed keepalive message
|
|
40
|
+
# @raise [ProtocolError] if the payload is empty, has the wrong message
|
|
41
|
+
# tag, or is too short to contain the required fields
|
|
42
|
+
def self.parse: (untyped bytes) -> untyped
|
|
43
|
+
|
|
44
|
+
# Latest server WAL position formatted as a PostgreSQL LSN string.
|
|
45
|
+
#
|
|
46
|
+
# @return [String]
|
|
47
|
+
def wal_end_lsn: () -> untyped
|
|
48
|
+
|
|
49
|
+
# @param binary [String]
|
|
50
|
+
# @param offset [Integer]
|
|
51
|
+
# @return [Integer]
|
|
52
|
+
def self.unpack_u64: (untyped binary, untyped offset) -> untyped
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|