pub_sub_model_sync 0.5.3 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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