pub_sub_model_sync 1.0.beta → 1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -2
- data/Gemfile.lock +7 -2
- data/README.md +5 -3
- data/lib/pub_sub_model_sync/config.rb +2 -1
- data/lib/pub_sub_model_sync/initializers/before_commit.rb +23 -0
- data/lib/pub_sub_model_sync/message_publisher.rb +1 -1
- data/lib/pub_sub_model_sync/publisher_concern.rb +10 -7
- data/lib/pub_sub_model_sync/railtie.rb +5 -0
- data/lib/pub_sub_model_sync/transaction.rb +30 -20
- data/lib/pub_sub_model_sync/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13b5f627ef31865359d033508451bca2297f99cf2cba31d2d3b1a0edb5e0120e
|
4
|
+
data.tar.gz: e273ff16f01bda1cae1ec2d78b8fd33174dadccdc78b4430503bd5ae40a35988
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bbff15963073476121be61b70abc9899b34c88f12d4b0c75e658f9554cb97b7a6adfeeff7eb1b265fcdd46d3ab2a9bfe97274fc9cd2d67b3a7192d28cf52fb8
|
7
|
+
data.tar.gz: dea3272e6930728975dfa140e5b49355ce799c9361d892f0d2acd5a665a699f16383a930db714f64746f03185726abaa1a477da1ae03a3ca22730e750397dccc
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pub_sub_model_sync (1.0.
|
4
|
+
pub_sub_model_sync (1.0.beta1)
|
5
5
|
rails
|
6
6
|
|
7
7
|
GEM
|
@@ -115,6 +115,7 @@ GEM
|
|
115
115
|
gapic-common (~> 0.3)
|
116
116
|
google-cloud-errors (~> 1.0)
|
117
117
|
grpc-google-iam-v1 (>= 0.6.10, < 2.0)
|
118
|
+
google-protobuf (3.17.0)
|
118
119
|
google-protobuf (3.17.0-x86_64-linux)
|
119
120
|
googleapis-common-protos (1.3.11)
|
120
121
|
google-protobuf (~> 3.14)
|
@@ -129,6 +130,9 @@ GEM
|
|
129
130
|
multi_json (~> 1.11)
|
130
131
|
os (>= 0.9, < 2.0)
|
131
132
|
signet (~> 0.14)
|
133
|
+
grpc (1.37.1)
|
134
|
+
google-protobuf (~> 3.15)
|
135
|
+
googleapis-common-protos-types (~> 1.0)
|
132
136
|
grpc (1.37.1-x86_64-linux)
|
133
137
|
google-protobuf (~> 3.15)
|
134
138
|
googleapis-common-protos-types (~> 1.0)
|
@@ -152,7 +156,7 @@ GEM
|
|
152
156
|
multi_json (1.15.0)
|
153
157
|
multipart-post (2.1.1)
|
154
158
|
nio4r (2.5.7)
|
155
|
-
nokogiri (1.11.3-x86_64-
|
159
|
+
nokogiri (1.11.3-x86_64-darwin)
|
156
160
|
racc (~> 1.4)
|
157
161
|
os (1.1.1)
|
158
162
|
parallel (1.20.1)
|
@@ -244,6 +248,7 @@ GEM
|
|
244
248
|
zeitwerk (2.4.2)
|
245
249
|
|
246
250
|
PLATFORMS
|
251
|
+
ruby
|
247
252
|
x86_64-linux
|
248
253
|
|
249
254
|
DEPENDENCIES
|
data/README.md
CHANGED
@@ -364,9 +364,9 @@ Any notification before delivering is transformed as a Payload for a better port
|
|
364
364
|
**Note**: When any error is raised when saving user or posts, the transaction is cancelled and thus all notifications wont be delivered (customizable by `PubSubModelSync::Config.transactions_use_buffer`).
|
365
365
|
|
366
366
|
- Manual transactions
|
367
|
-
`PubSubModelSync::MessagePublisher::transaction(key,
|
367
|
+
`PubSubModelSync::MessagePublisher::transaction(key, max_buffer: , &block)`
|
368
368
|
- `key` (String|nil) Key used as the ordering key for all inner notifications (When nil, will use `ordering_key` of the first notification)
|
369
|
-
- `
|
369
|
+
- `max_buffer:` (Boolean, default: `PubSubModelSync::Config.transactions_max_buffer`)
|
370
370
|
If true: will save all notifications and deliver all them when transaction has successfully finished. If transaction has failed, then all saved notifications will be discarded (not delivered).
|
371
371
|
If false: will deliver all notifications immediately (no way to rollback notifications if transaction has failed)
|
372
372
|
Sample:
|
@@ -479,7 +479,9 @@ config.debug = true
|
|
479
479
|
(Proc) => called after publishing a message
|
480
480
|
- ```.on_error_publish = ->(exception, {payload:}) { payload.delay(...).publish! }```
|
481
481
|
(Proc) => called when failed publishing a message (delayed_job or similar can be used for retrying)
|
482
|
-
- ```.
|
482
|
+
- ```.transactions_max_buffer = 100``` (Integer) Once this quantity of notifications is reached, then all notifications will immediately be delivered.
|
483
|
+
Note: There is no way to rollback delivered notifications if current transaction fails
|
484
|
+
- ```.enable_rails4_before_commit = true``` (true*|false) When false will disable rails 4 hack compatibility and then CRUD notifications will be prepared using `after_commit` callback instead of `before_commit` which will not rollback sql transactions if fails.
|
483
485
|
|
484
486
|
## **TODO**
|
485
487
|
- Auto publish update only if payload has changed (see ways to compare previous payload vs new payload)
|
@@ -8,7 +8,8 @@ module PubSubModelSync
|
|
8
8
|
# customizable callbacks
|
9
9
|
cattr_accessor(:debug) { false }
|
10
10
|
cattr_accessor :logger # LoggerInst
|
11
|
-
cattr_accessor(:
|
11
|
+
cattr_accessor(:transactions_max_buffer) { 100 }
|
12
|
+
cattr_accessor(:enable_rails4_before_commit) { Rails::VERSION::MAJOR == 4 }
|
12
13
|
|
13
14
|
cattr_accessor(:on_before_processing) { ->(_payload, _info) {} } # return :cancel to skip
|
14
15
|
cattr_accessor(:on_success_processing) { ->(_payload, _info) {} }
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Rails 4 backward compatibility (Add "simple" ps_before_*_commit callbacks)
|
4
|
+
ActiveRecord::ConnectionAdapters::RealTransaction.class_eval do
|
5
|
+
alias_method :commit_with_before_commit, :commit
|
6
|
+
|
7
|
+
def commit
|
8
|
+
call_before_commit_records if Rails::VERSION::MAJOR == 4
|
9
|
+
commit_with_before_commit
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def call_before_commit_records
|
15
|
+
ite = records.uniq
|
16
|
+
ite.each do |record|
|
17
|
+
action = record.previous_changes.include?(:id) ? :create : :update
|
18
|
+
action = :destroy if record.destroyed?
|
19
|
+
callback_name = "ps_before_#{action}_commit".to_sym
|
20
|
+
record.send(callback_name) if record.respond_to?(callback_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -55,14 +55,17 @@ module PubSubModelSync
|
|
55
55
|
|
56
56
|
# @param crud_actions (Symbol|Array<Symbol>): :create, :update, :destroy
|
57
57
|
# @param method_name (Symbol, optional) method to be called
|
58
|
-
def ps_on_crud_event(crud_actions, method_name = nil, &block)
|
59
|
-
crud_actions = Array(crud_actions)
|
58
|
+
def ps_on_crud_event(crud_actions, method_name = nil, &block) # rubocop:disable Metrics/MethodLength
|
60
59
|
callback = ->(action) { method_name ? send(method_name, action) : instance_exec(action, &block) }
|
61
60
|
commit_name = respond_to?(:before_commit) ? :before_commit : :after_commit
|
62
|
-
crud_actions.each do |action|
|
63
|
-
|
64
|
-
|
65
|
-
|
61
|
+
Array(crud_actions).each do |action|
|
62
|
+
if action == :destroy
|
63
|
+
after_destroy { instance_exec(action, &callback) }
|
64
|
+
elsif PubSubModelSync::Config.enable_rails4_before_commit # rails 4 compatibility
|
65
|
+
define_method("ps_before_#{action}_commit") { instance_exec(action, &callback) }
|
66
|
+
else
|
67
|
+
send(commit_name, on: action) { instance_exec(action, &callback) }
|
68
|
+
end
|
66
69
|
end
|
67
70
|
end
|
68
71
|
|
@@ -77,7 +80,7 @@ module PubSubModelSync
|
|
77
80
|
after_create start_transaction, prepend: true # wait for ID
|
78
81
|
before_update start_transaction, prepend: true
|
79
82
|
before_destroy start_transaction, prepend: true
|
80
|
-
after_commit { @ps_transaction.
|
83
|
+
after_commit { @ps_transaction.finish }
|
81
84
|
after_rollback(prepend: true) { @ps_transaction.rollback }
|
82
85
|
end
|
83
86
|
end
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require 'pub_sub_model_sync'
|
4
4
|
require 'rails'
|
5
|
+
require 'pub_sub_model_sync/config'
|
5
6
|
module PubSubModelSync
|
6
7
|
class Railtie < ::Rails::Railtie
|
7
8
|
railtie_name :pub_sub_model_sync
|
@@ -9,5 +10,9 @@ module PubSubModelSync
|
|
9
10
|
rake_tasks do
|
10
11
|
load 'pub_sub_model_sync/tasks/worker.rake'
|
11
12
|
end
|
13
|
+
|
14
|
+
configure do
|
15
|
+
require 'pub_sub_model_sync/initializers/before_commit' if PubSubModelSync::Config.enable_rails4_before_commit
|
16
|
+
end
|
12
17
|
end
|
13
18
|
end
|
@@ -3,55 +3,65 @@
|
|
3
3
|
module PubSubModelSync
|
4
4
|
class Transaction < Base
|
5
5
|
PUBLISHER_KLASS = PubSubModelSync::MessagePublisher
|
6
|
-
attr_accessor :key, :payloads, :
|
6
|
+
attr_accessor :key, :payloads, :max_buffer, :root, :children, :finished
|
7
7
|
|
8
8
|
# @param key (String|nil) Transaction key, if empty will use the ordering_key from first payload
|
9
|
-
# @param
|
10
|
-
#
|
11
|
-
|
9
|
+
# @param max_buffer (Integer) Once this quantity of notifications is reached, then all notifications
|
10
|
+
# will immediately be delivered.
|
11
|
+
# Note: There is no way to rollback delivered notifications if current transaction fails
|
12
|
+
def initialize(key, max_buffer: config.transactions_max_buffer)
|
12
13
|
@key = key
|
13
|
-
@
|
14
|
+
@max_buffer = max_buffer
|
14
15
|
@children = []
|
15
16
|
@payloads = []
|
16
17
|
end
|
17
18
|
|
18
19
|
# @param payload (Payload)
|
19
20
|
def add_payload(payload)
|
20
|
-
|
21
|
+
payloads << payload
|
22
|
+
deliver_payloads if payloads.count >= max_buffer
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
24
|
-
if
|
25
|
-
|
26
|
-
|
25
|
+
def finish # rubocop:disable Metrics/AbcSize
|
26
|
+
if root
|
27
|
+
root.children = root.children.reject { |t| t == self }
|
28
|
+
root.deliver_all if root.finished && root.children.empty?
|
27
29
|
end
|
28
|
-
|
29
|
-
|
30
|
+
self.finished = true
|
31
|
+
deliver_all if children.empty?
|
30
32
|
end
|
31
33
|
|
32
34
|
def add_transaction(transaction)
|
33
|
-
transaction.
|
35
|
+
transaction.root = self
|
34
36
|
children << transaction
|
35
37
|
transaction
|
36
38
|
end
|
37
39
|
|
38
40
|
def rollback
|
39
|
-
log("rollback #{
|
41
|
+
log("rollback #{payloads.count} notifications", :warn) if children.any? && debug?
|
40
42
|
self.children = []
|
41
|
-
|
43
|
+
root&.rollback
|
42
44
|
clean_publisher
|
43
45
|
end
|
44
46
|
|
45
47
|
def clean_publisher
|
46
|
-
PUBLISHER_KLASS.current_transaction = nil if !
|
48
|
+
PUBLISHER_KLASS.current_transaction = nil if !root && children.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
def deliver_all
|
52
|
+
deliver_payloads
|
53
|
+
clean_publisher
|
47
54
|
end
|
48
55
|
|
49
56
|
private
|
50
57
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
def deliver_payloads
|
59
|
+
payloads.each do |payload|
|
60
|
+
PUBLISHER_KLASS.connector_publish(payload)
|
61
|
+
rescue => e
|
62
|
+
PUBLISHER_KLASS.send(:notify_error, e, payload)
|
63
|
+
end
|
64
|
+
self.payloads = []
|
55
65
|
end
|
56
66
|
end
|
57
67
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pub_sub_model_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -110,6 +110,7 @@ files:
|
|
110
110
|
- lib/pub_sub_model_sync/base.rb
|
111
111
|
- lib/pub_sub_model_sync/config.rb
|
112
112
|
- lib/pub_sub_model_sync/connector.rb
|
113
|
+
- lib/pub_sub_model_sync/initializers/before_commit.rb
|
113
114
|
- lib/pub_sub_model_sync/message_processor.rb
|
114
115
|
- lib/pub_sub_model_sync/message_publisher.rb
|
115
116
|
- lib/pub_sub_model_sync/mock_google_service.rb
|