pub_sub_model_sync 0.5.4 → 0.5.7.1

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: 57e8d23c9e514734a8a45664f641378bbb46e8de5315c536a0f692efcbe29dd2
4
- data.tar.gz: d0f290dac2b0563ffe5412f85e1a6a6e340e281049755b26dc732a3661501b92
3
+ metadata.gz: cd5c9fd9bd9c35d62c1eeea4fc91024a5c14f136a757c82bde849501e0445c9d
4
+ data.tar.gz: 20ea1422d130daa72863743cae0716ba01455e445ee96a9410ec050f0b7f5e52
5
5
  SHA512:
6
- metadata.gz: 351901f98e6c806e7a4efe20abdac65de5bf8f716dc57e1889302eab02d33b3f2f4d449cd0d351fd5ae882d16abe79a77791bea8ad956c52cda47829319eb858
7
- data.tar.gz: e906d601a8c37b999a8b6d550e605e9c04b67db692cec4b60220ae286bef9adde7132d8614cee4ca7dab9ef43538ae2baede3f07e402c4c21a189b79a9ba6873
6
+ metadata.gz: 4c1c1afba624ef824b269ab7e6aeb112b40bc932b9125ffb90b46b03f7aea96dfc3359fd3ba780b74f9145d37b7fc01be279c8dcf2ecbadce23ac4faad821441
7
+ data.tar.gz: c908efda5d92bcf8b262586feb22cadc884c24033a43318d22bdd16fb90036d139994fefc02a7b33335dd38f176cb93096e17aca4cd519d4ed8222d911848f69
@@ -1,5 +1,21 @@
1
1
  # Change Log
2
2
 
3
+ # 0.5.7.1 (January 26, 2021)
4
+ - fix: does not call :on_error_processing when processing a message
5
+
6
+ # 0.5.7 (January 13, 2021)
7
+ - feat: add method to preload sync listeners
8
+
9
+ # 0.5.6 (January 12, 2021)
10
+ - feat: add payload validation
11
+ - feat: add method to rebuild payload
12
+
13
+ # 0.5.5 (January 11, 2021)
14
+ - feat: google-pub/sub receive messages in the same order they were delivered
15
+
16
+ # 0.5.4.1 (January 8, 2021)
17
+ - fix: google-pub/sub receive messages sequentially and not in parallel (default 5 threads).
18
+
3
19
  # 0.5.4 (January 8, 2021)
4
20
  - fix: exclude identifiers when syncing model
5
21
  - feat: callbacks support for future extra params
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pub_sub_model_sync (0.5.4)
4
+ pub_sub_model_sync (0.5.7.1)
5
5
  rails
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -59,10 +59,10 @@ And then execute: $ bundle install
59
59
  rake pub_sub_model_sync:start
60
60
  ```
61
61
  Note: Publishers do not need todo this
62
- Note2 (Rails 6+): Due to Zeitwerk, you need to load listeners manually when syncing outside ```rake pub_sub_model_sync:start```
62
+ Note2 (Rails 6+): Due to Zeitwerk, you need to load listeners manually when syncing without mentioned task (like rails console)
63
63
  ```ruby
64
64
  # PubSubModelSync::Config.subscribers ==> []
65
- Rails.application.try(:eager_load!)
65
+ PubSubModelSync::Runner.preload_listeners
66
66
  # PubSubModelSync::Config.subscribers ==> [#<PubSubModelSync::Subscriber:0x000.. @klass="Article", @action=:create..., ....]
67
67
  ```
68
68
 
@@ -310,7 +310,37 @@ config.debug = true
310
310
  - Add alias attributes when subscribing (similar to publisher)
311
311
  - Add flag ```model.ps_processing``` to indicate that the current transaction is being processed by pub/sub
312
312
  - Auto publish update only if payload has changed
313
- - On delete, payload must only be composed by ids
313
+ - On delete, payload must only be composed by ids
314
+ - Change notifications into messages
315
+
316
+ ## Q&A
317
+ - Error "could not obtain a connection from the pool within 5.000 seconds"
318
+ This problem occurs because pub/sub dependencies (kafka, google-pubsub, rabbitmq) use many threads to perform notifications where the qty of threads is greater than qty of DB pools ([Google pubsub info](https://github.com/googleapis/google-cloud-ruby/blob/master/google-cloud-pubsub/lib/google/cloud/pubsub/subscription.rb#L888))
319
+ To fix the problem, edit config/database.yml and increase the quantity of ```pool: 10```
320
+ - Google pubsub: How to process notifications parallely and not sequentially (default 1 thread)?
321
+ ```ruby PubSubModelSync::ServiceGoogle::LISTEN_SETTINGS = { threads: { callback: qty_threads } } ```
322
+ Note: by this way some notifications can be processed before others thus missing relationship errors can appear
323
+ - How to retry failed syncs with sidekiq?
324
+ ```ruby
325
+ # lib/initializers/pub_sub_config.rb
326
+
327
+ class PubSubRecovery
328
+ include Sidekiq::Worker
329
+ sidekiq_options queue: :pubsub, retry: 2, backtrace: true
330
+
331
+ def perform(payload_data, action)
332
+ payload = PubSubModelSync::Payload.from_payload_data(payload_data)
333
+ payload.send(action)
334
+ end
335
+ end
336
+
337
+ PubSubModelSync::Config.on_error_publish = lambda do |_e, data|
338
+ PubSubRecovery.perform_async(data[:payload].to_h, :publish!)
339
+ end
340
+ PubSubModelSync::Config.on_error_processing = lambda do |_e, data|
341
+ PubSubRecovery.perform_async(data[:payload].to_h, :process!)
342
+ end
343
+ ```
314
344
 
315
345
  ## Contributing
316
346
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  module PubSubModelSync
4
4
  class Payload
5
+ class MissingInfo < StandardError; end
5
6
  attr_reader :data, :attributes, :headers
6
7
 
7
8
  # @param data (Hash: { any value }):
@@ -11,8 +12,10 @@ module PubSubModelSync
11
12
  @attributes = attributes
12
13
  @headers = headers
13
14
  build_headers
15
+ validate!
14
16
  end
15
17
 
18
+ # @return Hash: payload data
16
19
  def to_h
17
20
  { data: data, attributes: attributes, headers: headers }
18
21
  end
@@ -25,33 +28,52 @@ module PubSubModelSync
25
28
  attributes[:action]
26
29
  end
27
30
 
31
+ # Process payload data
32
+ # (If error will raise exception and wont call on_error_processing callback)
28
33
  def process!
29
34
  process do |publisher|
30
35
  publisher.raise_error = true
31
36
  end
32
37
  end
33
38
 
39
+ # Process payload data
40
+ # (If error will call on_error_processing callback)
34
41
  def process
35
42
  publisher = PubSubModelSync::MessageProcessor.new(self)
36
43
  yield(publisher) if block_given?
37
44
  publisher.process
38
45
  end
39
46
 
47
+ # Publish payload to pubsub
48
+ # (If error will raise exception and wont call on_error_publish callback)
40
49
  def publish!
41
50
  klass = PubSubModelSync::MessagePublisher
42
51
  klass.publish(self, raise_error: true)
43
52
  end
44
53
 
54
+ # Publish payload to pubsub
55
+ # (If error will call on_error_publish callback)
45
56
  def publish
46
57
  klass = PubSubModelSync::MessagePublisher
47
58
  klass.publish(self)
48
59
  end
49
60
 
61
+ # convert payload data into Payload
62
+ # @param data [Hash]: payload data (:data, :attributes, :headers)
63
+ def self.from_payload_data(data)
64
+ data = data.deep_symbolize_keys
65
+ new(data[:data], data[:attributes], data[:headers])
66
+ end
67
+
50
68
  private
51
69
 
52
70
  def build_headers
53
71
  headers[:uuid] ||= SecureRandom.uuid
54
72
  headers[:app_key] ||= PubSubModelSync::Config.subscription_key
55
73
  end
74
+
75
+ def validate!
76
+ raise MissingInfo if !attributes[:klass] || !attributes[:action]
77
+ end
56
78
  end
57
79
  end
@@ -4,6 +4,7 @@ require 'active_support/core_ext/module'
4
4
  module PubSubModelSync
5
5
  class Runner
6
6
  class ShutDown < StandardError; end
7
+ delegate :preload_listeners, to: :class
7
8
  attr_accessor :connector
8
9
 
9
10
  def initialize
@@ -12,12 +13,17 @@ module PubSubModelSync
12
13
 
13
14
  def run
14
15
  trap_signals!
15
- preload_framework!
16
+ preload_listeners
16
17
  start_listeners
17
18
  rescue ShutDown
18
19
  connector.stop
19
20
  end
20
21
 
22
+ def self.preload_listeners
23
+ Rails.application.try(:eager_load!) if defined?(Rails)
24
+ Zeitwerk::Loader.eager_load_all if defined?(Zeitwerk::Loader)
25
+ end
26
+
21
27
  private
22
28
 
23
29
  def start_listeners
@@ -31,10 +37,5 @@ module PubSubModelSync
31
37
  end
32
38
  %w[INT QUIT TERM].each { |signal| Signal.trap(signal, handler) }
33
39
  end
34
-
35
- def preload_framework!
36
- Rails.application.try(:eager_load!) if defined?(Rails)
37
- Zeitwerk::Loader.eager_load_all if defined?(Zeitwerk::Loader)
38
- end
39
40
  end
40
41
  end
@@ -29,7 +29,7 @@ module PubSubModelSync
29
29
  if same_app_message?(payload)
30
30
  log("Skip message from same origin: #{[payload]}") if config.debug
31
31
  else
32
- payload.process!
32
+ payload.process
33
33
  end
34
34
  rescue => e
35
35
  error = [payload, e.message, e.backtrace]
@@ -7,6 +7,8 @@ end
7
7
 
8
8
  module PubSubModelSync
9
9
  class ServiceGoogle < ServiceBase
10
+ LISTEN_SETTINGS = { threads: { callback: 1 } }.freeze
11
+ SUBSCRIPTION_SETTINGS = { message_ordering: true }.freeze
10
12
  attr_accessor :service, :topic, :subscription, :subscriber
11
13
 
12
14
  def initialize
@@ -40,7 +42,7 @@ module PubSubModelSync
40
42
 
41
43
  def subscribe_to_topic
42
44
  topic.subscription(config.subscription_key) ||
43
- topic.subscribe(config.subscription_key)
45
+ topic.subscribe(config.subscription_key, SUBSCRIPTION_SETTINGS)
44
46
  end
45
47
 
46
48
  def process_message(received_message)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PubSubModelSync
4
- VERSION = '0.5.4'
4
+ VERSION = '0.5.7.1'
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.4
4
+ version: 0.5.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Owen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-08 00:00:00.000000000 Z
11
+ date: 2021-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails