waldit 0.0.16 → 0.0.17

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: a323599011304e72762f4fc8662221c438056c64d4bc0e1918f88749c4e4079b
4
- data.tar.gz: d2495606705b6d2f85eb003a5a56c2be98895f168ec6c4fb5d656f6b4c8f2134
3
+ metadata.gz: 6c66dca1c2f51bdaa3f85e6f3f13930536e9352e6d5958f8b8eab140a108cab4
4
+ data.tar.gz: 43d8b34c506b98f5213372e624ab35d19f586570c47cf3abc5e692ec85ead638
5
5
  SHA512:
6
- metadata.gz: '08cc2d9380a1a4f085657bcc49784b123f73dae3861483c7e19114d67790e7085ba60b7e267df20d438c611b8c2b4b311347d824091f7a74da76ba23f3e3b9de'
7
- data.tar.gz: 32991fc4275d025c28fea6852f08c052d14f9c1295002252a2f007fdd48dc7341d8a0b2c72ea7af73aacf32b6af680dd110741c37cadc296528f3f9444f6a652
6
+ metadata.gz: 261e9f0b9bf6948c6fa6ac2f2bfd3dc2baf15541aa7ef18818b9aef76af08925427cf90a195bc32008c17bd674991687ac24cb1fe95b65d7cef08574c57aee08
7
+ data.tar.gz: 3a3dbf1982be4498d393f6ff10ce5be88835c34cdc0272be8d692db1ed5886ff66af1ea41f3e2f1dd79eab24a1ddf2d695c1a93ae74b38117d54de38e85695a0
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Waldit
4
- VERSION = "0.0.16"
4
+ VERSION = "0.0.17"
5
5
  end
@@ -35,72 +35,58 @@ module Waldit
35
35
  end
36
36
  end
37
37
 
38
+ def initialize(*)
39
+ super
40
+ initialize_connection
41
+ @retry = false
42
+ end
43
+
38
44
  def on_transaction_events(events)
39
- record.transaction do
40
- @connection = record.connection.raw_connection
45
+ @connection.transaction do
41
46
  tables = Set.new
42
- insert_prepared = false
43
- update_prepared = false
44
- delete_prepared = false
45
47
 
46
48
  events.each do |event|
47
49
  case event
48
50
  when CommitTransactionEvent
49
- record.where(transaction_id: event.transaction_id).update_all(committed_at: event.timestamp)
50
-
51
51
  changes = [:old, :new, :diff]
52
52
  .map { |diff| [diff, tables.filter { |table| Waldit.store_changes.call(table).include? diff }] }
53
53
  .to_h
54
54
 
55
- log_new = (changes[:new] || []).map { |table| "'#{table}'" }.join(",")
56
- log_old = (changes[:old] || []).map { |table| "'#{table}'" }.join(",")
57
- log_diff = (changes[:diff] || []).map { |table| "'#{table}'" }.join(",")
58
-
59
- record.where(transaction_id: event.transaction_id, action: "update").update_all(<<~SQL)
60
- new = CASE WHEN table_name = ANY (ARRAY[#{log_new}]::varchar[]) THEN new ELSE null END,
61
- old = CASE WHEN table_name = ANY (ARRAY[#{log_old}]::varchar[]) THEN old ELSE null END,
62
- diff =
63
- CASE WHEN table_name = ANY (ARRAY[#{log_diff}]::varchar[]) THEN (
64
- SELECT
65
- jsonb_object_agg(
66
- coalesce(old_kv.key, new_kv.key),
67
- jsonb_build_array(old_kv.value, new_kv.value)
68
- )
69
- FROM jsonb_each(old) AS old_kv
70
- FULL OUTER JOIN jsonb_each(new) AS new_kv ON old_kv.key = new_kv.key
71
- WHERE old_kv.value IS DISTINCT FROM new_kv.value
72
- )
73
- ELSE null
74
- END
75
- SQL
55
+ log_new = (changes[:new] || []).map { |table| "#{table}" }.join(",")
56
+ log_old = (changes[:old] || []).map { |table| "#{table}" }.join(",")
57
+ log_diff = (changes[:diff] || []).map { |table| "#{table}" }.join(",")
58
+
59
+ @connection.exec_prepared("waldit_finish", [
60
+ event.transaction_id,
61
+ event.timestamp,
62
+ "{#{log_new}}",
63
+ "{#{log_old}}",
64
+ "{#{log_diff}}",
65
+ ])
66
+
67
+ # We sucessful retried a connection, let's reset our retry state
68
+ @retry = false
76
69
 
77
70
  when InsertEvent
78
71
  tables << event.table
79
- unless insert_prepared
80
- prepare_insert
81
- insert_prepared = true
82
- end
83
72
  audit_event(event)
84
73
 
85
74
  when UpdateEvent
86
75
  tables << event.table
87
- unless update_prepared
88
- prepare_update
89
- update_prepared = true
90
- end
91
76
  audit_event(event)
92
77
 
93
78
  when DeleteEvent
94
79
  tables << event.table
95
- unless delete_prepared
96
- prepare_delete
97
- prepare_delete_cleanup
98
- delete_prepared = true
99
- end
100
80
  audit_event(event)
101
81
  end
102
82
  end
103
83
  end
84
+ rescue PG::ConnectionBad
85
+ raise if @retry
86
+ # Let's try to fetch a new connection and reprocess the transaction
87
+ initialize_connection
88
+ @retry = true
89
+ retry
104
90
  end
105
91
 
106
92
  def should_watch_table?(table)
@@ -125,6 +111,15 @@ module Waldit
125
111
 
126
112
  private
127
113
 
114
+ def initialize_connection
115
+ @connection = record.connection.raw_connection
116
+ prepare_insert
117
+ prepare_update
118
+ prepare_delete
119
+ prepare_delete_cleanup
120
+ prepare_finish
121
+ end
122
+
128
123
  def prepare_insert
129
124
  @connection.prepare("waldit_insert", <<~SQL)
130
125
  INSERT INTO #{record.table_name} (transaction_id, lsn, table_name, primary_key, action, context, new)
@@ -132,6 +127,7 @@ module Waldit
132
127
  ON CONFLICT (table_name, primary_key, transaction_id)
133
128
  DO UPDATE SET new = #{record.table_name}.new
134
129
  SQL
130
+ rescue PG::DuplicatePstatement
135
131
  end
136
132
 
137
133
  def prepare_update
@@ -141,6 +137,7 @@ module Waldit
141
137
  ON CONFLICT (table_name, primary_key, transaction_id)
142
138
  DO UPDATE SET new = excluded.new
143
139
  SQL
140
+ rescue PG::DuplicatePstatement
144
141
  end
145
142
 
146
143
  def prepare_delete
@@ -150,6 +147,7 @@ module Waldit
150
147
  ON CONFLICT (table_name, primary_key, transaction_id)
151
148
  DO UPDATE SET old = #{record.table_name}.old
152
149
  SQL
150
+ rescue PG::DuplicatePstatement
153
151
  end
154
152
 
155
153
  def prepare_delete_cleanup
@@ -162,6 +160,32 @@ module Waldit
162
160
  AND action IN ('insert'::waldit_action, 'update'::waldit_action)
163
161
  RETURNING action, old
164
162
  SQL
163
+ rescue PG::DuplicatePstatement
164
+ end
165
+
166
+ def prepare_finish
167
+ @connection.prepare("waldit_finish", <<~SQL)
168
+ UPDATE #{record.table_name}
169
+ SET
170
+ committed_at = $2,
171
+ new = CASE WHEN table_name = ANY ($3::varchar[]) THEN new ELSE null END,
172
+ old = CASE WHEN table_name = ANY ($4::varchar[]) THEN old ELSE null END,
173
+ diff =
174
+ CASE WHEN table_name = ANY ($5::varchar[]) THEN (
175
+ SELECT
176
+ jsonb_object_agg(
177
+ coalesce(old_kv.key, new_kv.key),
178
+ jsonb_build_array(old_kv.value, new_kv.value)
179
+ )
180
+ FROM jsonb_each(old) AS old_kv
181
+ FULL OUTER JOIN jsonb_each(new) AS new_kv ON old_kv.key = new_kv.key
182
+ WHERE old_kv.value IS DISTINCT FROM new_kv.value
183
+ )
184
+ ELSE null
185
+ END
186
+ WHERE transaction_id = $1
187
+ SQL
188
+ rescue PG::DuplicatePstatement
165
189
  end
166
190
  end
167
191
  end
data/rbi/waldit.rbi CHANGED
@@ -2,7 +2,7 @@
2
2
  module Waldit
3
3
  extend T::Sig
4
4
  extend Waldit::Context
5
- VERSION = "0.0.16"
5
+ VERSION = "0.0.17"
6
6
 
7
7
  class << self
8
8
  sig { returns(String) }
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: waldit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.16
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rodrigo Navarro
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-09-05 00:00:00.000000000 Z
10
+ date: 2025-09-08 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: wal