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.
@@ -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