pub_sub_model_sync 1.5.1pre → 1.6.1pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +8 -4
- data/lib/pub_sub_model_sync/message_processor.rb +8 -7
- data/lib/pub_sub_model_sync/message_publisher.rb +8 -3
- data/lib/pub_sub_model_sync/publisher_concern.rb +2 -4
- data/lib/pub_sub_model_sync/service_base.rb +2 -2
- data/lib/pub_sub_model_sync/transaction.rb +3 -2
- data/lib/pub_sub_model_sync/version.rb +1 -1
- data/pub_sub_model_sync.gemspec +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: 8ef75354a40d7b4da0e81bf3d56dcafca197f63827e77ec504bb041875032d6c
|
4
|
+
data.tar.gz: 7ebcdc2be8176224f774b9ea65d4cdd98829d2b514a0fa13d3e8938abe56e8af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9dddee04900a58852d7410b3aeaeefc8875703c67cfa7e8becb90ecb74cfb92c4126e8de1db7e52a57ff639d5c254665886f94abbea4d3e6ba859a52ca62cde
|
7
|
+
data.tar.gz: acb90e09cc29fa7e8d26b88cd1c5a4b34a74d09af84b263389cdf3b4e694d44d823f6addd0656f145503dea17d87898d9e029c6e4829822b11c595617e38a0d7
|
data/.github/workflows/ruby.yml
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -271,8 +271,10 @@ PubSubModelSync::Payload.new({ ids: [my_user.id] }, { klass: 'User', action: :ba
|
|
271
271
|
- `as_klass:` (String, default current class name): Class name of the notification
|
272
272
|
- `headers:` (Hash, optional): header settings (More in Payload.headers)
|
273
273
|
|
274
|
-
- `ps_perform_publish(action = :create)` Permits to perform manually the callback of a specific `ps_after_action`
|
274
|
+
- `ps_perform_publish(action = :create, parents_actions: false)` Permits to perform manually the callback of a specific `ps_after_action`
|
275
275
|
- `action` (Symbol, default: :create) Only :create|:update|:destroy
|
276
|
+
- `parents_actions` (Boolean, default: false) When `true`, includes inherited PubSub-callbacks from parent classes
|
277
|
+
|
276
278
|
|
277
279
|
#### **Publisher helpers**
|
278
280
|
- Publish or republish a notification
|
@@ -317,6 +319,7 @@ Any notification before delivering is transformed as a Payload for a better port
|
|
317
319
|
Note: Final `ordering_key` is calculated as: `payload.headers[:forced_ordering_key] || current_transaction&.key || payload.headers[:ordering_key]`
|
318
320
|
- `topic_name`: (String|Array<String>, optional): Specific topic name where to deliver the notification (default `PubSubModelSync::Config.topic_name`).
|
319
321
|
- `forced_ordering_key`: (String, optional): Overrides `ordering_key` with the provided value even withing transactions. Default `nil`.
|
322
|
+
- `target_app_key`: (String, optional): Allows to send the notification to a specific app (includes the application key, separated by comma when multiple apps). Default `nil`.
|
320
323
|
- `cache` (Boolean | Hash, Default false) Cache settings
|
321
324
|
- `true`: Skip publishing similar payloads
|
322
325
|
- `Hash<required: Array<Symbol>>`: Same as `true` and enables payload optimization to exclude unchanged non important attributes. Sample: `{ required: %i[id email] }`
|
@@ -379,16 +382,17 @@ Note: To reduce Payload size, some header info are not delivered (Enable debug m
|
|
379
382
|
- Manual transactions
|
380
383
|
`PubSubModelSync::MessagePublisher::transaction(key, max_buffer: , &block)`
|
381
384
|
- `key` (String|nil) Key used as the ordering_key for all inner notifications (When nil, will use `ordering_key` of the first notification)
|
382
|
-
- `max_buffer:` (Integer, default: `PubSubModelSync::Config.transactions_max_buffer`) Transaction buffer size (
|
385
|
+
- `max_buffer:` (Integer, default: `PubSubModelSync::Config.transactions_max_buffer`) Transaction buffer size (DEPRECATED).
|
386
|
+
- `headers:` (Hash) Header settings to be added to each Payload's header inside this transaction
|
383
387
|
Sample:
|
384
388
|
```ruby
|
385
|
-
PubSubModelSync::MessagePublisher::transaction('my-custom-key') do
|
389
|
+
PubSubModelSync::MessagePublisher::transaction('my-custom-key', headers: { key: 'my-key' }) do
|
386
390
|
user = User.create(name: 'test') # `User`:`:create` notification
|
387
391
|
post = Post.create(title: 'sample') # `Post`:`:create` notification
|
388
392
|
PubSubModelSync::Payload.new({ ids: [user.id] }, { klass: 'User', action: :send_welcome, mode: :klass }).publish! # `User`:`:send_welcome` notification
|
389
393
|
end
|
390
394
|
```
|
391
|
-
All notifications uses `ordering_key: 'my-custom-key'` and will be processed in the same order they were published.
|
395
|
+
All notifications uses `ordering_key: 'my-custom-key'` and will be processed in the same order they were published (Payload headers will include `key="my-key"`).
|
392
396
|
|
393
397
|
## **Testing with RSpec**
|
394
398
|
- Config: (spec/rails_helper.rb)
|
@@ -23,15 +23,15 @@ module PubSubModelSync
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def process
|
26
|
-
retries ||= 0
|
27
26
|
process!
|
28
27
|
rescue => e
|
29
|
-
|
28
|
+
notify_error(e)
|
30
29
|
end
|
31
30
|
|
32
31
|
private
|
33
32
|
|
34
|
-
def run_subscriber(subscriber)
|
33
|
+
def run_subscriber(subscriber) # rubocop:disable Metrics/AbcSize
|
34
|
+
retries ||= 0
|
35
35
|
processor = PubSubModelSync::RunSubscriber.new(subscriber, payload)
|
36
36
|
return unless processable?(subscriber)
|
37
37
|
|
@@ -39,6 +39,10 @@ module PubSubModelSync
|
|
39
39
|
processor.call
|
40
40
|
res = config.on_success_processing.call(payload, { subscriber: subscriber })
|
41
41
|
log "processed message with: #{payload.inspect}" if res != :skip_log
|
42
|
+
rescue => e
|
43
|
+
rr = retry_process?(e, retries += 1)
|
44
|
+
log("failed processing sync: #{{ klass: e.class.name, msg: e.message, retries: retries, rr: rr, payload: payload }.inspect}", :error)
|
45
|
+
rr ? retry : raise(e)
|
42
46
|
end
|
43
47
|
|
44
48
|
def processable?(subscriber)
|
@@ -47,7 +51,7 @@ module PubSubModelSync
|
|
47
51
|
!cancel
|
48
52
|
end
|
49
53
|
|
50
|
-
# @param error (StandardError)
|
54
|
+
# @param error (StandardError, Exception)
|
51
55
|
def notify_error(error)
|
52
56
|
error_msg = 'Error processing message: '
|
53
57
|
error_details = [payload, error.message, error.backtrace]
|
@@ -67,9 +71,6 @@ module PubSubModelSync
|
|
67
71
|
|
68
72
|
def retry_process?(error, retries) # rubocop:disable Metrics/MethodLength
|
69
73
|
error_payload = [payload, error.message, error.backtrace]
|
70
|
-
if error.message.include('Connection refused') || error.message.include('no connection to the server')
|
71
|
-
log("Error pubsub: #{[error.class.name, error.message]} (retries: #{retries}) => #{lost_db_connection?(error)}", :error)
|
72
|
-
end
|
73
74
|
return false unless lost_db_connection?(error)
|
74
75
|
|
75
76
|
if retries <= 5
|
@@ -18,6 +18,9 @@ module PubSubModelSync
|
|
18
18
|
# worker/thread.
|
19
19
|
# @see Transaction.new(...)
|
20
20
|
# @param key (String|Nil)
|
21
|
+
# @param settings (Hash<:headers, :max_buffer>)
|
22
|
+
# @option headers [Hash] Headers to be merged for each payload inside this transaction
|
23
|
+
# @option max_buffer [Integer] Deprecated
|
21
24
|
# @param block (Yield) block to be executed
|
22
25
|
def transaction(key, settings = {}, &block)
|
23
26
|
t = init_transaction(key, settings)
|
@@ -71,7 +74,7 @@ module PubSubModelSync
|
|
71
74
|
# @return Payload
|
72
75
|
# Raises error if exist
|
73
76
|
def publish!(payload, &block)
|
74
|
-
|
77
|
+
add_transaction_headers(payload)
|
75
78
|
return unless ensure_publish(payload)
|
76
79
|
|
77
80
|
current_transaction ? current_transaction.add_payload(payload) : connector_publish(payload)
|
@@ -106,8 +109,10 @@ module PubSubModelSync
|
|
106
109
|
!cancelled
|
107
110
|
end
|
108
111
|
|
109
|
-
def
|
110
|
-
payload.headers[:forced_ordering_key] || current_transaction&.key || payload.headers[:ordering_key]
|
112
|
+
def add_transaction_headers(payload)
|
113
|
+
key = payload.headers[:forced_ordering_key] || current_transaction&.key || payload.headers[:ordering_key]
|
114
|
+
payload.headers[:ordering_key] = key
|
115
|
+
payload.headers.merge!(current_transaction.headers) if current_transaction
|
111
116
|
end
|
112
117
|
|
113
118
|
def ensure_model_publish(model, action, payload)
|
@@ -39,11 +39,9 @@ module PubSubModelSync
|
|
39
39
|
# Permits to perform manually the callback for a specific action
|
40
40
|
# @param action (Symbol, default: :create) Only :create|:update|:destroy
|
41
41
|
def ps_perform_publish(action = :create, parents_actions: false)
|
42
|
-
parent_callbacks = parents_actions ? self.class.superclass.ps_cache_publish_callbacks : []
|
43
42
|
callbacks = self.class.ps_cache_publish_callbacks
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
callbacks = self.class.ancestors.map { |p| p.try(:ps_cache_publish_callbacks) }.compact.flatten if parents_actions
|
44
|
+
items = callbacks.select { |item| item[:actions].include?(action) }
|
47
45
|
items.each { |item| instance_exec(action, &item[:callback]) }
|
48
46
|
self
|
49
47
|
end
|
@@ -59,8 +59,8 @@ module PubSubModelSync
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def target_app_message?(payload)
|
62
|
-
key = payload.headers[:target_app_key]
|
63
|
-
key
|
62
|
+
key = payload.headers[:target_app_key].to_s
|
63
|
+
!key.present? || key.split(',').include?(config.subscription_key)
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -3,17 +3,18 @@
|
|
3
3
|
module PubSubModelSync
|
4
4
|
class Transaction < Base
|
5
5
|
PUBLISHER_KLASS = PubSubModelSync::MessagePublisher
|
6
|
-
attr_accessor :key, :payloads, :max_buffer, :root, :children, :finished
|
6
|
+
attr_accessor :key, :payloads, :max_buffer, :root, :children, :finished, :headers
|
7
7
|
|
8
8
|
# @param key (String,Nil) Transaction key, if empty will use the ordering_key from first payload
|
9
9
|
# @param max_buffer (Integer) Once this quantity of notifications is reached, then all notifications
|
10
10
|
# will immediately be delivered.
|
11
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
|
+
def initialize(key, max_buffer: config.transactions_max_buffer, headers: {})
|
13
13
|
@key = key
|
14
14
|
@max_buffer = max_buffer
|
15
15
|
@children = []
|
16
16
|
@payloads = []
|
17
|
+
@headers = headers
|
17
18
|
end
|
18
19
|
|
19
20
|
# @param payload (Payload)
|
data/pub_sub_model_sync.gemspec
CHANGED
@@ -4,7 +4,7 @@ lib = File.expand_path('lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require 'pub_sub_model_sync/version'
|
6
6
|
|
7
|
-
Gem::Specification.new do |spec|
|
7
|
+
Gem::Specification.new do |spec| # rubocop:disable Metrics/BlockLength
|
8
8
|
spec.required_ruby_version = '>= 2.4' # rubocop:disable Gemspec/RequiredRubyVersion
|
9
9
|
spec.name = 'pub_sub_model_sync'
|
10
10
|
spec.version = PubSubModelSync::VERSION
|
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.
|
4
|
+
version: 1.6.1pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|