pub_sub_model_sync 1.0.beta → 1.0.beta1
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/.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
|