pub_sub_model_sync 1.0 → 1.0.1

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: caaffd468399e03dbf5582bf6973339ec61348a6dcc67a87bda1d930f9271aae
4
- data.tar.gz: 9db2cb5f4a70c218d720130761a24ad7f6450531d845f9517e74968f409c9743
3
+ metadata.gz: 6e73c2af5a62d4b0ae32ea40f3c3c369a049edfd47360a50386eeb5e4ff97cd1
4
+ data.tar.gz: 5d1892ee41ada21c9bf70bcc3601e435edfdf55d7b51b443369bf3307da60436
5
5
  SHA512:
6
- metadata.gz: ac6c2b0087e411969e4a0fbe6fa4aa57e3fe46b6ff93f4d675e2a213cd0fd75786b5e16e1a4c1df6aee92296eac0c94a054a6b62543a0f7f643ba2ea0bc8ff7b
7
- data.tar.gz: 9816c7cedd0d6289d0d73a55f35ede63a46bca7f38805c4c566012fed04a58595498a80fd272ce89b617e34b1d1487ff2ee7f6e050c9712bfd6d75b364ad910a
6
+ metadata.gz: 962defddfdc780ce185d01e9069485207bdf66be9b3554a1003b5ec71211c467223c288fbb6c6a59ae819a9ba37ff118a470942bdef9e69c68e94f34ff899c9a
7
+ data.tar.gz: c6e771a40a96dcdf00161aa49fbe7c1b5f283709d5b42b87421c6655e4cb9972e9f7d3bb7d203d47c9757dc681f8c755c7026447f6582ffa1f43a553ba90197a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Change Log
2
2
 
3
+ # 1.0.1 (August 20, 2021)
4
+ - refactor: improve service exit when running in k8s
5
+
3
6
  # 1.0 (June 13, 2021)
4
7
  This version includes many changes that was refactored from previous version, and thus it needs manual changes to migrate into this version.
5
8
  - Refactor: Subscribers param renamed `from_action` into `to_action` and added support for block or lambda
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pub_sub_model_sync (1.0)
4
+ pub_sub_model_sync (1.0.1)
5
5
  rails
6
6
 
7
7
  GEM
@@ -158,8 +158,6 @@ GEM
158
158
  nio4r (2.5.7)
159
159
  nokogiri (1.11.3-x86_64-darwin)
160
160
  racc (~> 1.4)
161
- nokogiri (1.11.3-x86_64-linux)
162
- racc (~> 1.4)
163
161
  os (1.1.1)
164
162
  parallel (1.20.1)
165
163
  parser (3.0.1.1)
data/README.md CHANGED
@@ -3,8 +3,8 @@
3
3
  ![Ruby badge](https://img.shields.io/badge/Ruby-2.4+-success.png)
4
4
  ![Production badge](https://img.shields.io/badge/Production-ready-success.png)
5
5
 
6
- This gem permits to sync automatically models and custom data between multiple Rails applications by publishing notifications via pubsub (Google PubSub, RabbitMQ, or Apache Kafka) and automatically processed by all connected applications. Out of the scope, this gem includes transactions to keep Data consistency by processing notifications in the order they were delivered.
7
- These notifications use JSON format to easily be decoded by subscribers (Rails applications and even other languages)
6
+ This gem permits to sync automatically models and custom data between multiple Rails applications by publishing notifications via pubsub (Google PubSub, RabbitMQ, or Apache Kafka) and automatically processed by all connected applications. Out of the scope, this gem includes transactions to keep Data consistency by processing notifications in the order they were delivered.
7
+ These notifications use JSON format to easily be decoded by subscribers (Rails applications and even other languages, soon for [Cristal-lang](https://crystal-lang.org/))
8
8
 
9
9
  - [**PubSubModelSync**](#pubsubmodelsync)
10
10
  - [**Features**](#features)
@@ -104,6 +104,7 @@ And then execute: $ bundle install
104
104
  ![Diagram](/docs/notifications-diagram.png?raw=true)
105
105
 
106
106
  ## **Examples**
107
+ See sample apps in [/samples](/samples/)
107
108
  ### **Basic Example**
108
109
  ```ruby
109
110
  # App 1 (Publisher)
@@ -561,6 +562,8 @@ config.debug = true
561
562
  - Last notification is not being delivered immediately in google pubsub (maybe force with timeout 10secs and service.deliver_messages)
562
563
  - Update folder structure
563
564
  - Services support to deliver multiple payloads from transactions
565
+ - Fix deprecation warnings: pub_sub_model_sync/service_google.rb:39: warning: Splitting the last argument into positional and keyword parameters is deprecated
566
+ - Add if/unless to ps_after_action
564
567
 
565
568
  ## **Q&A**
566
569
  - I'm getting error "could not obtain a connection from the pool within 5.000 seconds"... what does this mean?
@@ -54,9 +54,9 @@ module PubSubModelSync
54
54
  publish(payload)
55
55
  end
56
56
 
57
- # @param model (ActiveRecord::Base)
58
- # @param action (Symbol: @see PublishConcern::ps_publish)
59
- # @param settings (Hash: @see PayloadBuilder.settings)
57
+ # @param model (ActiveRecord::Base,PubSubModelSync::PublisherConcern)
58
+ # @param action (Symbol,String @see PublishConcern::ps_publish)
59
+ # @param settings (Hash @see PayloadBuilder.settings)
60
60
  def publish_model(model, action, settings = {})
61
61
  log("Building payload for: #{[model, action].inspect}") if config.debug
62
62
  payload = PubSubModelSync::PayloadBuilder.new(model, action, settings).call
@@ -80,7 +80,7 @@ module PubSubModelSync
80
80
  end
81
81
 
82
82
  def connector_publish(payload)
83
- log("Publishing message #{payload.inspect}...") if config.debug
83
+ log("Publishing message #{[payload]}...") if config.debug
84
84
  connector.publish(payload)
85
85
  log("Published message: #{[payload]}")
86
86
  config.on_after_publish.call(payload)
@@ -99,7 +99,7 @@ module PubSubModelSync
99
99
 
100
100
  def ensure_publish(payload)
101
101
  cancelled = config.on_before_publish.call(payload) == :cancel
102
- log("Publish cancelled by config.on_before_publish: #{payload}") if config.debug && cancelled
102
+ log("Publish cancelled by config.on_before_publish: #{[payload]}") if config.debug && cancelled
103
103
  !cancelled
104
104
  end
105
105
 
@@ -110,7 +110,7 @@ module PubSubModelSync
110
110
  def ensure_model_publish(model, action, payload)
111
111
  res_before = model.ps_before_publish(action, payload)
112
112
  cancelled = res_before == :cancel
113
- log("Publish cancelled by model.ps_before_publish: #{payload}") if config.debug && cancelled
113
+ log("Publish cancelled by model.ps_before_publish: #{[payload]}") if config.debug && cancelled
114
114
  !cancelled
115
115
  end
116
116
 
@@ -4,7 +4,7 @@ module PubSubModelSync
4
4
  class PayloadBuilder < PubSubModelSync::Base
5
5
  attr_accessor :model, :action, :data, :mapping, :headers, :as_klass
6
6
 
7
- # @param model (ActiveRecord::Base)
7
+ # @param model (ActiveRecord::Base,PubSubModelSync::PublisherConcern)
8
8
  # @param action (@see PublishConcern::ps_publish)
9
9
  # @param settings (@see PublishConcern::ps_publish): { data:, mapping:, headers:, as_klass: }
10
10
  def initialize(model, action, settings = {})
@@ -18,14 +18,14 @@ module PubSubModelSync
18
18
  alias ps_after_sync ps_after_publish # @deprecated
19
19
 
20
20
  # Delivers a notification via pubsub
21
- # @param action (Sym|String) Sample: create|update|save|destroy|<any_other_key>
21
+ # @param action (Symbol,String) Sample: create|update|save|destroy|<any_other_key>
22
22
  # @param mapping? (Array<String>) If present will generate data using the mapping and added to the payload.
23
23
  # Sample: ["id", "full_name:name"]
24
- # @param data? (Hash|Symbol|Proc)
24
+ # @param data? (Hash,Symbol,Proc)
25
25
  # Hash: Data to be added to the payload
26
26
  # Symbol: Method name to be called to retrieve payload data (must return a hash value, receives :action name)
27
27
  # Proc: Block to be called to retrieve payload data
28
- # @param headers? (Hash|Symbol|Proc): (All available attributes in Payload.headers)
28
+ # @param headers? (Hash,Symbol,Proc): (All available attributes in @Payload.headers)
29
29
  # Hash: Data that will be merged with default header values
30
30
  # Symbol: Method name that will be called to retrieve header values (must return a hash, receives :action name)
31
31
  # Proc: Block to be called to retrieve header values
@@ -57,7 +57,7 @@ module PubSubModelSync
57
57
  klass.publish_data((as_klass || name).to_s, data, action.to_sym, headers: headers)
58
58
  end
59
59
 
60
- # @param crud_actions (Symbol|Array<Symbol>): :create, :update, :destroy
60
+ # @param crud_actions (Symbol,Array<Symbol>): :create, :update, :destroy
61
61
  # @param method_name (Symbol, optional) method to be called
62
62
  def ps_after_action(crud_actions, method_name = nil, &block)
63
63
  actions = Array(crud_actions).map(&:to_sym)
@@ -3,7 +3,6 @@
3
3
  require 'active_support/core_ext/module'
4
4
  module PubSubModelSync
5
5
  class Runner
6
- class ShutDown < StandardError; end
7
6
  delegate :preload_listeners, to: :class
8
7
  attr_accessor :connector
9
8
 
@@ -12,11 +11,10 @@ module PubSubModelSync
12
11
  end
13
12
 
14
13
  def run
14
+ at_exit { connector.stop }
15
15
  trap_signals!
16
16
  preload_listeners
17
17
  start_listeners
18
- rescue ShutDown
19
- connector.stop
20
18
  end
21
19
 
22
20
  def self.preload_listeners
@@ -32,8 +30,8 @@ module PubSubModelSync
32
30
 
33
31
  def trap_signals!
34
32
  handler = proc do |signal|
35
- puts "received #{Signal.signame(signal)}"
36
- raise ShutDown
33
+ puts "PS_MSYNC ==> received #{Signal.signame(signal)}"
34
+ exit
37
35
  end
38
36
  %w[INT QUIT TERM].each { |signal| Signal.trap(signal, handler) }
39
37
  end
@@ -44,7 +44,7 @@ module PubSubModelSync
44
44
 
45
45
  def stop
46
46
  log('Listener stopping...')
47
- subscribers.each(&:stop!)
47
+ (subscribers || []).each(&:stop!)
48
48
  end
49
49
 
50
50
  private
@@ -76,8 +76,8 @@ module PubSubModelSync
76
76
  end
77
77
 
78
78
  # Check topic existence, create if missing topic
79
- # @param names (Array<String>|String)
80
- # @return (Array|String) return @param names
79
+ # @param names (Array<String>,String)
80
+ # @return (Array,String) return @param names
81
81
  def ensure_topics(names)
82
82
  missing_topics = Array(names) - (@known_topics || service.topics)
83
83
  missing_topics.each do |name|
@@ -9,16 +9,16 @@ module PubSubModelSync
9
9
  end
10
10
 
11
11
  module ClassMethods
12
- # @param actions (Symbol|Array<Symbol>) Notification.action name: save|create|update|destroy|<any_other_action>
12
+ # @param actions (Symbol,Array<Symbol>) Notification.action name: save|create|update|destroy|<any_other_action>
13
13
  # @param mapping (Array<String,Symbol>) Attributes mapping with aliasing support, sample: ["id", "full_name:name"]
14
14
  # @param settings (Hash<:from_klass, :to_action, :id, :if, :unless>)
15
15
  # from_klass (String) Notification.class name
16
- # to_action (Symbol|Proc):
16
+ # to_action (Symbol,Proc):
17
17
  # Symbol: Method to process the notification
18
18
  # Proc: Block to process the notification
19
- # id (Symbol|Array<Symbol|String>) attribute(s) DB primary identifier(s). Supports for mapping format.
20
- # if (Symbol|Proc|Array<Symbol>) Method or block called as the conformation before calling the callback
21
- # unless (Symbol|Proc|Array<Symbol>) Method or block called as the negation before calling the callback
19
+ # id (Symbol,Array<Symbol,String>) attribute(s) DB primary identifier(s). Supports for mapping format.
20
+ # if (Symbol,Proc,Array<Symbol>) Method or block called as the conformation before calling the callback
21
+ # unless (Symbol,Proc,Array<Symbol>) Method or block called as the negation before calling the callback
22
22
  def ps_subscribe(actions, mapping = [], settings = {}, &block)
23
23
  settings[:to_action] ||= block if block
24
24
  Array(actions).map do |action|
@@ -5,7 +5,7 @@ module PubSubModelSync
5
5
  PUBLISHER_KLASS = PubSubModelSync::MessagePublisher
6
6
  attr_accessor :key, :payloads, :max_buffer, :root, :children, :finished
7
7
 
8
- # @param key (String|nil) Transaction key, if empty will use the ordering_key from first payload
8
+ # @param key (String,Null) 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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PubSubModelSync
4
- VERSION = '1.0'
4
+ VERSION = '1.0.1'
5
5
  end
data/samples/README.md CHANGED
@@ -6,7 +6,7 @@ This is a sample to sync information between rails applications using RabbitMQ
6
6
  ```docker network create shared_app_services```
7
7
 
8
8
  * Start RabbitMQ server
9
- ```docker-compose up pubsub```
9
+ ```cd samples/app1 && docker-compose up pubsub```
10
10
 
11
11
  * In another tab access to App1 to publish notifications (Wait for step 2)
12
12
  - Access to the application
data/samples/app1/Gemfile CHANGED
@@ -18,7 +18,7 @@ gem 'bootsnap', '>= 1.4.4', require: false
18
18
  # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
19
19
  # gem 'rack-cors'
20
20
 
21
- gem 'pub_sub_model_sync'
21
+ gem 'pub_sub_model_sync', '>= 1.0'
22
22
  gem 'bunny' # to use rabbit-mq pub/sub service
23
23
  gem 'annotate'
24
24
 
@@ -96,7 +96,7 @@ GEM
96
96
  nokogiri (1.11.3)
97
97
  mini_portile2 (~> 2.5.0)
98
98
  racc (~> 1.4)
99
- pub_sub_model_sync (1.0.beta1)
99
+ pub_sub_model_sync (1.0)
100
100
  rails
101
101
  puma (5.3.1)
102
102
  nio4r (~> 2.0)
@@ -160,7 +160,7 @@ DEPENDENCIES
160
160
  bunny
161
161
  byebug
162
162
  listen (~> 3.3)
163
- pub_sub_model_sync (= 1.0.beta2)
163
+ pub_sub_model_sync (>= 1.0)
164
164
  puma (~> 5.0)
165
165
  rails (~> 6.1.3, >= 6.1.3.2)
166
166
  spring
@@ -168,4 +168,4 @@ DEPENDENCIES
168
168
  tzinfo-data
169
169
 
170
170
  BUNDLED WITH
171
- 2.1.4
171
+ 2.2.17
@@ -0,0 +1 @@
1
+ f76db08751757e296d844ca18dcdb0a1
data/samples/app2/Gemfile CHANGED
@@ -18,7 +18,7 @@ gem 'bootsnap', '>= 1.4.4', require: false
18
18
  # Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
19
19
  # gem 'rack-cors'
20
20
 
21
- gem 'pub_sub_model_sync'
21
+ gem 'pub_sub_model_sync', '>= 1.0'
22
22
  gem 'bunny' # to use rabbit-mq pub/sub service
23
23
  gem 'annotate'
24
24
 
@@ -96,7 +96,7 @@ GEM
96
96
  nokogiri (1.11.3)
97
97
  mini_portile2 (~> 2.5.0)
98
98
  racc (~> 1.4)
99
- pub_sub_model_sync (1.0.beta1)
99
+ pub_sub_model_sync (1.0)
100
100
  rails
101
101
  puma (5.3.1)
102
102
  nio4r (~> 2.0)
@@ -160,7 +160,7 @@ DEPENDENCIES
160
160
  bunny
161
161
  byebug
162
162
  listen (~> 3.3)
163
- pub_sub_model_sync (= 1.0.beta2)
163
+ pub_sub_model_sync (>= 1.0)
164
164
  puma (~> 5.0)
165
165
  rails (~> 6.1.3, >= 6.1.3.2)
166
166
  spring
@@ -168,4 +168,4 @@ DEPENDENCIES
168
168
  tzinfo-data
169
169
 
170
170
  BUNDLED WITH
171
- 2.1.4
171
+ 2.2.17
@@ -0,0 +1 @@
1
+ ca702da1b8c8f8405ed03739ca90b0e5
Binary file
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.0'
4
+ version: 1.0.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-06-13 00:00:00.000000000 Z
11
+ date: 2021-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -134,8 +134,6 @@ files:
134
134
  - lib/pub_sub_model_sync/version.rb
135
135
  - pub_sub_model_sync.gemspec
136
136
  - samples/README.md
137
- - samples/app1/.gitattributes
138
- - samples/app1/.gitignore
139
137
  - samples/app1/Dockerfile
140
138
  - samples/app1/Gemfile
141
139
  - samples/app1/Gemfile.lock
@@ -168,6 +166,7 @@ files:
168
166
  - samples/app1/config/initializers/pubsub.rb
169
167
  - samples/app1/config/initializers/wrap_parameters.rb
170
168
  - samples/app1/config/locales/en.yml
169
+ - samples/app1/config/master.key
171
170
  - samples/app1/config/puma.rb
172
171
  - samples/app1/config/routes.rb
173
172
  - samples/app1/config/spring.rb
@@ -177,8 +176,6 @@ files:
177
176
  - samples/app1/db/seeds.rb
178
177
  - samples/app1/docker-compose.yml
179
178
  - samples/app1/log/.keep
180
- - samples/app2/.gitattributes
181
- - samples/app2/.gitignore
182
179
  - samples/app2/Dockerfile
183
180
  - samples/app2/Gemfile
184
181
  - samples/app2/Gemfile.lock
@@ -211,9 +208,11 @@ files:
211
208
  - samples/app2/config/initializers/pubsub.rb
212
209
  - samples/app2/config/initializers/wrap_parameters.rb
213
210
  - samples/app2/config/locales/en.yml
211
+ - samples/app2/config/master.key
214
212
  - samples/app2/config/puma.rb
215
213
  - samples/app2/config/routes.rb
216
214
  - samples/app2/config/spring.rb
215
+ - samples/app2/db/development.sqlite3
217
216
  - samples/app2/db/migrate/20210513080956_create_customers.rb
218
217
  - samples/app2/db/migrate/20210513135203_create_posts.rb
219
218
  - samples/app2/db/schema.rb
@@ -1,8 +0,0 @@
1
- # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2
-
3
- # Mark the database schema as having been generated.
4
- db/schema.rb linguist-generated
5
-
6
-
7
- # Mark any vendored files as having been vendored.
8
- vendor/* linguist-vendored
@@ -1,28 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
- #
3
- # If you find yourself ignoring temporary files generated by your text editor
4
- # or operating system, you probably want to add a global ignore instead:
5
- # git config --global core.excludesfile '~/.gitignore_global'
6
-
7
- # Ignore bundler config.
8
- /.bundle
9
-
10
- # Ignore the default SQLite database.
11
- /db/*.sqlite3
12
- /db/*.sqlite3-*
13
-
14
- # Ignore all logfiles and tempfiles.
15
- /log/*
16
- /tmp/*
17
- !/log/.keep
18
- !/tmp/.keep
19
-
20
- # Ignore pidfiles, but keep the directory.
21
- /tmp/pids/*
22
- !/tmp/pids/
23
- !/tmp/pids/.keep
24
-
25
- .byebug_history
26
-
27
- # Ignore master key for decrypting credentials and more.
28
- /config/master.key
@@ -1,8 +0,0 @@
1
- # See https://git-scm.com/docs/gitattributes for more about git attribute files.
2
-
3
- # Mark the database schema as having been generated.
4
- db/schema.rb linguist-generated
5
-
6
-
7
- # Mark any vendored files as having been vendored.
8
- vendor/* linguist-vendored
@@ -1,28 +0,0 @@
1
- # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
- #
3
- # If you find yourself ignoring temporary files generated by your text editor
4
- # or operating system, you probably want to add a global ignore instead:
5
- # git config --global core.excludesfile '~/.gitignore_global'
6
-
7
- # Ignore bundler config.
8
- /.bundle
9
-
10
- # Ignore the default SQLite database.
11
- /db/*.sqlite3
12
- /db/*.sqlite3-*
13
-
14
- # Ignore all logfiles and tempfiles.
15
- /log/*
16
- /tmp/*
17
- !/log/.keep
18
- !/tmp/.keep
19
-
20
- # Ignore pidfiles, but keep the directory.
21
- /tmp/pids/*
22
- !/tmp/pids/
23
- !/tmp/pids/.keep
24
-
25
- .byebug_history
26
-
27
- # Ignore master key for decrypting credentials and more.
28
- /config/master.key