pub_sub_model_sync 1.3.1 → 1.4.0
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/CHANGELOG.md +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +7 -2
- data/lib/pub_sub_model_sync/config.rb +1 -0
- data/lib/pub_sub_model_sync/message_publisher.rb +5 -2
- data/lib/pub_sub_model_sync/payload.rb +19 -1
- data/lib/pub_sub_model_sync/payload_cache_optimizer.rb +50 -0
- data/lib/pub_sub_model_sync/service_base.rb +1 -1
- data/lib/pub_sub_model_sync/version.rb +1 -1
- data/lib/pub_sub_model_sync.rb +1 -0
- 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: 1740843df35081aaeb35e2be5c1c27cf1ff4d219af0bcf9ae4394495ab8bba5e
|
4
|
+
data.tar.gz: ed506905c6b29b554f4a1cd100ddf4c8df2bf0a99590eb26901fae8feef862ce
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bff308ce421ae321d2a9e7b53df194d3678e5f6103eb4f2048d4ed064302c042fb7768f96a3c639190b8d452a0636fded9e72394a5ffe4731b4e24ba0b2f5b53
|
7
|
+
data.tar.gz: e60c4c78c5fbde7c40d68adb1ed029d74bb10d1759a27682850aae6015c84f938cbccccaadc976878afa26d97621d360937cdeb5cc028b2393facb12fa0d4831
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -313,10 +313,15 @@ Any notification before delivering is transformed as a Payload for a better port
|
|
313
313
|
* `headers`: (Hash) Notification settings that defines how the notification will be processed or delivered.
|
314
314
|
- `ordering_key`: (String, optional): notifications with the same `ordering_key` are processed in the same order they were delivered, default: `<model.class.name>/<model.id>` when instance notification and `klass_name` when class notification.
|
315
315
|
Note: Final `ordering_key` is calculated as: `payload.headers[:forced_ordering_key] || current_transaction&.key || payload.headers[:ordering_key]`
|
316
|
-
- `internal_key`: (String, optional) Internal identifier of the payload, default: `<model.class.name>/<action>/<model.id>` when model notification and `<klass_name>/<action>` when class notification (Useful for caching techniques).
|
317
316
|
- `topic_name`: (String|Array<String>, optional): Specific topic name where to deliver the notification (default `PubSubModelSync::Config.topic_name`).
|
318
317
|
- `forced_ordering_key`: (String, optional): Overrides `ordering_key` with the provided value even withing transactions. Default `nil`.
|
319
|
-
- `
|
318
|
+
- `cache` (Boolean | Hash, Default false) Cache settings
|
319
|
+
- `true`: Skip publishing similar payloads
|
320
|
+
- `Hash<required: Array<Symbol>>`: Same as `true` and enables payload optimization to exclude unchanged non important attributes. Sample: `{ required: %i[id email] }`
|
321
|
+
|
322
|
+
** Read ONLY **
|
323
|
+
- `internal_key`: Internal identifier of the payload, default: `<model.class.name>/<action>/<model.id>` when model notification and `<klass_name>/<action>` when class notification (Useful for caching techniques).
|
324
|
+
- `app_key`: (Auto calculated): Name of the application who delivered the notification.
|
320
325
|
- `uuid`: (Auto calculated): Unique notification identifier (Very useful when debugging).
|
321
326
|
Note: To reduce Payload size, some header info are not delivered (Enable debug mode to deliver all payload info).
|
322
327
|
|
@@ -9,6 +9,7 @@ module PubSubModelSync
|
|
9
9
|
cattr_accessor(:debug) { false }
|
10
10
|
cattr_accessor :logger # LoggerInst
|
11
11
|
cattr_accessor(:transactions_max_buffer) { 1 }
|
12
|
+
cattr_accessor(:skip_cache) { false }
|
12
13
|
|
13
14
|
cattr_accessor(:on_before_processing) { ->(_payload, _info) {} } # return :cancel to skip
|
14
15
|
cattr_accessor(:on_success_processing) { ->(_payload, _info) {} }
|
@@ -98,8 +98,11 @@ module PubSubModelSync
|
|
98
98
|
private
|
99
99
|
|
100
100
|
def ensure_publish(payload)
|
101
|
-
|
102
|
-
|
101
|
+
cache_klass = PubSubModelSync::PayloadCacheOptimizer
|
102
|
+
cancelled = payload.cache_settings ? cache_klass.new(payload).call == :already_sent : false
|
103
|
+
cancelled ||= config.on_before_publish.call(payload) == :cancel
|
104
|
+
log_msg = "Publish cancelled by config.on_before_publish or cache checker: #{[payload]}"
|
105
|
+
log(log_msg) if config.debug && cancelled
|
103
106
|
!cancelled
|
104
107
|
end
|
105
108
|
|
@@ -19,9 +19,17 @@ module PubSubModelSync
|
|
19
19
|
# <klass>: when class message
|
20
20
|
# <klass/id>: when model message
|
21
21
|
# topic_name (String|Array<String>): Specific topic name to be used when delivering the
|
22
|
-
# message (default
|
22
|
+
# message (default Config.topic_name)
|
23
23
|
# forced_ordering_key (String, optional): Will force to use this value as the ordering_key,
|
24
24
|
# even withing transactions. Default nil.
|
25
|
+
# cache (Boolean | Hash, Default false) Cache settings
|
26
|
+
# true: Skip publishing similar payloads
|
27
|
+
# Hash<required: Array<Symbol>>: Same as true and enables payload optimization to exclude
|
28
|
+
# unchanged non important attributes. Sample: { required: %i[id email] }
|
29
|
+
# --- READ ONLY ----
|
30
|
+
# app_key: (string) Subscriber-Key of the application who delivered the notification
|
31
|
+
# internal_key: (String) "<klass>/<action>"
|
32
|
+
# uuid: Unique notification identifier
|
25
33
|
def initialize(data, info, headers = {})
|
26
34
|
@data = data.deep_symbolize_keys
|
27
35
|
@info = info.deep_symbolize_keys
|
@@ -75,6 +83,16 @@ module PubSubModelSync
|
|
75
83
|
klass.publish(self)
|
76
84
|
end
|
77
85
|
|
86
|
+
# @param attr_keys (Array<Symbol>) List of attributes to be excluded from payload
|
87
|
+
def exclude_data_attrs(attr_keys)
|
88
|
+
@data = data.except(*attr_keys)
|
89
|
+
end
|
90
|
+
|
91
|
+
# Attributes to always be delivered after cache optimization
|
92
|
+
def cache_settings
|
93
|
+
headers[:cache]
|
94
|
+
end
|
95
|
+
|
78
96
|
# convert payload data into Payload
|
79
97
|
# @param data [Hash]: payload data (:data, :info, :headers)
|
80
98
|
def self.from_payload_data(data)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PubSubModelSync
|
4
|
+
class PayloadCacheOptimizer < PubSubModelSync::Base
|
5
|
+
# Optimizes payload data to deliver only the required ones and the changed ones and thus avoid
|
6
|
+
# delivering unnecessary notifications.
|
7
|
+
# Uses Rails.cache to retrieve previous delivered data.
|
8
|
+
attr_reader :payload, :required_attrs, :cache_key
|
9
|
+
|
10
|
+
# @param payload (Payload)
|
11
|
+
def initialize(payload)
|
12
|
+
@payload = payload
|
13
|
+
@cache_key = "pubsub/#{payload.headers[:internal_key]}/#{payload.headers[:topic_name]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return (:already_sent|Payload)
|
17
|
+
def call
|
18
|
+
backup_data = payload.data.clone
|
19
|
+
return payload if cache_disabled?
|
20
|
+
return :already_sent if previous_payload_data == payload.data
|
21
|
+
|
22
|
+
optimize_payload if optimization_enabled?
|
23
|
+
Rails.cache.write(cache_key, backup_data, expires_in: 1.week)
|
24
|
+
payload
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def optimization_enabled?
|
30
|
+
previous_payload_data && payload.cache_settings.is_a?(Hash)
|
31
|
+
end
|
32
|
+
|
33
|
+
def cache_disabled?
|
34
|
+
res = config.skip_cache || Rails.cache.nil?
|
35
|
+
log("Skipping cache, it was disabled: #{[payload]}") if res && debug?
|
36
|
+
res
|
37
|
+
end
|
38
|
+
|
39
|
+
def previous_payload_data
|
40
|
+
@previous_payload_data ||= Rails.cache.read(cache_key)
|
41
|
+
end
|
42
|
+
|
43
|
+
def optimize_payload # rubocop:disable Metrics/AbcSize
|
44
|
+
changed_keys = Hash[(payload.data.to_a - previous_payload_data.to_a)].keys
|
45
|
+
invalid_keys = payload.data.keys - (changed_keys + payload.cache_settings[:required])
|
46
|
+
log("Excluding non changed attributes: #{invalid_keys} from: #{payload.inspect}") if debug?
|
47
|
+
payload.exclude_data_attrs(invalid_keys)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -24,7 +24,7 @@ module PubSubModelSync
|
|
24
24
|
# @return (String): Json Format
|
25
25
|
def encode_payload(payload)
|
26
26
|
data = payload.to_h
|
27
|
-
not_important_keys = %i[forced_ordering_key]
|
27
|
+
not_important_keys = %i[forced_ordering_key cache]
|
28
28
|
reduce_payload_size = !config.debug
|
29
29
|
data[:headers].except!(*not_important_keys) if reduce_payload_size
|
30
30
|
data.to_json
|
data/lib/pub_sub_model_sync.rb
CHANGED
@@ -16,6 +16,7 @@ require 'pub_sub_model_sync/message_processor'
|
|
16
16
|
require 'pub_sub_model_sync/run_subscriber'
|
17
17
|
|
18
18
|
require 'pub_sub_model_sync/payload_builder'
|
19
|
+
require 'pub_sub_model_sync/payload_cache_optimizer'
|
19
20
|
require 'pub_sub_model_sync/subscriber'
|
20
21
|
|
21
22
|
require 'pub_sub_model_sync/service_base'
|
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.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02
|
11
|
+
date: 2022-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- lib/pub_sub_model_sync/mock_rabbit_service.rb
|
120
120
|
- lib/pub_sub_model_sync/payload.rb
|
121
121
|
- lib/pub_sub_model_sync/payload_builder.rb
|
122
|
+
- lib/pub_sub_model_sync/payload_cache_optimizer.rb
|
122
123
|
- lib/pub_sub_model_sync/publisher_concern.rb
|
123
124
|
- lib/pub_sub_model_sync/railtie.rb
|
124
125
|
- lib/pub_sub_model_sync/run_subscriber.rb
|