pub_sub_model_sync 0.5.3 → 0.5.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 608c6430e2e37529a6a219d09db34b7a540d89bed73da7e272c1624ad7ba821f
4
- data.tar.gz: 99eaf893d6c66d3e7429d6ba8758b7e44d9ca0a29069b72f260bccecd7a207f0
3
+ metadata.gz: 57e8d23c9e514734a8a45664f641378bbb46e8de5315c536a0f692efcbe29dd2
4
+ data.tar.gz: d0f290dac2b0563ffe5412f85e1a6a6e340e281049755b26dc732a3661501b92
5
5
  SHA512:
6
- metadata.gz: c9a0d769a2c18b9097d7f9d4b10f8f11567e743a39bcf10fe39ed4bd3daf156fb028685be4f8100d92d9bb0fd8ea742a1c0a5dca8fe0743c0c4e21b3b23fd552
7
- data.tar.gz: 4ff19cc02656fd8ddae04e061808c89ec61eae3e86cd889a3c2abc3fed0c2975ed8eed995363ad834d294f75ac340fdeb454c1de21e05e2f4080458664f8d181
6
+ metadata.gz: 351901f98e6c806e7a4efe20abdac65de5bf8f716dc57e1889302eab02d33b3f2f4d449cd0d351fd5ae882d16abe79a77791bea8ad956c52cda47829319eb858
7
+ data.tar.gz: e906d601a8c37b999a8b6d550e605e9c04b67db692cec4b60220ae286bef9adde7132d8614cee4ca7dab9ef43538ae2baede3f07e402c4c21a189b79a9ba6873
@@ -1,5 +1,12 @@
1
1
  # Change Log
2
2
 
3
+ # 0.5.4 (January 8, 2021)
4
+ - fix: exclude identifiers when syncing model
5
+ - feat: callbacks support for future extra params
6
+ - feat: make connectors configurable
7
+ - feat: add :process! and :process, :publish!, :publish methods to payload
8
+ - feat: auto retry 2 times when "could not obtain a database connection within 5.000 seconds..." error occurs
9
+
3
10
  # 0.5.3 (December 30, 2020)
4
11
  - fix: kafka consume all messages from different apps
5
12
  - style: use the correct consumer key
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pub_sub_model_sync (0.5.3)
4
+ pub_sub_model_sync (0.5.4)
5
5
  rails
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -206,10 +206,13 @@ Note: Be careful with collision of names
206
206
  * action_name: (required, :sim) Action name
207
207
  * as_klass: (optional, :string) Custom class name (Default current model name)
208
208
 
209
- - Publish a class level notification (Same as above: manual call)
209
+ - Payload actions
210
210
  ```ruby
211
211
  payload = PubSubModelSync::Payload.new({ title: 'hello' }, { action: :greeting, klass: 'User' })
212
- payload.publish!
212
+ payload.publish! # publishes notification data. It raises exception if fails and does not call ```:on_error_publishing``` callback
213
+ payload.publish # publishes notification data. On error does not raise exception but calls ```:on_error_publishing``` callback
214
+ payload.process! # process a notification data. It raises exception if fails and does not call ```.on_error_processing``` callback
215
+ payload.publish # process a notification data. It does not raise exception if fails but calls ```.on_error_processing``` callback
213
216
  ```
214
217
 
215
218
  - Get crud publisher configured for the class
@@ -290,18 +293,18 @@ config.debug = true
290
293
  (Logger) => define custom logger
291
294
  - ```.disabled_callback_publisher = ->(_model, _action) { false }```
292
295
  (true/false*) => if true, does not listen model callbacks for auto sync (Create/Update/Destroy)
293
- - ```.on_before_processing = ->(payload, subscriber) { puts payload }```
296
+ - ```.on_before_processing = ->(payload, {subscriber:}) { puts payload }```
294
297
  (Proc) => called before processing received message (:cancel can be returned to skip processing)
295
- - ```.on_success_processing = ->(payload, subscriber) { puts payload }```
298
+ - ```.on_success_processing = ->(payload, {subscriber:}) { puts payload }```
296
299
  (Proc) => called when a message was successfully processed
297
- - ```.on_error_processing = ->(exception, payload) { sleep 1; payload.process! }```
298
- (Proc) => called when a message failed when processing
300
+ - ```.on_error_processing = ->(exception, {payload:, subscriber:}) { payload.delay(...).process! }```
301
+ (Proc) => called when a message failed when processing (delayed_job or similar can be used for retrying)
299
302
  - ```.on_before_publish = ->(payload) { puts payload }```
300
303
  (Proc) => called before publishing a message (:cancel can be returned to skip publishing)
301
304
  - ```.on_after_publish = ->(payload) { puts payload }```
302
305
  (Proc) => called after publishing a message
303
- - ```.on_error_publish = ->(exception, payload) { sleep 1; payload.publish! }```
304
- (Proc) => called when failed publishing a message
306
+ - ```.on_error_publish = ->(exception, {payload:}) { payload.delay(...).publish! }```
307
+ (Proc) => called when failed publishing a message (delayed_job or similar can be used for retrying)
305
308
 
306
309
  ## TODO
307
310
  - Add alias attributes when subscribing (similar to publisher)
@@ -13,5 +13,12 @@ module PubSubModelSync
13
13
  config.log message, kind
14
14
  end
15
15
  end
16
+
17
+ def retry_error(error_klass, qty: 2, &block)
18
+ @retries ||= 0
19
+ block.call
20
+ rescue error_klass => _e
21
+ (@retries += 1) <= qty ? retry : raise
22
+ end
16
23
  end
17
24
  end
@@ -10,12 +10,12 @@ module PubSubModelSync
10
10
  cattr_accessor(:debug) { false }
11
11
  cattr_accessor :logger # LoggerInst
12
12
 
13
- cattr_accessor(:on_before_processing) { ->(_payload, _subscriber) {} } # return :cancel to skip
14
- cattr_accessor(:on_success_processing) { ->(_payload, _subscriber) {} }
15
- cattr_accessor(:on_error_processing) { ->(_exception, _payload) {} }
13
+ cattr_accessor(:on_before_processing) { ->(_payload, _info) {} } # return :cancel to skip
14
+ cattr_accessor(:on_success_processing) { ->(_payload, _info) {} }
15
+ cattr_accessor(:on_error_processing) { ->(_exception, _info) {} }
16
16
  cattr_accessor(:on_before_publish) { ->(_payload) {} } # return :cancel to skip
17
17
  cattr_accessor(:on_after_publish) { ->(_payload) {} }
18
- cattr_accessor(:on_error_publish) { ->(_exception, _payload) {} }
18
+ cattr_accessor(:on_error_publish) { ->(_exception, _info) {} }
19
19
  cattr_accessor(:disabled_callback_publisher) { ->(_model, _action) { false } }
20
20
 
21
21
  # google service
@@ -2,7 +2,7 @@
2
2
 
3
3
  module PubSubModelSync
4
4
  class MessageProcessor < PubSubModelSync::Base
5
- attr_accessor :payload
5
+ attr_accessor :payload, :raise_error
6
6
 
7
7
  # @param payload (Payload): payload to be delivered
8
8
  # @Deprecated: def initialize(data, klass, action)
@@ -24,23 +24,25 @@ module PubSubModelSync
24
24
  def run_subscriber(subscriber)
25
25
  return unless processable?(subscriber)
26
26
 
27
- subscriber.process!(payload)
28
- res = config.on_success_processing.call(payload, subscriber)
29
- log "processed message with: #{payload.inspect}" if res != :skip_log
27
+ retry_error(ActiveRecord::ConnectionTimeoutError, qty: 2) do
28
+ subscriber.process!(payload)
29
+ res = config.on_success_processing.call(payload, { subscriber: subscriber })
30
+ log "processed message with: #{payload.inspect}" if res != :skip_log
31
+ end
30
32
  rescue => e
31
- print_subscriber_error(e)
33
+ raise_error ? raise : print_subscriber_error(e, subscriber)
32
34
  end
33
35
 
34
36
  def processable?(subscriber)
35
- cancel = config.on_before_processing.call(payload, subscriber) == :cancel
37
+ cancel = config.on_before_processing.call(payload, { subscriber: subscriber }) == :cancel
36
38
  log("process message cancelled: #{payload}") if cancel && config.debug
37
39
  !cancel
38
40
  end
39
41
 
40
42
  # @param error (Error)
41
- def print_subscriber_error(error)
43
+ def print_subscriber_error(error, subscriber)
42
44
  info = [payload, error.message, error.backtrace]
43
- res = config.on_error_processing.call(error, payload)
45
+ res = config.on_error_processing.call(error, { payload: payload, subscriber: subscriber })
44
46
  log("Error processing message: #{info}", :error) if res != :skip_log
45
47
  end
46
48
 
@@ -27,7 +27,7 @@ module PubSubModelSync
27
27
  model.ps_after_sync(action, payload.data)
28
28
  end
29
29
 
30
- def publish(payload)
30
+ def publish(payload, raise_error: false)
31
31
  if config.on_before_publish.call(payload) == :cancel
32
32
  log("Publish message cancelled: #{payload}") if config.debug
33
33
  return
@@ -37,14 +37,14 @@ module PubSubModelSync
37
37
  connector.publish(payload)
38
38
  config.on_after_publish.call(payload)
39
39
  rescue => e
40
- notify_error(e, payload)
40
+ raise_error ? raise : notify_error(e, payload)
41
41
  end
42
42
 
43
43
  private
44
44
 
45
45
  def notify_error(exception, payload)
46
46
  info = [payload, exception.message, exception.backtrace]
47
- res = config.on_error_publish.call(exception, payload)
47
+ res = config.on_error_publish.call(exception, { payload: payload })
48
48
  log("Error publishing: #{info}", :error) if res != :skip_log
49
49
  end
50
50
  end
@@ -26,11 +26,23 @@ module PubSubModelSync
26
26
  end
27
27
 
28
28
  def process!
29
+ process do |publisher|
30
+ publisher.raise_error = true
31
+ end
32
+ end
33
+
34
+ def process
29
35
  publisher = PubSubModelSync::MessageProcessor.new(self)
36
+ yield(publisher) if block_given?
30
37
  publisher.process
31
38
  end
32
39
 
33
40
  def publish!
41
+ klass = PubSubModelSync::MessagePublisher
42
+ klass.publish(self, raise_error: true)
43
+ end
44
+
45
+ def publish
34
46
  klass = PubSubModelSync::MessagePublisher
35
47
  klass.publish(self)
36
48
  end
@@ -4,6 +4,8 @@ require 'pub_sub_model_sync/payload'
4
4
  module PubSubModelSync
5
5
  class ServiceBase < PubSubModelSync::Base
6
6
  SERVICE_KEY = 'service_model_sync'
7
+ PUBLISH_SETTINGS = {}.freeze
8
+ LISTEN_SETTINGS = {}.freeze
7
9
 
8
10
  def listen_messages
9
11
  raise 'method :listen_messages must be defined in service'
@@ -18,7 +18,7 @@ module PubSubModelSync
18
18
 
19
19
  def listen_messages
20
20
  @subscription = subscribe_to_topic
21
- @subscriber = subscription.listen(&method(:process_message))
21
+ @subscriber = subscription.listen(LISTEN_SETTINGS, &method(:process_message))
22
22
  log('Listener starting...')
23
23
  subscriber.start
24
24
  log('Listener started')
@@ -28,7 +28,7 @@ module PubSubModelSync
28
28
  end
29
29
 
30
30
  def publish(payload)
31
- topic.publish(payload.to_json, { SERVICE_KEY => true })
31
+ topic.publish(payload.to_json, { SERVICE_KEY => true }.merge(PUBLISH_SETTINGS))
32
32
  end
33
33
 
34
34
  def stop
@@ -20,7 +20,7 @@ module PubSubModelSync
20
20
  def listen_messages
21
21
  log('Listener starting...')
22
22
  start_consumer
23
- consumer.each_message(&method(:process_message))
23
+ consumer.each_message(LISTEN_SETTINGS, &method(:process_message))
24
24
  rescue PubSubModelSync::Runner::ShutDown
25
25
  log('Listener stopped')
26
26
  rescue => e
@@ -28,7 +28,11 @@ module PubSubModelSync
28
28
  end
29
29
 
30
30
  def publish(payload)
31
- producer.produce(payload.to_json, message_settings)
31
+ settings = {
32
+ topic: config.topic_name,
33
+ headers: { SERVICE_KEY => true }
34
+ }.merge(PUBLISH_SETTINGS)
35
+ producer.produce(payload.to_json, settings)
32
36
  producer.deliver_messages
33
37
  end
34
38
 
@@ -39,10 +43,6 @@ module PubSubModelSync
39
43
 
40
44
  private
41
45
 
42
- def message_settings
43
- { topic: config.topic_name, headers: { SERVICE_KEY => true } }
44
- end
45
-
46
46
  def start_consumer
47
47
  @consumer = service.consumer(group_id: config.subscription_key)
48
48
  consumer.subscribe(config.topic_name)
@@ -51,7 +51,7 @@ module PubSubModelSync
51
51
  routing_key: queue.name,
52
52
  type: SERVICE_KEY,
53
53
  persistent: true
54
- }
54
+ }.merge(PUBLISH_SETTINGS)
55
55
  end
56
56
 
57
57
  def queue_settings
@@ -59,7 +59,7 @@ module PubSubModelSync
59
59
  end
60
60
 
61
61
  def subscribe_settings
62
- { manual_ack: false }
62
+ { manual_ack: false }.merge(LISTEN_SETTINGS)
63
63
  end
64
64
 
65
65
  def process_message(_delivery_info, meta_info, payload)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module PubSubModelSync
4
4
  class Subscriber
5
- attr_accessor :klass, :action, :attrs, :settings
5
+ attr_accessor :klass, :action, :attrs, :settings, :identifiers
6
6
  attr_reader :payload
7
7
 
8
8
  # @param settings: (Hash) { id: :id, direct_mode: false,
@@ -14,6 +14,7 @@ module PubSubModelSync
14
14
  @action = action
15
15
  @attrs = attrs
16
16
  @settings = def_settings.merge(settings)
17
+ @identifiers = Array(settings[:id]).map(&:to_sym)
17
18
  end
18
19
 
19
20
  def process!(payload)
@@ -55,12 +56,11 @@ module PubSubModelSync
55
56
  end
56
57
 
57
58
  def model_identifiers
58
- identifiers = Array(settings[:id])
59
59
  identifiers.map { |key| [key, payload.data[key.to_sym]] }.to_h
60
60
  end
61
61
 
62
62
  def populate_model(model)
63
- values = payload.data.slice(*attrs)
63
+ values = payload.data.slice(*attrs).except(*identifiers)
64
64
  values.each do |attr, value|
65
65
  model.send("#{attr}=", value)
66
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PubSubModelSync
4
- VERSION = '0.5.3'
4
+ VERSION = '0.5.4'
5
5
  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: 0.5.3
4
+ version: 0.5.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Owen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-12-31 00:00:00.000000000 Z
11
+ date: 2021-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails