pub_sub_model_sync 0.3.0 → 0.4.2.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 +4 -4
- data/.github/workflows/ruby.yml +24 -7
- data/.rubocop.yml +3 -1
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +8 -9
- data/README.md +35 -28
- data/gemfiles/Gemfile_4 +16 -0
- data/gemfiles/Gemfile_5 +14 -0
- data/gemfiles/Gemfile_6 +14 -0
- data/lib/pub_sub_model_sync.rb +4 -1
- data/lib/pub_sub_model_sync/config.rb +1 -1
- data/lib/pub_sub_model_sync/message_processor.rb +15 -67
- data/lib/pub_sub_model_sync/message_publisher.rb +33 -0
- data/lib/pub_sub_model_sync/publisher.rb +13 -36
- data/lib/pub_sub_model_sync/publisher_concern.rb +21 -20
- data/lib/pub_sub_model_sync/service_base.rb +1 -1
- data/lib/pub_sub_model_sync/service_google.rb +4 -2
- data/lib/pub_sub_model_sync/service_kafka.rb +2 -2
- data/lib/pub_sub_model_sync/service_rabbit.rb +8 -3
- data/lib/pub_sub_model_sync/subscriber.rb +67 -0
- data/lib/pub_sub_model_sync/subscriber_concern.rb +21 -18
- data/lib/pub_sub_model_sync/version.rb +1 -1
- data/pub_sub_model_sync.gemspec +1 -1
- metadata +11 -29
- data/.idea/.gitignore +0 -8
- data/.idea/.rakeTasks +0 -7
- data/.idea/codeStyles/codeStyleConfig.xml +0 -5
- data/.idea/encodings.xml +0 -4
- data/.idea/inspectionProfiles/Project_Default.xml +0 -16
- data/.idea/misc.xml +0 -7
- data/.idea/modules.xml +0 -8
- data/.idea/pub_sub_model_sync.iml +0 -96
- data/.idea/vcs.xml +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30ddd2acf4ff439f66a35b747794b606dbe7949c31fe3f9bf064e87e718c8e48
|
4
|
+
data.tar.gz: 95724a2190dd0cdb8d9a4ef4e841c90462cd53794dbf5cde7c04e2699171f55a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 417260220e8c7c89a0fd37a23814d4b5436f29218bd212541b11e9ec1f815cb283fc8f1a1d579dd23ee5ada60c8138cc6a53515ddea2a0ec7dd75c5ee59c2be3
|
7
|
+
data.tar.gz: ded28709d868ec234553ac1d47927d48423f909126fc1a4b119d5cb98801181927883ae1b0b7e01c979b0225bafbd6685f2f7b9d843722da673e3d63760b8057
|
data/.github/workflows/ruby.yml
CHANGED
@@ -6,28 +6,45 @@ on:
|
|
6
6
|
- master
|
7
7
|
pull_request:
|
8
8
|
|
9
|
-
|
10
9
|
jobs:
|
11
10
|
build:
|
12
11
|
name: Tests and Code Style
|
13
12
|
runs-on: ubuntu-latest
|
13
|
+
strategy:
|
14
|
+
matrix:
|
15
|
+
ruby: [2.4, 2.5, 2.6]
|
16
|
+
rails: [4, 5, 6]
|
17
|
+
include:
|
18
|
+
- ruby: 2.7
|
19
|
+
rails: 6
|
20
|
+
exclude: # rails 6 requires ruby >= 2.5
|
21
|
+
- ruby: 2.4
|
22
|
+
rails: 6
|
14
23
|
|
15
24
|
steps:
|
16
25
|
- uses: actions/checkout@v2
|
17
|
-
- name: Set up Ruby
|
26
|
+
- name: Set up Ruby
|
18
27
|
uses: actions/setup-ruby@v1
|
19
28
|
with:
|
20
|
-
ruby-version:
|
21
|
-
|
29
|
+
ruby-version: ${{ matrix.ruby }}
|
22
30
|
- name: Install sqlite3
|
23
31
|
run: sudo apt-get install libsqlite3-dev
|
24
32
|
|
25
|
-
- name:
|
33
|
+
- name: Install bundler
|
34
|
+
env:
|
35
|
+
GEMFILE_PATH: gemfiles/Gemfile_${{ matrix.rails }}
|
36
|
+
RAILS_V: ${{ matrix.rails }}
|
26
37
|
run: |
|
27
|
-
|
28
|
-
|
38
|
+
rm -f Gemfile.lock && rm -f Gemfile
|
39
|
+
cp $GEMFILE_PATH ./Gemfile
|
40
|
+
bundler_v='2.1.4'
|
41
|
+
if [ $RAILS_V = "4" ]; then bundler_v="1.16.6"; fi
|
42
|
+
gem install bundler -v "~> $bundler_v"
|
43
|
+
bundle _${bundler_v}_ install --jobs 4 --retry 3
|
44
|
+
|
29
45
|
- name: Tests (rspec)
|
30
46
|
run: |
|
31
47
|
bundle exec rspec
|
48
|
+
|
32
49
|
- name: Code style (Rubocop)
|
33
50
|
run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
# This is the configuration used to check the rubocop source code.
|
2
2
|
|
3
3
|
AllCops:
|
4
|
+
TargetRubyVersion: 2.4
|
4
5
|
Exclude:
|
5
6
|
- 'spec/spec_helper.rb'
|
6
7
|
- 'Gemfile'
|
7
8
|
- 'Rakefile'
|
8
9
|
- 'bin/*'
|
9
|
-
TargetRubyVersion: 2.3
|
10
10
|
|
11
11
|
Metrics/BlockLength:
|
12
12
|
Exclude:
|
13
13
|
- 'spec/**/*.rb'
|
14
14
|
|
15
|
+
Layout/LineLength:
|
16
|
+
Max: 80
|
15
17
|
|
16
18
|
Style/SymbolArray:
|
17
19
|
Exclude:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,28 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
# 0.4.2.1 (August 20, 2020)
|
4
|
+
- Improve ```ps_subscriber_changed?``` to run validations and check for changes
|
5
|
+
|
6
|
+
# 0.4.2 (May 12, 2020)
|
7
|
+
- chore: remove typo
|
8
|
+
|
9
|
+
# 0.4.1 (May 12, 2020)
|
10
|
+
- chore: improve log messages
|
11
|
+
- feat: do not update model if no changes
|
12
|
+
- feat: skip publisher after updating if no changes
|
13
|
+
|
14
|
+
|
15
|
+
# 0.4.0 (May 06, 2020)
|
16
|
+
- rename as_klass to from_klass and as_action to from_action for subscribers
|
17
|
+
- refactor subscribers to be independent
|
18
|
+
- refactor message_publisher to use publisher
|
19
|
+
- rename publisher into message_publisher
|
20
|
+
- reformat publisher to reuse connector
|
21
|
+
|
22
|
+
# 0.3.1 (May 05, 2020)
|
23
|
+
- improve rabbit service to use sleep instead of block ("Block is not recommended for production")
|
24
|
+
- improve message ID
|
25
|
+
|
3
26
|
# 0.3.0 (April 29, 2020)
|
4
27
|
- Support for multiple identifiers when syncing
|
5
28
|
- Add klass.ps_find_model method for a custom model finder
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pub_sub_model_sync (0.
|
5
|
-
activesupport
|
4
|
+
pub_sub_model_sync (0.4.2.1)
|
6
5
|
rails
|
7
6
|
|
8
7
|
GEM
|
@@ -123,7 +122,7 @@ GEM
|
|
123
122
|
concurrent-ruby (~> 1.0)
|
124
123
|
jaro_winkler (1.5.4)
|
125
124
|
jwt (2.2.1)
|
126
|
-
loofah (2.
|
125
|
+
loofah (2.6.0)
|
127
126
|
crass (~> 1.0.2)
|
128
127
|
nokogiri (>= 1.5.9)
|
129
128
|
mail (2.7.1)
|
@@ -132,21 +131,21 @@ GEM
|
|
132
131
|
mimemagic (~> 0.3.2)
|
133
132
|
memoist (0.16.2)
|
134
133
|
method_source (1.0.0)
|
135
|
-
mimemagic (0.3.
|
134
|
+
mimemagic (0.3.5)
|
136
135
|
mini_mime (1.0.2)
|
137
136
|
mini_portile2 (2.4.0)
|
138
137
|
minitest (5.14.0)
|
139
138
|
multi_json (1.14.1)
|
140
139
|
multipart-post (2.1.1)
|
141
140
|
nio4r (2.5.2)
|
142
|
-
nokogiri (1.10.
|
141
|
+
nokogiri (1.10.10)
|
143
142
|
mini_portile2 (~> 2.4.0)
|
144
143
|
os (1.0.1)
|
145
144
|
parallel (1.19.1)
|
146
145
|
parser (2.7.0.4)
|
147
146
|
ast (~> 2.4.0)
|
148
147
|
public_suffix (4.0.3)
|
149
|
-
rack (2.2.
|
148
|
+
rack (2.2.3)
|
150
149
|
rack-test (1.1.0)
|
151
150
|
rack (>= 1.0, < 3)
|
152
151
|
rails (6.0.2.2)
|
@@ -208,7 +207,7 @@ GEM
|
|
208
207
|
faraday (~> 0.9)
|
209
208
|
jwt (>= 1.5, < 3.0)
|
210
209
|
multi_json (~> 1.10)
|
211
|
-
sprockets (4.0.
|
210
|
+
sprockets (4.0.2)
|
212
211
|
concurrent-ruby (~> 1.0)
|
213
212
|
rack (> 1, < 3)
|
214
213
|
sprockets-rails (3.2.1)
|
@@ -221,9 +220,9 @@ GEM
|
|
221
220
|
tzinfo (1.2.7)
|
222
221
|
thread_safe (~> 0.1)
|
223
222
|
unicode-display_width (1.6.1)
|
224
|
-
websocket-driver (0.7.
|
223
|
+
websocket-driver (0.7.3)
|
225
224
|
websocket-extensions (>= 0.1.0)
|
226
|
-
websocket-extensions (0.1.
|
225
|
+
websocket-extensions (0.1.5)
|
227
226
|
zeitwerk (2.3.0)
|
228
227
|
|
229
228
|
PLATFORMS
|
data/README.md
CHANGED
@@ -61,6 +61,9 @@ And then execute: $ bundle install
|
|
61
61
|
```
|
62
62
|
Note: Publishers do not need todo this
|
63
63
|
|
64
|
+
- Check the service status with:
|
65
|
+
```PubSubModelSync::MessagePublisher.publish_data('Test message', {sample_value: 10}, :create)```
|
66
|
+
|
64
67
|
## Examples
|
65
68
|
```ruby
|
66
69
|
# App 1 (Publisher)
|
@@ -86,7 +89,7 @@ User.create(name: 'test user', email: 'sample@gmail.com') # Review your App 2 to
|
|
86
89
|
User.new(name: 'test user').ps_perform_sync(:create) # similar to above to perform sync on demand
|
87
90
|
|
88
91
|
User.ps_class_publish({ msg: 'Hello' }, action: :greeting) # User.greeting method (Class method) will be called in App2
|
89
|
-
PubSubModelSync::
|
92
|
+
PubSubModelSync::MessagePublisher.publish_data(User, { msg: 'Hello' }, :greeting) # similar to above when not included publisher concern
|
90
93
|
```
|
91
94
|
|
92
95
|
## Advanced Example
|
@@ -110,15 +113,15 @@ end
|
|
110
113
|
class User < ActiveRecord::Base
|
111
114
|
self.table_name = 'subscriber_users'
|
112
115
|
include PubSubModelSync::SubscriberConcern
|
113
|
-
ps_subscribe(%i[name], actions: %i[update],
|
114
|
-
ps_class_subscribe(:greeting,
|
116
|
+
ps_subscribe(%i[name], actions: %i[update], from_klass: 'Client', id: %i[client_id email])
|
117
|
+
ps_class_subscribe(:greeting, from_action: :custom_greeting, from_klass: 'CustomUser')
|
115
118
|
alias_attribute :full_name, :name
|
116
119
|
|
117
120
|
def self.greeting(data)
|
118
121
|
puts 'Class message called through custom_greeting'
|
119
122
|
end
|
120
123
|
|
121
|
-
# def self.ps_find_model(data
|
124
|
+
# def self.ps_find_model(data)
|
122
125
|
# where(email: data[:email], ...).first_or_initialize
|
123
126
|
# end
|
124
127
|
end
|
@@ -126,42 +129,39 @@ end
|
|
126
129
|
|
127
130
|
Note: Be careful with collision of names
|
128
131
|
```
|
129
|
-
|
130
|
-
|
131
|
-
ps_publish %i[name_data:name key_data:key] # use alias to avoid collision
|
132
|
-
|
133
|
-
def key_data
|
134
|
-
name
|
135
|
-
end
|
136
|
-
end
|
132
|
+
# ps_publish %i[name_data:name name:key] # key will be replaced with name_data
|
133
|
+
ps_publish %i[name_data:name key_data:key] # use alias to avoid collision
|
137
134
|
```
|
138
135
|
|
139
136
|
## API
|
140
137
|
### Subscribers
|
141
|
-
- Permit to configure class level
|
142
|
-
```ps_class_subscribe(action_name,
|
143
|
-
*
|
144
|
-
*
|
138
|
+
- Permit to configure class level subscriptions
|
139
|
+
```ps_class_subscribe(action_name, from_action: nil, from_klass: nil)```
|
140
|
+
* from_action: (Optional) Source method name
|
141
|
+
* from_klass: (Optional) Source class name
|
145
142
|
|
146
|
-
- Permit to configure instance level
|
147
|
-
```ps_subscribe(attrs,
|
143
|
+
- Permit to configure instance level subscriptions (CRUD)
|
144
|
+
```ps_subscribe(attrs, from_klass: nil, actions: nil, id: nil)```
|
148
145
|
* attrs: (Array/Required) Array of all attributes to be synced
|
149
|
-
*
|
146
|
+
* from_klass: (String/Optional) Source class name (Instead of the model class name, will use this value)
|
150
147
|
* actions: (Array/Optional, default: create/update/destroy) permit to customize action names
|
151
148
|
* id: (Sym|Array/Optional, default: id) Attr identifier(s) to find the corresponding model
|
152
149
|
|
153
150
|
- Permit to configure a custom model finder
|
154
|
-
```ps_find_model(data
|
151
|
+
```ps_find_model(data)```
|
155
152
|
* data: (Hash) Data received from sync
|
156
|
-
* settings: (Hash(:klass, :action)) Class and action name from sync
|
157
153
|
Must return an existent or a new model object
|
158
154
|
|
159
155
|
- Get crud subscription configured for the class
|
160
156
|
```User.ps_subscriber(action_name)```
|
161
157
|
* action_name (default :create, :sym): can be :create, :update, :destroy
|
162
158
|
|
163
|
-
- Inspect all configured
|
164
|
-
```PubSubModelSync::Config.
|
159
|
+
- Inspect all configured subscribers
|
160
|
+
```PubSubModelSync::Config.subscribers```
|
161
|
+
|
162
|
+
- Permit to customize the way to detect if the subscribed model was changed (Only for update action).
|
163
|
+
```.ps_subscriber_changed?(data)```
|
164
|
+
By default: ```model.changed?```
|
165
165
|
|
166
166
|
### Publishers
|
167
167
|
- Permit to configure crud publishers
|
@@ -172,6 +172,7 @@ end
|
|
172
172
|
|
173
173
|
- Permit to cancel sync called after create/update/destroy (Before initializing sync service)
|
174
174
|
```model.ps_skip_callback?(action)```
|
175
|
+
Default: False
|
175
176
|
Note: Return true to cancel sync
|
176
177
|
|
177
178
|
- Callback called before preparing data for sync (Permit to stop sync)
|
@@ -198,7 +199,7 @@ end
|
|
198
199
|
* as_klass: (optional, :string) Custom class name (Default current model name)
|
199
200
|
|
200
201
|
- Publish a class level notification (Same as above: on demand call)
|
201
|
-
```PubSubModelSync::
|
202
|
+
```PubSubModelSync::MessagePublisher.publish_data(Klass_name, data, action_name)```
|
202
203
|
* klass_name: (required, Class) same class name as defined in ps_class_subscribe(...)
|
203
204
|
* data: (required, :hash) message value to deliver
|
204
205
|
* action_name: (required, :sim) same action name as defined in ps_class_subscribe(...)
|
@@ -254,23 +255,29 @@ end
|
|
254
255
|
|
255
256
|
# Publisher
|
256
257
|
it 'publish model action' do
|
257
|
-
publisher = PubSubModelSync::
|
258
|
+
publisher = PubSubModelSync::MessagePublisher
|
258
259
|
data = { name: 'hello'}
|
259
260
|
action = :create
|
260
261
|
User.ps_class_publish(data, action: action)
|
261
262
|
user = User.create(name: 'name', email: 'email')
|
262
|
-
|
263
|
+
expect(publisher).to receive(:publish_model).with(user, :create, anything)
|
263
264
|
end
|
264
265
|
|
265
266
|
it 'publish class message' do
|
266
|
-
publisher = PubSubModelSync::
|
267
|
+
publisher = PubSubModelSync::MessagePublisher
|
267
268
|
data = {msg: 'hello'}
|
268
269
|
action = :greeting
|
269
270
|
User.ps_class_publish(data, action: action)
|
270
|
-
|
271
|
+
expect(publisher).to receive(:publish_data).with('User', data, action)
|
271
272
|
end
|
272
273
|
```
|
273
274
|
|
275
|
+
## TODO
|
276
|
+
- Hooks/callbacks when message processed or failed
|
277
|
+
- Add alias attributes when subscribing (similar to publisher)
|
278
|
+
- Add flag ```model.ps_processing``` to indicate that the current transaction is being processed by pub/sub
|
279
|
+
|
280
|
+
|
274
281
|
## Contributing
|
275
282
|
|
276
283
|
Bug reports and pull requests are welcome on GitHub at https://github.com/owen2345/pub_sub_model_sync. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
data/gemfiles/Gemfile_4
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'rubocop'
|
4
|
+
gem 'bunny' # rabbit-mq
|
5
|
+
gem 'google-cloud-pubsub' # google pub/sub
|
6
|
+
gem 'ruby-kafka' # kafka pub/sub
|
7
|
+
gem 'rails', '~> 4'
|
8
|
+
gem 'bundler'
|
9
|
+
gem 'sqlite3', '1.3.13'
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'database_cleaner-active_record'
|
13
|
+
end
|
14
|
+
|
15
|
+
# Specify your gem's dependencies in pub_sub_model_sync.gemspec
|
16
|
+
gemspec
|
data/gemfiles/Gemfile_5
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'rubocop'
|
4
|
+
gem 'bunny' # rabbit-mq
|
5
|
+
gem 'google-cloud-pubsub' # google pub/sub
|
6
|
+
gem 'ruby-kafka' # kafka pub/sub
|
7
|
+
gem 'rails', '~> 5'
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem 'database_cleaner-active_record'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Specify your gem's dependencies in pub_sub_model_sync.gemspec
|
14
|
+
gemspec
|
data/gemfiles/Gemfile_6
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gem 'rubocop'
|
4
|
+
gem 'bunny' # rabbit-mq
|
5
|
+
gem 'google-cloud-pubsub' # google pub/sub
|
6
|
+
gem 'ruby-kafka' # kafka pub/sub
|
7
|
+
gem 'rails', '~> 6'
|
8
|
+
|
9
|
+
group :test do
|
10
|
+
gem 'database_cleaner-active_record'
|
11
|
+
end
|
12
|
+
|
13
|
+
# Specify your gem's dependencies in pub_sub_model_sync.gemspec
|
14
|
+
gemspec
|
data/lib/pub_sub_model_sync.rb
CHANGED
@@ -6,12 +6,15 @@ require 'active_support'
|
|
6
6
|
require 'pub_sub_model_sync/railtie'
|
7
7
|
require 'pub_sub_model_sync/config'
|
8
8
|
require 'pub_sub_model_sync/subscriber_concern'
|
9
|
-
require 'pub_sub_model_sync/
|
9
|
+
require 'pub_sub_model_sync/message_publisher'
|
10
10
|
require 'pub_sub_model_sync/publisher_concern'
|
11
11
|
require 'pub_sub_model_sync/runner'
|
12
12
|
require 'pub_sub_model_sync/connector'
|
13
13
|
require 'pub_sub_model_sync/message_processor'
|
14
14
|
|
15
|
+
require 'pub_sub_model_sync/publisher'
|
16
|
+
require 'pub_sub_model_sync/subscriber'
|
17
|
+
|
15
18
|
require 'pub_sub_model_sync/service_base'
|
16
19
|
require 'pub_sub_model_sync/service_google'
|
17
20
|
require 'pub_sub_model_sync/service_rabbit'
|
@@ -2,91 +2,39 @@
|
|
2
2
|
|
3
3
|
module PubSubModelSync
|
4
4
|
class MessageProcessor
|
5
|
-
attr_accessor :data, :
|
5
|
+
attr_accessor :data, :klass, :action
|
6
6
|
|
7
7
|
# @param data (Hash): any hash value to deliver
|
8
8
|
def initialize(data, klass, action)
|
9
9
|
@data = data
|
10
|
-
@
|
11
|
-
@
|
10
|
+
@klass = klass
|
11
|
+
@action = action
|
12
12
|
end
|
13
13
|
|
14
14
|
def process
|
15
|
-
|
16
|
-
|
17
|
-
listeners = filter_listeners
|
18
|
-
return log 'Skipped: No listeners' unless listeners.any?
|
19
|
-
|
20
|
-
eval_message(listeners)
|
21
|
-
log 'processed message' unless @failed
|
15
|
+
subscribers = filter_subscribers
|
16
|
+
subscribers.each { |subscriber| run_subscriber(subscriber) }
|
22
17
|
end
|
23
18
|
|
24
19
|
private
|
25
20
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
call_class_listener(listener)
|
30
|
-
else
|
31
|
-
call_listener(listener)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def call_class_listener(listener)
|
37
|
-
model_class = listener[:klass].constantize
|
38
|
-
model_class.send(listener[:action], data)
|
21
|
+
def run_subscriber(subscriber)
|
22
|
+
subscriber.eval_message(data)
|
23
|
+
log "processed message with: #{[klass, action, data]}"
|
39
24
|
rescue => e
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
# support for: create, update, destroy
|
45
|
-
def call_listener(listener)
|
46
|
-
model = find_model(listener)
|
47
|
-
if settings[:action].to_sym == :destroy
|
48
|
-
model.destroy!
|
49
|
-
else
|
50
|
-
populate_model(model, listener)
|
51
|
-
model.save!
|
52
|
-
end
|
53
|
-
rescue => e
|
54
|
-
log("Error listener (#{listener}): #{e.message}", :error)
|
55
|
-
@failed = true
|
56
|
-
end
|
57
|
-
|
58
|
-
def find_model(listener)
|
59
|
-
model_class = listener[:klass].constantize
|
60
|
-
if model_class.respond_to?(:ps_find_model)
|
61
|
-
return model_class.ps_find_model(data, settings)
|
62
|
-
end
|
63
|
-
|
64
|
-
model_class.where(model_identifiers(listener)).first_or_initialize
|
65
|
-
end
|
66
|
-
|
67
|
-
def model_identifiers(listener)
|
68
|
-
identifiers = listener[:settings][:id]
|
69
|
-
identifiers = [identifiers] unless identifiers.is_a?(Array)
|
70
|
-
identifiers.map { |key| [key, data[key.to_sym]] }.to_h
|
71
|
-
end
|
72
|
-
|
73
|
-
def populate_model(model, listener)
|
74
|
-
values = data.slice(*listener[:settings][:attrs])
|
75
|
-
values.each do |attr, value|
|
76
|
-
model.send("#{attr}=", value)
|
77
|
-
end
|
25
|
+
info = [klass, action, data, e.message, e.backtrace]
|
26
|
+
log("error processing message: #{info}", :error)
|
78
27
|
end
|
79
28
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
listener[:as_action].to_s == settings[:action].to_s
|
29
|
+
def filter_subscribers
|
30
|
+
PubSubModelSync::Config.subscribers.select do |subscriber|
|
31
|
+
subscriber.settings[:from_klass].to_s == klass.to_s &&
|
32
|
+
subscriber.settings[:from_action].to_s == action.to_s
|
85
33
|
end
|
86
34
|
end
|
87
35
|
|
88
36
|
def log(message, kind = :info)
|
89
|
-
PubSubModelSync::Config.log
|
37
|
+
PubSubModelSync::Config.log message, kind
|
90
38
|
end
|
91
39
|
end
|
92
40
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PubSubModelSync
|
4
|
+
class MessagePublisher
|
5
|
+
class << self
|
6
|
+
delegate :publish, to: :connector
|
7
|
+
|
8
|
+
def connector
|
9
|
+
@connector ||= PubSubModelSync::Connector.new
|
10
|
+
end
|
11
|
+
|
12
|
+
def publish_data(klass, data, action)
|
13
|
+
attrs = { klass: klass.to_s, action: action.to_sym }
|
14
|
+
publish(data, attrs)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param model: ActiveRecord model
|
18
|
+
# @param action: (Sym) Action name
|
19
|
+
# @param publisher: (Publisher, optional) Publisher to be used
|
20
|
+
def publish_model(model, action, publisher = nil)
|
21
|
+
return if model.ps_skip_sync?(action)
|
22
|
+
|
23
|
+
publisher ||= model.class.ps_publisher(action)
|
24
|
+
payload = publisher.payload(model, action)
|
25
|
+
res_before = model.ps_before_sync(action, payload[:data])
|
26
|
+
return if res_before == :cancel
|
27
|
+
|
28
|
+
publish(payload[:data], payload[:attrs])
|
29
|
+
model.ps_after_sync(action, payload[:data])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -2,42 +2,24 @@
|
|
2
2
|
|
3
3
|
module PubSubModelSync
|
4
4
|
class Publisher
|
5
|
-
attr_accessor :
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@
|
10
|
-
|
11
|
-
|
12
|
-
def publish_data(klass, data, action)
|
13
|
-
attributes = self.class.build_attrs(klass, action)
|
14
|
-
publish(data, attributes)
|
5
|
+
attr_accessor :attrs, :actions, :klass, :as_klass
|
6
|
+
def initialize(attrs, klass, actions = nil, as_klass = nil)
|
7
|
+
@attrs = attrs
|
8
|
+
@klass = klass
|
9
|
+
@actions = actions || %i[create update destroy]
|
10
|
+
@as_klass = as_klass || klass
|
15
11
|
end
|
16
12
|
|
17
|
-
|
18
|
-
|
19
|
-
return if model.ps_skip_sync?(action)
|
20
|
-
|
21
|
-
settings = model.class.ps_publisher(action).merge(custom_settings)
|
22
|
-
attributes = build_model_attrs(model, action, settings)
|
23
|
-
data = build_model_data(model, settings[:attrs])
|
24
|
-
res_before = model.ps_before_sync(action, data)
|
25
|
-
return if res_before == :cancel
|
26
|
-
|
27
|
-
publish(data.symbolize_keys, attributes)
|
28
|
-
model.ps_after_sync(action, data)
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.build_attrs(klass, action)
|
32
|
-
{ klass: klass.to_s, action: action.to_sym }
|
13
|
+
def payload(model, action)
|
14
|
+
{ data: payload_data(model), attrs: payload_attrs(model, action) }
|
33
15
|
end
|
34
16
|
|
35
17
|
private
|
36
18
|
|
37
|
-
def
|
38
|
-
source_props =
|
19
|
+
def payload_data(model)
|
20
|
+
source_props = @attrs.map { |prop| prop.to_s.split(':').first }
|
39
21
|
data = model.as_json(only: source_props, methods: source_props)
|
40
|
-
aliased_props =
|
22
|
+
aliased_props = @attrs.select { |prop| prop.to_s.include?(':') }
|
41
23
|
aliased_props.each do |prop|
|
42
24
|
source, target = prop.to_s.split(':')
|
43
25
|
data[target] = data.delete(source)
|
@@ -45,13 +27,8 @@ module PubSubModelSync
|
|
45
27
|
data.symbolize_keys
|
46
28
|
end
|
47
29
|
|
48
|
-
def
|
49
|
-
|
50
|
-
self.class.build_attrs(as_klass, action)
|
51
|
-
end
|
52
|
-
|
53
|
-
def log(msg)
|
54
|
-
PubSubModelSync::Config.log(msg)
|
30
|
+
def payload_attrs(model, action)
|
31
|
+
{ klass: (as_klass || model.class.name).to_s, action: action.to_sym }
|
55
32
|
end
|
56
33
|
end
|
57
34
|
end
|
@@ -11,6 +11,7 @@ module PubSubModelSync
|
|
11
11
|
false
|
12
12
|
end
|
13
13
|
|
14
|
+
# TODO: make it using respond_to?(:ps_skip_sync?)
|
14
15
|
# before preparing data to sync
|
15
16
|
def ps_skip_sync?(_action)
|
16
17
|
false
|
@@ -23,49 +24,49 @@ module PubSubModelSync
|
|
23
24
|
def ps_after_sync(_action, _data); end
|
24
25
|
|
25
26
|
# To perform sync on demand
|
26
|
-
# @param
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
27
|
+
# @param attrs (Array, optional): custom attrs to be used
|
28
|
+
# @param as_klass (Array, optional): custom klass name to be used
|
29
|
+
# @param publisher (Publisher, optional): custom publisher object
|
30
|
+
def ps_perform_sync(action = :create, attrs: nil, as_klass: nil,
|
31
|
+
publisher: nil)
|
32
|
+
publisher ||= self.class.ps_publisher(action).dup
|
33
|
+
publisher.attrs = attrs if attrs
|
34
|
+
publisher.as_klass = as_klass if as_klass
|
35
|
+
PubSubModelSync::MessagePublisher.publish_model(self, action, publisher)
|
31
36
|
end
|
32
37
|
|
33
38
|
module ClassMethods
|
34
39
|
# Permit to configure to publish crud actions (:create, :update, :destroy)
|
35
40
|
def ps_publish(attrs, actions: %i[create update destroy], as_klass: nil)
|
36
|
-
|
41
|
+
klass = PubSubModelSync::Publisher
|
42
|
+
publisher = klass.new(attrs, name, actions, as_klass)
|
43
|
+
PubSubModelSync::Config.publishers << publisher
|
37
44
|
actions.each do |action|
|
38
|
-
|
39
|
-
as_klass: as_klass }
|
40
|
-
PubSubModelSync::Config.publishers << info
|
41
|
-
ps_register_callback(action.to_sym, info)
|
45
|
+
ps_register_callback(action.to_sym, publisher)
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
45
49
|
# On demand class level publisher
|
46
50
|
def ps_class_publish(data, action:, as_klass: nil)
|
47
51
|
as_klass = (as_klass || name).to_s
|
48
|
-
|
52
|
+
klass = PubSubModelSync::MessagePublisher
|
53
|
+
klass.publish_data(as_klass, data, action.to_sym)
|
49
54
|
end
|
50
55
|
|
51
56
|
# Publisher info for specific action
|
52
57
|
def ps_publisher(action = :create)
|
53
|
-
PubSubModelSync::Config.publishers.find do |
|
54
|
-
|
58
|
+
PubSubModelSync::Config.publishers.find do |publisher|
|
59
|
+
publisher.klass == name && publisher.actions.include?(action)
|
55
60
|
end
|
56
61
|
end
|
57
62
|
|
58
|
-
def ps_publisher_service
|
59
|
-
PubSubModelSync::Publisher.new
|
60
|
-
end
|
61
|
-
|
62
63
|
private
|
63
64
|
|
64
|
-
def ps_register_callback(action,
|
65
|
+
def ps_register_callback(action, publisher)
|
65
66
|
after_commit(on: action) do |model|
|
66
67
|
unless model.ps_skip_callback?(action)
|
67
|
-
|
68
|
-
|
68
|
+
klass = PubSubModelSync::MessagePublisher
|
69
|
+
klass.publish_model(model, action.to_sym, publisher)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
end
|
@@ -19,7 +19,7 @@ module PubSubModelSync
|
|
19
19
|
private
|
20
20
|
|
21
21
|
# @param payload (String JSON): '{"data":{}, "attributes":{..}}'
|
22
|
-
# refer: PubSubModelSync::
|
22
|
+
# refer: PubSubModelSync::MessagePublisher(.publish_model | .publish_data)
|
23
23
|
def perform_message(payload)
|
24
24
|
data, attrs = parse_message_payload(payload)
|
25
25
|
args = [data, attrs[:klass], attrs[:action]]
|
@@ -29,10 +29,12 @@ module PubSubModelSync
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def publish(data, attributes)
|
32
|
-
log("Publishing message: #{[
|
33
|
-
|
32
|
+
log("Publishing message: #{[attributes, data]}")
|
34
33
|
payload = { data: data, attributes: attributes }.to_json
|
35
34
|
topic.publish(payload, { SERVICE_KEY => true })
|
35
|
+
rescue => e
|
36
|
+
info = [attributes, data, e.message, e.backtrace]
|
37
|
+
log("Error publishing: #{info}", :error)
|
36
38
|
end
|
37
39
|
|
38
40
|
def stop
|
@@ -29,12 +29,12 @@ module PubSubModelSync
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def publish(data, attributes)
|
32
|
-
log("Publishing: #{[
|
32
|
+
log("Publishing: #{[attributes, data]}")
|
33
33
|
payload = { data: data, attributes: attributes }
|
34
34
|
producer.produce(payload.to_json, message_settings)
|
35
35
|
producer.deliver_messages
|
36
36
|
rescue => e
|
37
|
-
info = [
|
37
|
+
info = [attributes, data, e.message, e.backtrace]
|
38
38
|
log("Error publishing: #{info}", :error)
|
39
39
|
end
|
40
40
|
|
@@ -19,7 +19,8 @@ module PubSubModelSync
|
|
19
19
|
log('Listener starting...')
|
20
20
|
subscribe_to_queue
|
21
21
|
log('Listener started')
|
22
|
-
queue.subscribe(
|
22
|
+
queue.subscribe(subscribe_settings, &method(:process_message))
|
23
|
+
loop { sleep 5 }
|
23
24
|
rescue PubSubModelSync::Runner::ShutDown
|
24
25
|
raise
|
25
26
|
rescue => e
|
@@ -27,7 +28,7 @@ module PubSubModelSync
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def publish(data, attributes)
|
30
|
-
log("Publishing: #{[
|
31
|
+
log("Publishing: #{[attributes, data]}")
|
31
32
|
deliver_data(data, attributes)
|
32
33
|
# TODO: max retry
|
33
34
|
rescue Timeout::Error => e
|
@@ -35,7 +36,7 @@ module PubSubModelSync
|
|
35
36
|
initialize
|
36
37
|
retry
|
37
38
|
rescue => e
|
38
|
-
info = [
|
39
|
+
info = [attributes, data, e.message, e.backtrace]
|
39
40
|
log("Error publishing: #{info}", :error)
|
40
41
|
end
|
41
42
|
|
@@ -50,6 +51,10 @@ module PubSubModelSync
|
|
50
51
|
{ routing_key: queue.name, type: SERVICE_KEY }
|
51
52
|
end
|
52
53
|
|
54
|
+
def subscribe_settings
|
55
|
+
{ manual_ack: false }
|
56
|
+
end
|
57
|
+
|
53
58
|
def process_message(_delivery_info, meta_info, payload)
|
54
59
|
return unless meta_info[:type] == SERVICE_KEY
|
55
60
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PubSubModelSync
|
4
|
+
class Subscriber
|
5
|
+
attr_accessor :klass, :action, :attrs, :settings
|
6
|
+
|
7
|
+
# @param settings: (Hash) { id: :id, direct_mode: false,
|
8
|
+
# from_klass: klass, from_action: action }
|
9
|
+
def initialize(klass, action, attrs: nil, settings: {})
|
10
|
+
def_settings = { id: :id, direct_mode: false,
|
11
|
+
from_klass: klass, from_action: action }
|
12
|
+
@klass = klass
|
13
|
+
@action = action
|
14
|
+
@attrs = attrs
|
15
|
+
@settings = def_settings.merge(settings)
|
16
|
+
end
|
17
|
+
|
18
|
+
def eval_message(message)
|
19
|
+
if settings[:direct_mode]
|
20
|
+
run_class_message(message)
|
21
|
+
else
|
22
|
+
run_model_message(message)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def run_class_message(message)
|
29
|
+
model_class = klass.constantize
|
30
|
+
model_class.send(action, message)
|
31
|
+
end
|
32
|
+
|
33
|
+
# support for: create, update, destroy
|
34
|
+
def run_model_message(message)
|
35
|
+
model = find_model(message)
|
36
|
+
if action == :destroy
|
37
|
+
model.destroy!
|
38
|
+
else
|
39
|
+
populate_model(model, message)
|
40
|
+
return if action == :update && !model.ps_subscriber_changed?(message)
|
41
|
+
|
42
|
+
model.save!
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_model(message)
|
47
|
+
model_class = klass.constantize
|
48
|
+
if model_class.respond_to?(:ps_find_model)
|
49
|
+
return model_class.ps_find_model(message)
|
50
|
+
end
|
51
|
+
|
52
|
+
model_class.where(model_identifiers(message)).first_or_initialize
|
53
|
+
end
|
54
|
+
|
55
|
+
def model_identifiers(message)
|
56
|
+
identifiers = Array(settings[:id])
|
57
|
+
identifiers.map { |key| [key, message[key.to_sym]] }.to_h
|
58
|
+
end
|
59
|
+
|
60
|
+
def populate_model(model, message)
|
61
|
+
values = message.slice(*attrs)
|
62
|
+
values.each do |attr, value|
|
63
|
+
model.send("#{attr}=", value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -6,38 +6,41 @@ module PubSubModelSync
|
|
6
6
|
base.extend(ClassMethods)
|
7
7
|
end
|
8
8
|
|
9
|
+
# check if model was changed to skip nonsense .update!()
|
10
|
+
def ps_subscriber_changed?(_data)
|
11
|
+
validate
|
12
|
+
changed?
|
13
|
+
end
|
14
|
+
|
9
15
|
module ClassMethods
|
10
|
-
def ps_subscribe(attrs,
|
16
|
+
def ps_subscribe(attrs, actions: nil, from_klass: name, id: :id)
|
17
|
+
settings = { id: id, from_klass: from_klass }
|
11
18
|
actions ||= %i[create update destroy]
|
12
|
-
settings = { attrs: attrs, id: id }
|
13
19
|
actions.each do |action|
|
14
|
-
add_ps_subscriber(
|
20
|
+
add_ps_subscriber(action, attrs, settings)
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
18
|
-
def ps_class_subscribe(action,
|
19
|
-
|
24
|
+
def ps_class_subscribe(action, from_action: nil, from_klass: nil)
|
25
|
+
settings = { direct_mode: true }
|
26
|
+
settings[:from_action] = from_action if from_action
|
27
|
+
settings[:from_klass] = from_klass if from_klass
|
28
|
+
add_ps_subscriber(action, nil, settings)
|
20
29
|
end
|
21
30
|
|
22
31
|
def ps_subscriber(action = :create)
|
23
|
-
PubSubModelSync::Config.
|
24
|
-
|
32
|
+
PubSubModelSync::Config.subscribers.find do |subscriber|
|
33
|
+
subscriber.klass == name && subscriber.action == action
|
25
34
|
end
|
26
35
|
end
|
27
36
|
|
28
37
|
private
|
29
38
|
|
30
|
-
# @param settings (Hash):
|
31
|
-
def add_ps_subscriber(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
action: action.to_sym,
|
36
|
-
as_action: (as_action || action).to_sym,
|
37
|
-
direct_mode: direct_mode,
|
38
|
-
settings: settings
|
39
|
-
}
|
40
|
-
PubSubModelSync::Config.listeners.push(listener) && listener
|
39
|
+
# @param settings (Hash): refer to PubSubModelSync::Subscriber.settings
|
40
|
+
def add_ps_subscriber(action, attrs, settings = {})
|
41
|
+
klass = PubSubModelSync::Subscriber
|
42
|
+
subscriber = klass.new(name, action, attrs: attrs, settings: settings)
|
43
|
+
PubSubModelSync::Config.subscribers.push(subscriber) && subscriber
|
41
44
|
end
|
42
45
|
end
|
43
46
|
end
|
data/pub_sub_model_sync.gemspec
CHANGED
@@ -5,6 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'pub_sub_model_sync/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
+
spec.required_ruby_version = '>= 2.4'
|
8
9
|
spec.name = 'pub_sub_model_sync'
|
9
10
|
spec.version = PubSubModelSync::VERSION
|
10
11
|
spec.authors = ['Owen']
|
@@ -32,7 +33,6 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
34
|
spec.require_paths = ['lib']
|
34
35
|
|
35
|
-
spec.add_dependency 'activesupport'
|
36
36
|
spec.add_dependency 'rails'
|
37
37
|
|
38
38
|
spec.add_development_dependency 'bundler'
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pub_sub_model_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Owen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-08-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: activesupport
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: rails
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -103,15 +89,6 @@ extra_rdoc_files: []
|
|
103
89
|
files:
|
104
90
|
- ".github/workflows/ruby.yml"
|
105
91
|
- ".gitignore"
|
106
|
-
- ".idea/.gitignore"
|
107
|
-
- ".idea/.rakeTasks"
|
108
|
-
- ".idea/codeStyles/codeStyleConfig.xml"
|
109
|
-
- ".idea/encodings.xml"
|
110
|
-
- ".idea/inspectionProfiles/Project_Default.xml"
|
111
|
-
- ".idea/misc.xml"
|
112
|
-
- ".idea/modules.xml"
|
113
|
-
- ".idea/pub_sub_model_sync.iml"
|
114
|
-
- ".idea/vcs.xml"
|
115
92
|
- ".rspec"
|
116
93
|
- ".rubocop.yml"
|
117
94
|
- CHANGELOG.md
|
@@ -123,10 +100,14 @@ files:
|
|
123
100
|
- Rakefile
|
124
101
|
- bin/console
|
125
102
|
- bin/setup
|
103
|
+
- gemfiles/Gemfile_4
|
104
|
+
- gemfiles/Gemfile_5
|
105
|
+
- gemfiles/Gemfile_6
|
126
106
|
- lib/pub_sub_model_sync.rb
|
127
107
|
- lib/pub_sub_model_sync/config.rb
|
128
108
|
- lib/pub_sub_model_sync/connector.rb
|
129
109
|
- lib/pub_sub_model_sync/message_processor.rb
|
110
|
+
- lib/pub_sub_model_sync/message_publisher.rb
|
130
111
|
- lib/pub_sub_model_sync/mock_google_service.rb
|
131
112
|
- lib/pub_sub_model_sync/mock_kafka_service.rb
|
132
113
|
- lib/pub_sub_model_sync/mock_rabbit_service.rb
|
@@ -138,6 +119,7 @@ files:
|
|
138
119
|
- lib/pub_sub_model_sync/service_google.rb
|
139
120
|
- lib/pub_sub_model_sync/service_kafka.rb
|
140
121
|
- lib/pub_sub_model_sync/service_rabbit.rb
|
122
|
+
- lib/pub_sub_model_sync/subscriber.rb
|
141
123
|
- lib/pub_sub_model_sync/subscriber_concern.rb
|
142
124
|
- lib/pub_sub_model_sync/tasks/worker.rake
|
143
125
|
- lib/pub_sub_model_sync/version.rb
|
@@ -149,7 +131,7 @@ metadata:
|
|
149
131
|
homepage_uri: https://github.com/owen2345/pub_sub_model_sync
|
150
132
|
source_code_uri: https://github.com/owen2345/pub_sub_model_sync
|
151
133
|
changelog_uri: https://github.com/owen2345/pub_sub_model_sync/blob/master/CHANGELOG.md
|
152
|
-
post_install_message:
|
134
|
+
post_install_message:
|
153
135
|
rdoc_options: []
|
154
136
|
require_paths:
|
155
137
|
- lib
|
@@ -157,7 +139,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
157
139
|
requirements:
|
158
140
|
- - ">="
|
159
141
|
- !ruby/object:Gem::Version
|
160
|
-
version: '
|
142
|
+
version: '2.4'
|
161
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
144
|
requirements:
|
163
145
|
- - ">="
|
@@ -165,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
147
|
version: '0'
|
166
148
|
requirements: []
|
167
149
|
rubygems_version: 3.0.8
|
168
|
-
signing_key:
|
150
|
+
signing_key:
|
169
151
|
specification_version: 4
|
170
152
|
summary: Permit to sync models between apps through pub/sub
|
171
153
|
test_files: []
|
data/.idea/.gitignore
DELETED
data/.idea/.rakeTasks
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<Settings><!--This file was automatically generated by Ruby plugin.
|
3
|
-
You are allowed to:
|
4
|
-
1. Remove rake task
|
5
|
-
2. Add existing rake tasks
|
6
|
-
To add existing rake tasks automatically delete this file and reload the project.
|
7
|
-
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Build pub_sub_model_sync-0.1.0.gem into the pkg directory" fullCmd="build" taksId="build" /><RakeTask description="Remove any temporary products" fullCmd="clean" taksId="clean" /><RakeTask description="Remove any generated files" fullCmd="clobber" taksId="clobber" /><RakeTask description="Build and install pub_sub_model_sync-0.1.0.gem into system gems" fullCmd="install" taksId="install" /><RakeGroup description="" fullCmd="" taksId="install"><RakeTask description="Build and install pub_sub_model_sync-0.1.0.gem into system gems without network access" fullCmd="install:local" taksId="local" /></RakeGroup><RakeTask description="Create tag v0.1.0 and build and push pub_sub_model_sync-0.1.0.gem to TODO: Set to 'http://mygemserver.com'" fullCmd="release[remote]" taksId="release[remote]" /><RakeTask description="Run RSpec code examples" fullCmd="spec" taksId="spec" /><RakeTask description="" fullCmd="default" taksId="default" /><RakeTask description="" fullCmd="release" taksId="release" /><RakeGroup description="" fullCmd="" taksId="release"><RakeTask description="" fullCmd="release:guard_clean" taksId="guard_clean" /><RakeTask description="" fullCmd="release:rubygem_push" taksId="rubygem_push" /><RakeTask description="" fullCmd="release:source_control_push" taksId="source_control_push" /></RakeGroup></RakeGroup></Settings>
|
data/.idea/encodings.xml
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
<component name="InspectionProjectProfileManager">
|
2
|
-
<profile version="1.0">
|
3
|
-
<option name="myName" value="Project Default" />
|
4
|
-
<inspection_tool class="Rubocop" enabled="true" level="WARNING" enabled_by_default="true">
|
5
|
-
<option name="mySeverityMap">
|
6
|
-
<map>
|
7
|
-
<entry key="convention" value="ERROR" />
|
8
|
-
<entry key="error" value="ERROR" />
|
9
|
-
<entry key="fatal" value="ERROR" />
|
10
|
-
<entry key="refactor" value="ERROR" />
|
11
|
-
<entry key="warning" value="ERROR" />
|
12
|
-
</map>
|
13
|
-
</option>
|
14
|
-
</inspection_tool>
|
15
|
-
</profile>
|
16
|
-
</component>
|
data/.idea/misc.xml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<project version="4">
|
3
|
-
<component name="JavaScriptSettings">
|
4
|
-
<option name="languageLevel" value="ES6" />
|
5
|
-
</component>
|
6
|
-
<component name="ProjectRootManager" version="2" project-jdk-name="RVM: ruby-2.5.3" project-jdk-type="RUBY_SDK" />
|
7
|
-
</project>
|
data/.idea/modules.xml
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<project version="4">
|
3
|
-
<component name="ProjectModuleManager">
|
4
|
-
<modules>
|
5
|
-
<module fileurl="file://$PROJECT_DIR$/.idea/pub_sub_model_sync.iml" filepath="$PROJECT_DIR$/.idea/pub_sub_model_sync.iml" />
|
6
|
-
</modules>
|
7
|
-
</component>
|
8
|
-
</project>
|
@@ -1,96 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
-
<module type="RUBY_MODULE" version="4">
|
3
|
-
<component name="ModuleRunConfigurationManager">
|
4
|
-
<shared />
|
5
|
-
</component>
|
6
|
-
<component name="NewModuleRootManager">
|
7
|
-
<content url="file://$MODULE_DIR$" />
|
8
|
-
<orderEntry type="jdk" jdkName="RVM: ruby-2.6.5" jdkType="RUBY_SDK" />
|
9
|
-
<orderEntry type="sourceFolder" forTests="false" />
|
10
|
-
<orderEntry type="library" scope="PROVIDED" name="actioncable (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
11
|
-
<orderEntry type="library" scope="PROVIDED" name="actionmailbox (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
12
|
-
<orderEntry type="library" scope="PROVIDED" name="actionmailer (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
13
|
-
<orderEntry type="library" scope="PROVIDED" name="actionpack (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
14
|
-
<orderEntry type="library" scope="PROVIDED" name="actiontext (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
15
|
-
<orderEntry type="library" scope="PROVIDED" name="actionview (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
16
|
-
<orderEntry type="library" scope="PROVIDED" name="activejob (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
17
|
-
<orderEntry type="library" scope="PROVIDED" name="activemodel (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
18
|
-
<orderEntry type="library" scope="PROVIDED" name="activerecord (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
19
|
-
<orderEntry type="library" scope="PROVIDED" name="activestorage (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
20
|
-
<orderEntry type="library" scope="PROVIDED" name="activesupport (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
21
|
-
<orderEntry type="library" scope="PROVIDED" name="addressable (v2.7.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
22
|
-
<orderEntry type="library" scope="PROVIDED" name="amq-protocol (v2.3.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
23
|
-
<orderEntry type="library" scope="PROVIDED" name="ast (v2.4.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
24
|
-
<orderEntry type="library" scope="PROVIDED" name="builder (v3.2.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
25
|
-
<orderEntry type="library" scope="PROVIDED" name="bundler (v2.1.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
26
|
-
<orderEntry type="library" scope="PROVIDED" name="bunny (v2.14.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
27
|
-
<orderEntry type="library" scope="PROVIDED" name="concurrent-ruby (v1.1.6, RVM: ruby-2.6.5) [gem]" level="application" />
|
28
|
-
<orderEntry type="library" scope="PROVIDED" name="crass (v1.0.6, RVM: ruby-2.6.5) [gem]" level="application" />
|
29
|
-
<orderEntry type="library" scope="PROVIDED" name="database_cleaner (v1.8.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
30
|
-
<orderEntry type="library" scope="PROVIDED" name="database_cleaner-active_record (v1.8.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
31
|
-
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
32
|
-
<orderEntry type="library" scope="PROVIDED" name="digest-crc (v0.5.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
33
|
-
<orderEntry type="library" scope="PROVIDED" name="erubi (v1.9.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
34
|
-
<orderEntry type="library" scope="PROVIDED" name="faraday (v0.17.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
35
|
-
<orderEntry type="library" scope="PROVIDED" name="globalid (v0.4.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
36
|
-
<orderEntry type="library" scope="PROVIDED" name="google-cloud-core (v1.3.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
37
|
-
<orderEntry type="library" scope="PROVIDED" name="google-cloud-env (v1.2.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
38
|
-
<orderEntry type="library" scope="PROVIDED" name="google-cloud-pubsub (v1.0.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
39
|
-
<orderEntry type="library" scope="PROVIDED" name="google-gax (v1.7.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
40
|
-
<orderEntry type="library" scope="PROVIDED" name="google-protobuf (v3.11.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
41
|
-
<orderEntry type="library" scope="PROVIDED" name="googleapis-common-protos (v1.3.9, RVM: ruby-2.6.5) [gem]" level="application" />
|
42
|
-
<orderEntry type="library" scope="PROVIDED" name="googleapis-common-protos-types (v1.0.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
43
|
-
<orderEntry type="library" scope="PROVIDED" name="googleauth (v0.9.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
44
|
-
<orderEntry type="library" scope="PROVIDED" name="grpc (v1.27.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
45
|
-
<orderEntry type="library" scope="PROVIDED" name="grpc-google-iam-v1 (v0.6.9, RVM: ruby-2.6.5) [gem]" level="application" />
|
46
|
-
<orderEntry type="library" scope="PROVIDED" name="i18n (v1.8.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
47
|
-
<orderEntry type="library" scope="PROVIDED" name="jaro_winkler (v1.5.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
48
|
-
<orderEntry type="library" scope="PROVIDED" name="jwt (v2.2.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
49
|
-
<orderEntry type="library" scope="PROVIDED" name="loofah (v2.5.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
50
|
-
<orderEntry type="library" scope="PROVIDED" name="mail (v2.7.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
51
|
-
<orderEntry type="library" scope="PROVIDED" name="marcel (v0.3.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
52
|
-
<orderEntry type="library" scope="PROVIDED" name="memoist (v0.16.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
53
|
-
<orderEntry type="library" scope="PROVIDED" name="method_source (v1.0.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
54
|
-
<orderEntry type="library" scope="PROVIDED" name="mimemagic (v0.3.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
55
|
-
<orderEntry type="library" scope="PROVIDED" name="mini_mime (v1.0.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
56
|
-
<orderEntry type="library" scope="PROVIDED" name="mini_portile2 (v2.4.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
57
|
-
<orderEntry type="library" scope="PROVIDED" name="minitest (v5.14.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
58
|
-
<orderEntry type="library" scope="PROVIDED" name="multi_json (v1.14.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
59
|
-
<orderEntry type="library" scope="PROVIDED" name="multipart-post (v2.1.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
60
|
-
<orderEntry type="library" scope="PROVIDED" name="nio4r (v2.5.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
61
|
-
<orderEntry type="library" scope="PROVIDED" name="nokogiri (v1.10.9, RVM: ruby-2.6.5) [gem]" level="application" />
|
62
|
-
<orderEntry type="library" scope="PROVIDED" name="os (v1.0.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
63
|
-
<orderEntry type="library" scope="PROVIDED" name="parallel (v1.19.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
64
|
-
<orderEntry type="library" scope="PROVIDED" name="parser (v2.7.0.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
65
|
-
<orderEntry type="library" scope="PROVIDED" name="public_suffix (v4.0.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
66
|
-
<orderEntry type="library" scope="PROVIDED" name="rack (v2.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
67
|
-
<orderEntry type="library" scope="PROVIDED" name="rack-test (v1.1.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
68
|
-
<orderEntry type="library" scope="PROVIDED" name="rails (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
69
|
-
<orderEntry type="library" scope="PROVIDED" name="rails-dom-testing (v2.0.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
70
|
-
<orderEntry type="library" scope="PROVIDED" name="rails-html-sanitizer (v1.3.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
71
|
-
<orderEntry type="library" scope="PROVIDED" name="railties (v6.0.2.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
72
|
-
<orderEntry type="library" scope="PROVIDED" name="rainbow (v3.0.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
73
|
-
<orderEntry type="library" scope="PROVIDED" name="rake (v13.0.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
74
|
-
<orderEntry type="library" scope="PROVIDED" name="rexml (v3.2.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
75
|
-
<orderEntry type="library" scope="PROVIDED" name="rly (v0.2.3, RVM: ruby-2.6.5) [gem]" level="application" />
|
76
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec (v3.9.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
77
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v3.9.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
78
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v3.9.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
79
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v3.9.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
80
|
-
<orderEntry type="library" scope="PROVIDED" name="rspec-support (v3.9.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
81
|
-
<orderEntry type="library" scope="PROVIDED" name="rubocop (v0.80.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
82
|
-
<orderEntry type="library" scope="PROVIDED" name="ruby-kafka (v1.0.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
83
|
-
<orderEntry type="library" scope="PROVIDED" name="ruby-progressbar (v1.10.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
84
|
-
<orderEntry type="library" scope="PROVIDED" name="signet (v0.11.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
85
|
-
<orderEntry type="library" scope="PROVIDED" name="sprockets (v4.0.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
86
|
-
<orderEntry type="library" scope="PROVIDED" name="sprockets-rails (v3.2.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
87
|
-
<orderEntry type="library" scope="PROVIDED" name="sqlite3 (v1.4.2, RVM: ruby-2.6.5) [gem]" level="application" />
|
88
|
-
<orderEntry type="library" scope="PROVIDED" name="thor (v1.0.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
89
|
-
<orderEntry type="library" scope="PROVIDED" name="thread_safe (v0.3.6, RVM: ruby-2.6.5) [gem]" level="application" />
|
90
|
-
<orderEntry type="library" scope="PROVIDED" name="tzinfo (v1.2.7, RVM: ruby-2.6.5) [gem]" level="application" />
|
91
|
-
<orderEntry type="library" scope="PROVIDED" name="unicode-display_width (v1.6.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
92
|
-
<orderEntry type="library" scope="PROVIDED" name="websocket-driver (v0.7.1, RVM: ruby-2.6.5) [gem]" level="application" />
|
93
|
-
<orderEntry type="library" scope="PROVIDED" name="websocket-extensions (v0.1.4, RVM: ruby-2.6.5) [gem]" level="application" />
|
94
|
-
<orderEntry type="library" scope="PROVIDED" name="zeitwerk (v2.3.0, RVM: ruby-2.6.5) [gem]" level="application" />
|
95
|
-
</component>
|
96
|
-
</module>
|