wal 0.0.20 → 0.0.21

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: 823832e9e8ecbc21c1369c093e21da2f6feefc9d9ef0eb44ec73c38048075322
4
- data.tar.gz: 23d82a6e7b0d7630fef5e34fc46db32bfb7786300c9a8b2ebbaad44098a1dc8f
3
+ metadata.gz: 302e387a9951a4120fea323ca2f3eee13e8608963defa796c8ce0193ac1f2310
4
+ data.tar.gz: 7adfed0108d9e3671eb83f3750babe622acb1470cc85447a74ab8519c9e41122
5
5
  SHA512:
6
- metadata.gz: 3398ab723fab693c7c9ffa653fa7a3f399431b2cf05106dc56127a31240b4d72f158e515a402312553db4729fe8f39937e490a0f338aa9bf94afc7c3984cad22
7
- data.tar.gz: cd5d54cb4ca4351ccff83090dbfd78b5d64a17b4119d6c9b49eb1c31da39d1ce6c7cb577f60137f1c88ad6222436b39b85b2ae623e3319c84e57cf44072cae71
6
+ metadata.gz: 06d389b77e47f82dbcf6c3397c0e5c9b7d9b9fba124273e58d2a336d45c341317cb17ce0810e84c5cebf10ce51b12a0b26102a1600fa84e79f09fc42cb9fd89e
7
+ data.tar.gz: '09ccf267a08bf2007aeb799ca521445fe25fbaa55ddabf1618577ef70f91b0baaff1bf0f622800d7dd9e2d210c8eaf2f401fa8dc847f72f45c950a4d74d974ab'
data/LICENSE.txt CHANGED
@@ -1,21 +1,28 @@
1
- The MIT License (MIT)
1
+ BSD 3-Clause License
2
2
 
3
- Copyright (c) 2025 Rodrigo Navarro
3
+ Copyright (c) 2025-present, Rodrigo Navarro. All rights reserved.
4
4
 
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
11
7
 
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
8
+ * Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
14
10
 
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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
- THE SOFTWARE.
11
+ * Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ * Neither the name of wsrv.nl and images.weserv.nl nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -76,12 +76,12 @@ module Wal
76
76
  def on_record_changed(event)
77
77
  case event
78
78
  when InsertEvent
79
- @@change_callbacks[event.table]
79
+ @@change_callbacks[event.full_table_name]
80
80
  .filter { |callback| callback[:only].include? :create }
81
81
  .each { |callback| instance_exec(event, &callback[:block]) }
82
82
 
83
83
  when UpdateEvent
84
- @@change_callbacks[event.table]
84
+ @@change_callbacks[event.full_table_name]
85
85
  .filter { |callback| callback[:only].include? :update }
86
86
  .each do |callback|
87
87
  if (attributes = callback[:changed])
@@ -92,7 +92,7 @@ module Wal
92
92
  end
93
93
 
94
94
  when DeleteEvent
95
- @@delete_callbacks[event.table].each do |callback|
95
+ @@delete_callbacks[event.full_table_name].each do |callback|
96
96
  instance_exec(event, &callback[:block])
97
97
  end
98
98
  end
@@ -184,7 +184,7 @@ module Wal
184
184
  def on_update(event)
185
185
  if (id = event.primary_key)
186
186
  @records ||= {}
187
- @records[[event.table, id]] = case (existing_event = @records[[event.table, id]])
187
+ @records[[event.full_table_name, id]] = case (existing_event = @records[[event.full_table_name, id]])
188
188
  when InsertEvent
189
189
  # A record inserted on this transaction is being updated, which means it should still reflect as a insert
190
190
  # event, we just change the information to reflect the most current data that was just updated.
@@ -204,7 +204,7 @@ module Wal
204
204
  def on_delete(event)
205
205
  if (id = event.primary_key)
206
206
  @records ||= {}
207
- @records[[event.table, id]] = case (existing_event = @records[[event.table, id]])
207
+ @records[[event.full_table_name, id]] = case (existing_event = @records[[event.full_table_name, id]])
208
208
  when InsertEvent
209
209
  # We are removing a record that was inserted on this transaction, we should not even report this change, as
210
210
  # this record never existed outside this transaction anyways.
@@ -304,9 +304,9 @@ module Wal
304
304
  end
305
305
 
306
306
  def on_delete(event)
307
- case @table.where(table_name: event.table, primary_key: event.primary_key).pluck(:action, :old).first
307
+ case @table.where(table_name: event.full_table_name, primary_key: event.primary_key).pluck(:action, :old).first
308
308
  in ["insert", _]
309
- @table.where(table_name: event.table, primary_key: event.primary_key).delete_all
309
+ @table.where(table_name: event.full_table_name, primary_key: event.primary_key).delete_all
310
310
  in ["update", old]
311
311
  @table.upsert(serialize(event).merge(old:))
312
312
  in ["delete", _]
@@ -326,7 +326,7 @@ module Wal
326
326
  serialized = {
327
327
  transaction_id: event.transaction_id,
328
328
  lsn: event.lsn,
329
- table_name: event.table,
329
+ table_name: event.full_table_name,
330
330
  primary_key: event.primary_key,
331
331
  context: event.context,
332
332
  }
@@ -343,10 +343,12 @@ module Wal
343
343
  end
344
344
 
345
345
  def deserialize(persisted_event)
346
+ table, schema = persisted_event.table_name.split(".", 2)
346
347
  deserialized = {
347
348
  transaction_id: persisted_event.transaction_id,
348
349
  lsn: persisted_event.lsn,
349
- table: persisted_event.table_name,
350
+ schema: schema || "public",
351
+ table: table,
350
352
  primary_key: persisted_event.primary_key,
351
353
  context: persisted_event.context,
352
354
  }
@@ -47,10 +47,11 @@ module Wal
47
47
 
48
48
  watch_conn.start_pgoutput_replication_slot(@replication_slot, publications, messages: true).filter_map do |msg|
49
49
  case msg
50
- in XLogData(data: PG::Replication::PGOutput::Relation(oid:, name:, columns:))
50
+ in XLogData(data: PG::Replication::PGOutput::Relation(oid:, name:, columns:, namespace:))
51
51
  tables[oid] = Table.new(
52
52
  # TODO: for now we are forcing an id column here, but that is not really correct
53
53
  primary_key_colums: columns.any? { |col| col.name == "id" } ? ["id"] : [],
54
+ schema: namespace,
54
55
  name:,
55
56
  columns: columns.map do |col|
56
57
  Column.new(
@@ -100,7 +101,7 @@ module Wal
100
101
 
101
102
  in XLogData(lsn:, data: PG::Replication::PGOutput::Insert(oid:, new:))
102
103
  table = tables[oid]
103
- next unless watcher.should_watch_table? table.name
104
+ next unless watcher.should_watch_table? table.full_table_name
104
105
  new_data = table.decode_row(new)
105
106
  record_id = table.primary_key(new_data)
106
107
  next unless record_id
@@ -109,6 +110,7 @@ module Wal
109
110
  transaction_id:,
110
111
  lsn:,
111
112
  context:,
113
+ schema: table.schema,
112
114
  table: table.name,
113
115
  primary_key: record_id,
114
116
  new: new_data,
@@ -116,7 +118,7 @@ module Wal
116
118
 
117
119
  in XLogData(lsn:, data: PG::Replication::PGOutput::Update(oid:, new:, old:))
118
120
  table = tables[oid]
119
- next unless watcher.should_watch_table? table.name
121
+ next unless watcher.should_watch_table? table.full_table_name
120
122
  old_data = table.decode_row(old)
121
123
  new_data = table.decode_row(new)
122
124
  record_id = table.primary_key(new_data)
@@ -126,6 +128,7 @@ module Wal
126
128
  transaction_id:,
127
129
  lsn:,
128
130
  context:,
131
+ schema: table.schema,
129
132
  table: table.name,
130
133
  primary_key: record_id,
131
134
  old: old_data,
@@ -134,7 +137,7 @@ module Wal
134
137
 
135
138
  in XLogData(lsn:, data: PG::Replication::PGOutput::Delete(oid:, old:, key:))
136
139
  table = tables[oid]
137
- next unless watcher.should_watch_table? table.name
140
+ next unless watcher.should_watch_table? table.full_table_name
138
141
  old_data = table.decode_row(old.presence || key)
139
142
  record_id = table.primary_key(old_data)
140
143
  next unless record_id
@@ -143,6 +146,7 @@ module Wal
143
146
  transaction_id:,
144
147
  lsn:,
145
148
  context:,
149
+ schema: table.schema,
146
150
  table: table.name,
147
151
  primary_key: record_id,
148
152
  old: old_data,
@@ -160,7 +164,16 @@ module Wal
160
164
  end
161
165
  end
162
166
 
163
- class Table < Data.define(:name, :primary_key_colums, :columns)
167
+ class Table < Data.define(:schema, :name, :primary_key_colums, :columns)
168
+ def full_table_name
169
+ case schema
170
+ in "public"
171
+ name
172
+ else
173
+ "#{schema}.#{name}"
174
+ end
175
+ end
176
+
164
177
  def primary_key(decoded_row)
165
178
  case primary_key_colums
166
179
  in [key]
data/lib/wal/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Wal
4
- VERSION = "0.0.20"
4
+ VERSION = "0.0.21"
5
5
  end
data/lib/wal.rb CHANGED
@@ -29,6 +29,17 @@ module Wal
29
29
  class CommitTransactionEvent < Data.define(:transaction_id, :lsn, :context, :timestamp)
30
30
  end
31
31
 
32
+ module TableName
33
+ def full_table_name
34
+ case schema
35
+ in "public"
36
+ table
37
+ else
38
+ "#{schema}.#{table}"
39
+ end
40
+ end
41
+ end
42
+
32
43
  module ChangeEvent
33
44
  def diff
34
45
  {}
@@ -55,7 +66,8 @@ module Wal
55
66
  end
56
67
  end
57
68
 
58
- class InsertEvent < Data.define(:transaction_id, :lsn, :context, :table, :primary_key, :new)
69
+ class InsertEvent < Data.define(:transaction_id, :lsn, :context, :schema, :table, :primary_key, :new)
70
+ include ::Wal::TableName
59
71
  include ::Wal::ChangeEvent
60
72
 
61
73
  def diff
@@ -63,7 +75,8 @@ module Wal
63
75
  end
64
76
  end
65
77
 
66
- class UpdateEvent < Data.define(:transaction_id, :lsn, :context, :table, :primary_key, :old, :new)
78
+ class UpdateEvent < Data.define(:transaction_id, :lsn, :context, :schema, :table, :primary_key, :old, :new)
79
+ include ::Wal::TableName
67
80
  include ::Wal::ChangeEvent
68
81
 
69
82
  def diff
@@ -73,7 +86,8 @@ module Wal
73
86
  end
74
87
  end
75
88
 
76
- class DeleteEvent < Data.define(:transaction_id, :lsn, :context, :table, :primary_key, :old)
89
+ class DeleteEvent < Data.define(:transaction_id, :lsn, :context, :schema, :table, :primary_key, :old)
90
+ include ::Wal::TableName
77
91
  include ::Wal::ChangeEvent
78
92
 
79
93
  def diff
data/rbi/wal.rbi CHANGED
@@ -7,7 +7,7 @@ module Wal
7
7
  UpdateEvent,
8
8
  DeleteEvent,
9
9
  ) }
10
- VERSION = "0.0.20"
10
+ VERSION = "0.0.21"
11
11
 
12
12
  class << self
13
13
  sig { returns(T.class_of(Logger)) }
@@ -37,6 +37,13 @@ module Wal
37
37
 
38
38
  end
39
39
 
40
+ module TableName
41
+ extend T::Sig
42
+
43
+ sig { returns(String) }
44
+ def full_table_name; end
45
+ end
46
+
40
47
  module ChangeEvent
41
48
  extend T::Sig
42
49
 
@@ -60,10 +67,12 @@ module Wal
60
67
  prop :transaction_id, Integer, immutable: true
61
68
  prop :lsn, Integer, immutable: true
62
69
  prop :context, T::Hash[String, T.untyped], immutable: true
70
+ prop :schema, String, immutable: true
63
71
  prop :table, String, immutable: true
64
72
  prop :primary_key, T.untyped, immutable: true
65
73
  prop :new, T::Hash[String, T.untyped], immutable: true
66
74
 
75
+ include ::Wal::TableName
67
76
  include ::Wal::ChangeEvent
68
77
  extend T::Sig
69
78
 
@@ -75,11 +84,13 @@ module Wal
75
84
  prop :transaction_id, Integer, immutable: true
76
85
  prop :lsn, Integer, immutable: true
77
86
  prop :context, T::Hash[String, T.untyped], immutable: true
87
+ prop :schema, String, immutable: true
78
88
  prop :table, String, immutable: true
79
89
  prop :primary_key, T.untyped, immutable: true
80
90
  prop :old, T::Hash[String, T.untyped], immutable: true
81
91
  prop :new, T::Hash[String, T.untyped], immutable: true
82
92
 
93
+ include ::Wal::TableName
83
94
  include ::Wal::ChangeEvent
84
95
  extend T::Sig
85
96
 
@@ -91,10 +102,12 @@ module Wal
91
102
  prop :transaction_id, Integer, immutable: true
92
103
  prop :lsn, Integer, immutable: true
93
104
  prop :context, T::Hash[String, T.untyped], immutable: true
105
+ prop :schema, String, immutable: true
94
106
  prop :table, String, immutable: true
95
107
  prop :primary_key, T.untyped, immutable: true
96
108
  prop :old, T::Hash[String, T.untyped], immutable: true
97
109
 
110
+ include ::Wal::TableName
98
111
  include ::Wal::ChangeEvent
99
112
  extend T::Sig
100
113
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.20
4
+ version: 0.0.21
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Navarro
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-09-20 00:00:00.000000000 Z
10
+ date: 2025-10-09 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: pg
@@ -105,7 +105,7 @@ files:
105
105
  - lib/wal/watcher.rb
106
106
  - rbi/wal.rbi
107
107
  licenses:
108
- - MIT
108
+ - BSD-3-Clause
109
109
  metadata:
110
110
  homepage_uri: https://github.com/reu/wal
111
111
  source_code_uri: https://github.com/reu/wal