waldit 0.0.15 → 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 +4 -4
- data/lib/waldit/record.rb +2 -3
- data/lib/waldit/version.rb +1 -1
- data/lib/waldit/watcher.rb +65 -41
- data/rbi/waldit.rbi +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6c66dca1c2f51bdaa3f85e6f3f13930536e9352e6d5958f8b8eab140a108cab4
|
4
|
+
data.tar.gz: 43d8b34c506b98f5213372e624ab35d19f586570c47cf3abc5e692ec85ead638
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 261e9f0b9bf6948c6fa6ac2f2bfd3dc2baf15541aa7ef18818b9aef76af08925427cf90a195bc32008c17bd674991687ac24cb1fe95b65d7cef08574c57aee08
|
7
|
+
data.tar.gz: 3a3dbf1982be4498d393f6ff10ce5be88835c34cdc0272be8d692db1ed5886ff66af1ea41f3e2f1dd79eab24a1ddf2d695c1a93ae74b38117d54de38e85695a0
|
data/lib/waldit/record.rb
CHANGED
@@ -4,11 +4,10 @@ module Waldit
|
|
4
4
|
module Record
|
5
5
|
def self.included(base)
|
6
6
|
base.class_eval do
|
7
|
-
|
8
|
-
scope :from_table, -> table { where(table_name: table) }
|
7
|
+
scope :from_table, -> table { order(:committed_at).where(table_name: table) }
|
9
8
|
scope :from_model, -> model { from_table(model.table_name) }
|
10
9
|
scope :for, -> record { from_model(record.class).where(primary_key: record.id) }
|
11
|
-
scope :with_context, -> ctx { where("context @> ?", ctx.to_json) }
|
10
|
+
scope :with_context, -> ctx { order(:committed_at).where("context @> ?", ctx.to_json) }
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
data/lib/waldit/version.rb
CHANGED
data/lib/waldit/watcher.rb
CHANGED
@@ -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
|
-
|
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| "
|
56
|
-
log_old = (changes[:old] || []).map { |table| "
|
57
|
-
log_diff = (changes[:diff] || []).map { |table| "
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
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
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.
|
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-
|
10
|
+
date: 2025-09-08 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: wal
|