table_sync 1.13.0 → 2.3.0

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: 01c6a6ad4b67454e29e7eaf06f85c09f4d786fc7842ef34cc87bc1db29937765
4
- data.tar.gz: 5ffdfad99bdd53182870f0297c9bba8181884b51fc8a7bcc234ec8fd7a5035ee
3
+ metadata.gz: f0b124973e82ee0bf943d61fb64b4ef0eb2798d1bca0b9c6396a597b2bf00ca5
4
+ data.tar.gz: d119902d368a1af85d954f586036b4f2e12b727f82bf4901b1f852b86e047627
5
5
  SHA512:
6
- metadata.gz: b7c21a601fa063b33ee9f13d580700c5ba2f70c88cdf59fbccc1fe5e9bb4a88d7cba8336dae55be7154e4aaf07194f869789c0b6a6886a04d7dc08db2dfa3f15
7
- data.tar.gz: 378f2049f688922282d0b99972b28e021b36508fc153c8546085b710ca1649993d4e19f1dfa5eaebe9041dfdbd0b871ddef1f042a0bf29825dee8ebfa6ac69bc
6
+ metadata.gz: 653ffcb319c370378c8e861b0dd0c3468970dc10c8736a570c9f6fabbb1af05ade6a0506a744617bb9b9c2b07f218405ab17ecf969c9e7fd584ef96468d8e990
7
+ data.tar.gz: 0d080baf2462565addf4cfada754a5ba1ef67772a5e155d3958a354b938e190a99eb2d961dc56c70f26fa903cdc1ee76d0f4761999a13caf05c7e93c351ac22c
data/.gitignore CHANGED
@@ -9,5 +9,4 @@
9
9
  /spec/reports/
10
10
  /tmp/
11
11
  .ruby-version
12
- Gemfile.lock
13
12
  *.gem
@@ -2,7 +2,7 @@ inherit_gem:
2
2
  rubocop-config-umbrellio: lib/rubocop.yml
3
3
 
4
4
  AllCops:
5
- TargetRubyVersion: 2.3
5
+ TargetRubyVersion: 2.5
6
6
  Include:
7
7
  - bin/*
8
8
  - lib/**/*.rb
@@ -10,3 +10,7 @@ AllCops:
10
10
  - Gemfile
11
11
  - Rakefile
12
12
  - table_sync.gemspec
13
+
14
+ Style/Alias:
15
+ Enabled: true
16
+ EnforcedStyle: prefer_alias_method
@@ -1,13 +1,13 @@
1
1
  language: ruby
2
2
 
3
+ rvm:
4
+ - 2.5
5
+ - 2.6
6
+ - 2.7
7
+ - ruby-head
8
+
3
9
  matrix:
4
10
  fast_finish: true
5
- include:
6
- - rvm: 2.3
7
- - rvm: 2.4
8
- - rvm: 2.5
9
- - rvm: 2.6
10
- - rvm: ruby-head
11
11
  allow_failures:
12
12
  - rvm: ruby-head
13
13
 
@@ -1,6 +1,43 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [2.3.0] - 2020-07-22
5
+ ### Added
6
+ - ruby 2.7 in Travis
7
+ - Gemfile.lock
8
+
9
+ ### Changed
10
+ - some fixes to get rid of warnings for ruby 2.7 (implicit conversion of hashes into kwargs will be dropped)
11
+ - TableSync.sync now explicitly expects klass and kwargs (it converts them into hash)
12
+ - TableSync::Instrument.notify now explicitly expects kwargs and delegates them further as kwargs
13
+
14
+ ### Removed
15
+ - ruby 2.3, 2.4 from Travis
16
+
17
+ ## [2.2.0] - 2020-04-12
18
+ ### Added
19
+ - Introduce Plugin ecosystem (**TableSync::Plugins**);
20
+
21
+ ## [2.1.1] - 2020-04-10
22
+ ### Fixed
23
+ - Updated docs for batch_publishing to fully reflect changes in 2.1.0
24
+
25
+ ## [2.1.0] - 2020-04-09
26
+ ### Added
27
+ - **TableSync::BatchPublisher**: custom headers;
28
+ - **TableSync::BatchPublisher**: custom events;
29
+
30
+ ### Changed
31
+ - Slight changes to specs
32
+
33
+ ## [2.0.0] - 2020-04-06
34
+ ### Changed
35
+ - Sequel publishing hooks: checking for `:destroy` events inside `:if`/`:unless` predicates
36
+
37
+ ## [1.13.1] - 2020-03-24
38
+ ### Fixed
39
+ - **TableSync::BatchPublisher**: incorrect `attrs_for_metadata` definition (typo in method name);
40
+
4
41
  ## [1.13.0] - 2019-11-02
5
42
  ### Added
6
43
  - Wrapping interface around receiving logic (`wrap_receiving`);
@@ -0,0 +1,257 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ table_sync (2.2.0)
5
+ memery
6
+ rabbit_messaging (~> 0.3)
7
+ rails
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actioncable (6.0.3.2)
13
+ actionpack (= 6.0.3.2)
14
+ nio4r (~> 2.0)
15
+ websocket-driver (>= 0.6.1)
16
+ actionmailbox (6.0.3.2)
17
+ actionpack (= 6.0.3.2)
18
+ activejob (= 6.0.3.2)
19
+ activerecord (= 6.0.3.2)
20
+ activestorage (= 6.0.3.2)
21
+ activesupport (= 6.0.3.2)
22
+ mail (>= 2.7.1)
23
+ actionmailer (6.0.3.2)
24
+ actionpack (= 6.0.3.2)
25
+ actionview (= 6.0.3.2)
26
+ activejob (= 6.0.3.2)
27
+ mail (~> 2.5, >= 2.5.4)
28
+ rails-dom-testing (~> 2.0)
29
+ actionpack (6.0.3.2)
30
+ actionview (= 6.0.3.2)
31
+ activesupport (= 6.0.3.2)
32
+ rack (~> 2.0, >= 2.0.8)
33
+ rack-test (>= 0.6.3)
34
+ rails-dom-testing (~> 2.0)
35
+ rails-html-sanitizer (~> 1.0, >= 1.2.0)
36
+ actiontext (6.0.3.2)
37
+ actionpack (= 6.0.3.2)
38
+ activerecord (= 6.0.3.2)
39
+ activestorage (= 6.0.3.2)
40
+ activesupport (= 6.0.3.2)
41
+ nokogiri (>= 1.8.5)
42
+ actionview (6.0.3.2)
43
+ activesupport (= 6.0.3.2)
44
+ builder (~> 3.1)
45
+ erubi (~> 1.4)
46
+ rails-dom-testing (~> 2.0)
47
+ rails-html-sanitizer (~> 1.1, >= 1.2.0)
48
+ activejob (6.0.3.2)
49
+ activesupport (= 6.0.3.2)
50
+ globalid (>= 0.3.6)
51
+ activemodel (6.0.3.2)
52
+ activesupport (= 6.0.3.2)
53
+ activerecord (6.0.3.2)
54
+ activemodel (= 6.0.3.2)
55
+ activesupport (= 6.0.3.2)
56
+ activestorage (6.0.3.2)
57
+ actionpack (= 6.0.3.2)
58
+ activejob (= 6.0.3.2)
59
+ activerecord (= 6.0.3.2)
60
+ marcel (~> 0.3.1)
61
+ activesupport (6.0.3.2)
62
+ concurrent-ruby (~> 1.0, >= 1.0.2)
63
+ i18n (>= 0.7, < 2)
64
+ minitest (~> 5.1)
65
+ tzinfo (~> 1.1)
66
+ zeitwerk (~> 2.2, >= 2.2.2)
67
+ amq-protocol (2.3.2)
68
+ ast (2.4.1)
69
+ builder (3.2.4)
70
+ bundler-audit (0.7.0.1)
71
+ bundler (>= 1.2.0, < 3)
72
+ thor (>= 0.18, < 2)
73
+ bunny (2.15.0)
74
+ amq-protocol (~> 2.3, >= 2.3.1)
75
+ coderay (1.1.3)
76
+ concurrent-ruby (1.1.6)
77
+ coveralls (0.8.23)
78
+ json (>= 1.8, < 3)
79
+ simplecov (~> 0.16.1)
80
+ term-ansicolor (~> 1.3)
81
+ thor (>= 0.19.4, < 2.0)
82
+ tins (~> 1.6)
83
+ crass (1.0.6)
84
+ diff-lcs (1.4.4)
85
+ docile (1.3.2)
86
+ erubi (1.9.0)
87
+ exception_notification (4.4.3)
88
+ actionmailer (>= 4.0, < 7)
89
+ activesupport (>= 4.0, < 7)
90
+ globalid (0.4.2)
91
+ activesupport (>= 4.2.0)
92
+ i18n (1.8.4)
93
+ concurrent-ruby (~> 1.0)
94
+ jaro_winkler (1.5.4)
95
+ json (2.3.1)
96
+ lamian (1.2.0)
97
+ rails (>= 4.2)
98
+ loofah (2.6.0)
99
+ crass (~> 1.0.2)
100
+ nokogiri (>= 1.5.9)
101
+ mail (2.7.1)
102
+ mini_mime (>= 0.1.1)
103
+ marcel (0.3.3)
104
+ mimemagic (~> 0.3.2)
105
+ memery (1.3.0)
106
+ ruby2_keywords (~> 0.0.2)
107
+ method_source (1.0.0)
108
+ mimemagic (0.3.5)
109
+ mini_mime (1.0.2)
110
+ mini_portile2 (2.4.0)
111
+ minitest (5.14.1)
112
+ nio4r (2.5.2)
113
+ nokogiri (1.10.10)
114
+ mini_portile2 (~> 2.4.0)
115
+ parallel (1.19.2)
116
+ parser (2.7.1.4)
117
+ ast (~> 2.4.1)
118
+ pg (0.21.0)
119
+ pry (0.13.1)
120
+ coderay (~> 1.1)
121
+ method_source (~> 1.0)
122
+ rabbit_messaging (0.7.1)
123
+ bunny (~> 2.0)
124
+ exception_notification
125
+ lamian
126
+ rails
127
+ sneakers (~> 2.0)
128
+ tainbox
129
+ rack (2.2.3)
130
+ rack-test (1.1.0)
131
+ rack (>= 1.0, < 3)
132
+ rails (6.0.3.2)
133
+ actioncable (= 6.0.3.2)
134
+ actionmailbox (= 6.0.3.2)
135
+ actionmailer (= 6.0.3.2)
136
+ actionpack (= 6.0.3.2)
137
+ actiontext (= 6.0.3.2)
138
+ actionview (= 6.0.3.2)
139
+ activejob (= 6.0.3.2)
140
+ activemodel (= 6.0.3.2)
141
+ activerecord (= 6.0.3.2)
142
+ activestorage (= 6.0.3.2)
143
+ activesupport (= 6.0.3.2)
144
+ bundler (>= 1.3.0)
145
+ railties (= 6.0.3.2)
146
+ sprockets-rails (>= 2.0.0)
147
+ rails-dom-testing (2.0.3)
148
+ activesupport (>= 4.2.0)
149
+ nokogiri (>= 1.6)
150
+ rails-html-sanitizer (1.3.0)
151
+ loofah (~> 2.3)
152
+ railties (6.0.3.2)
153
+ actionpack (= 6.0.3.2)
154
+ activesupport (= 6.0.3.2)
155
+ method_source
156
+ rake (>= 0.8.7)
157
+ thor (>= 0.20.3, < 2.0)
158
+ rainbow (3.0.0)
159
+ rake (13.0.1)
160
+ rexml (3.2.4)
161
+ rspec (3.9.0)
162
+ rspec-core (~> 3.9.0)
163
+ rspec-expectations (~> 3.9.0)
164
+ rspec-mocks (~> 3.9.0)
165
+ rspec-core (3.9.2)
166
+ rspec-support (~> 3.9.3)
167
+ rspec-expectations (3.9.2)
168
+ diff-lcs (>= 1.2.0, < 2.0)
169
+ rspec-support (~> 3.9.0)
170
+ rspec-mocks (3.9.1)
171
+ diff-lcs (>= 1.2.0, < 2.0)
172
+ rspec-support (~> 3.9.0)
173
+ rspec-support (3.9.3)
174
+ rubocop (0.81.0)
175
+ jaro_winkler (~> 1.5.1)
176
+ parallel (~> 1.10)
177
+ parser (>= 2.7.0.1)
178
+ rainbow (>= 2.2.2, < 4.0)
179
+ rexml
180
+ ruby-progressbar (~> 1.7)
181
+ unicode-display_width (>= 1.4.0, < 2.0)
182
+ rubocop-config-umbrellio (0.81.0.78)
183
+ rubocop (= 0.81.0)
184
+ rubocop-performance (= 1.5.2)
185
+ rubocop-rails (= 2.5.0)
186
+ rubocop-rspec (= 1.38.1)
187
+ rubocop-performance (1.5.2)
188
+ rubocop (>= 0.71.0)
189
+ rubocop-rails (2.5.0)
190
+ activesupport
191
+ rack (>= 1.1)
192
+ rubocop (>= 0.72.0)
193
+ rubocop-rspec (1.38.1)
194
+ rubocop (>= 0.68.1)
195
+ ruby-progressbar (1.10.1)
196
+ ruby2_keywords (0.0.2)
197
+ sequel (5.34.0)
198
+ serverengine (2.0.7)
199
+ sigdump (~> 0.2.2)
200
+ sigdump (0.2.4)
201
+ simplecov (0.16.1)
202
+ docile (~> 1.1)
203
+ json (>= 1.8, < 3)
204
+ simplecov-html (~> 0.10.0)
205
+ simplecov-html (0.10.2)
206
+ sneakers (2.11.0)
207
+ bunny (~> 2.12)
208
+ concurrent-ruby (~> 1.0)
209
+ rake
210
+ serverengine (~> 2.0.5)
211
+ thor
212
+ sprockets (4.0.2)
213
+ concurrent-ruby (~> 1.0)
214
+ rack (> 1, < 3)
215
+ sprockets-rails (3.2.1)
216
+ actionpack (>= 4.0)
217
+ activesupport (>= 4.0)
218
+ sprockets (>= 3.0.0)
219
+ sync (0.5.0)
220
+ tainbox (2.1.2)
221
+ activesupport
222
+ term-ansicolor (1.7.1)
223
+ tins (~> 1.0)
224
+ thor (1.0.1)
225
+ thread_safe (0.3.6)
226
+ timecop (0.9.1)
227
+ tins (1.25.0)
228
+ sync
229
+ tzinfo (1.2.7)
230
+ thread_safe (~> 0.1)
231
+ unicode-display_width (1.7.0)
232
+ websocket-driver (0.7.3)
233
+ websocket-extensions (>= 0.1.0)
234
+ websocket-extensions (0.1.5)
235
+ zeitwerk (2.4.0)
236
+
237
+ PLATFORMS
238
+ ruby
239
+
240
+ DEPENDENCIES
241
+ activejob (>= 6.0)
242
+ activerecord (>= 6.0)
243
+ bundler
244
+ bundler-audit
245
+ coveralls (~> 0.8)
246
+ pg (~> 0.18)
247
+ pry
248
+ rake
249
+ rspec (~> 3.8)
250
+ rubocop-config-umbrellio (~> 0.81)
251
+ sequel
252
+ simplecov (~> 0.16)
253
+ table_sync!
254
+ timecop
255
+
256
+ BUNDLED WITH
257
+ 2.1.4
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2019 Umbrellio
3
+ Copyright (c) 2019-2020 Umbrellio
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  DB Table synchronization between microservices based on Model's event system and RabbitMQ messaging
4
4
 
5
- ## Instalation
5
+ ## Installation
6
6
 
7
7
  ```ruby
8
8
  gem 'table_sync'
@@ -21,6 +21,7 @@ require 'table_sync'
21
21
  ## Usage
22
22
 
23
23
  - [Documentation](docs/synopsis.md)
24
+ - [Development](docs/development.md)
24
25
 
25
26
  ## Contributing
26
27
 
@@ -0,0 +1,43 @@
1
+ # TableSync (development)
2
+
3
+ ## Table of Contents
4
+
5
+ - [Creation and registration of the new plugin](#creation-and-registration-of-the-new-plugin)
6
+
7
+ ### Creation and registration of the new plugin
8
+
9
+ * Create a class inherited from `TableSync::Plugins::Abstract` (recommendation: place it in the plugins directory (`lib/plugins/`));
10
+ * Implement `.install!` method (`TableSync::Plugins::Abstract.install!`)
11
+ * Register the newly created class in plugins ecosystem (`TableSync.register_plugin('plugin_name', PluginClass))`);
12
+ * Usage: `TableSync.enable(:plugin_name)` / `TableSync.plugin(:plugin_name)` / `TableSync.load(:plugin_name)` (string name is supported too);
13
+
14
+ Example:
15
+
16
+ ```ruby
17
+ # 1) creation (lib/plugins/global_method.rb)
18
+ class TableSync::Plugins::GlobalMethod < TableSync::Plugins::Abstract
19
+ class << self
20
+ # 2) plugin loader method implementation
21
+ def install!
22
+ ::TableSync.extend(Module.new do
23
+ def global_method
24
+ :works!
25
+ end
26
+ end)
27
+ end
28
+ end
29
+ end
30
+
31
+ # 3) plugin registration
32
+ TableSync.register('global_method', TableSync::Plugins::GlobalMethod)
33
+
34
+ # 4) enable registerd plugin
35
+ TableSync.plugin(:global_method) # string is supported too
36
+ # --- or ---
37
+ TableSync.enable(:global_method) # string is supported too
38
+ # --- or ---
39
+ TableSync.load(:global_method) # string is supported too
40
+
41
+ # Your new functionality
42
+ TableSync.global_method # => :works!
43
+ ```
@@ -90,11 +90,10 @@ where state is one of `:created / :updated / :destroyed` and `confirm` is Rabbit
90
90
  # Manual publishing with batches
91
91
 
92
92
  You can use `TableSync::BatchPublisher` to publish changes in batches (array of hashes in `attributes`).
93
- For now, only the following changes in the table can be published: `create` and` update`.
94
93
 
95
94
  When using `TableSync::BatchPublisher`,` TableSync.routing_key_callable` is called as follows:
96
95
  `TableSync.routing_key_callable.call(klass, {})`, i.e. empty hash is passed instead of attributes.
97
- And `TableSync.routing_metadata_callable` is not called at all: header value is set to empty hash.
96
+ And `TableSync.routing_metadata_callable` is not called at all: metadata is set to empty hash.
98
97
 
99
98
  `TableSync::BatchPublisher.new(object_class, original_attributes_array, **options)`, where `original_attributes_array` is an array with hash of attributes of published objects and `options` is a hash of options.
100
99
 
@@ -103,21 +102,30 @@ And `TableSync.routing_metadata_callable` is not called at all: header value is
103
102
  - `routing_key`, which is a custom key used (if given) to override one from `TableSync.routing_key_callable`, `nil` by default
104
103
  - `push_original_attributes` (default value is `false`), if this option is set to `true`,
105
104
  original_attributes_array will be pushed to Rabbit instead of fetching records from database and sending their mapped attributes.
105
+ - `headers`, which is an option for custom headers (can be used for headers exchanges routes), `nil` by default
106
+ - `event`, which is an option for event specification (`:destroy` or `:update`), `:update` by default
106
107
 
107
108
  Example:
108
109
 
109
110
  ```ruby
110
- TableSync::BatchPublisher.new("SomeClass", [{ id: 1 }, { id: 2 }], confirm: false, routing_key: "custom_routing_key")
111
+ TableSync::BatchPublisher.new(
112
+ "SomeClass",
113
+ [{ id: 1 }, { id: 2 }],
114
+ confirm: false,
115
+ routing_key: "custom_routing_key",
116
+ push_original_attributes: true,
117
+ headers: { key: :value },
118
+ event: :destroy,
119
+ )
111
120
  ```
112
121
 
113
122
  # Manual publishing with batches (Russian)
114
123
 
115
124
  С помощью класса `TableSync::BatchPublisher` вы можете опубликовать изменения батчами (массивом в `attributes`).
116
- Пока можно публиковать только следующие изменения в таблице: `создание записи` и `обновление записи`.
117
125
 
118
126
  При использовании `TableSync::BatchPublisher`, `TableSync.routing_key_callable` вызывается следующим образом:
119
127
  `TableSync.routing_key_callable.call(klass, {})`, то есть вместо аттрибутов передается пустой хэш.
120
- А `TableSync.routing_metadata_callable` не вызывается вовсе: в хидерах устанавливается пустой хэш.
128
+ А `TableSync.routing_metadata_callable` не вызывается вовсе: в метадате устанавливается пустой хэш.
121
129
 
122
130
  `TableSync::BatchPublisher.new(object_class, original_attributes_array, **options)`, где `original_attributes_array` - массив с аттрибутами публикуемых объектов и `options`- это хэш с дополнительными опциями.
123
131
 
@@ -125,11 +133,21 @@ TableSync::BatchPublisher.new("SomeClass", [{ id: 1 }, { id: 2 }], confirm: fals
125
133
  - `confirm`, флаг для RabbitMQ, по умолчанию - `true`
126
134
  - `routing_key`, ключ, который (если указан) замещает ключ, получаемый из `TableSync.routing_key_callable`, по умолчанию - `nil`
127
135
  - `push_original_attributes` (значение по умолчанию `false`), если для этой опции задано значение true, в Rabbit будут отправлены original_attributes_array, вместо получения значений записей из базы непосредственно перед отправкой.
136
+ - `headers`, опция для задания headers (можно использовать для задания маршрутов в headers exchange'ах), `nil` по умолчанию
137
+ - `event`, опция для указания типа события (`:destroy` или `:update`), `:update` по умолчанию
128
138
 
129
139
  Example:
130
140
 
131
141
  ```ruby
132
- TableSync::BatchPublisher.new("SomeClass", [{ id: 1 }, { id: 2 }], confirm: false, routing_key: "custom_routing_key")
142
+ TableSync::BatchPublisher.new(
143
+ "SomeClass",
144
+ [{ id: 1 }, { id: 2 }],
145
+ confirm: false,
146
+ routing_key: "custom_routing_key",
147
+ push_original_attributes: true,
148
+ headers: { key: :value },
149
+ event: :destroy,
150
+ )
133
151
  ```
134
152
 
135
153
  # Receiving changes
@@ -7,26 +7,31 @@ require "active_support/core_ext/object/blank"
7
7
  require "active_support/core_ext/numeric/time"
8
8
 
9
9
  module TableSync
10
- require_relative "./table_sync/version"
11
- require_relative "./table_sync/errors"
12
- require_relative "./table_sync/event_actions"
13
- require_relative "./table_sync/event_actions/data_wrapper"
14
- require_relative "./table_sync/config"
15
- require_relative "./table_sync/config/callback_registry"
16
- require_relative "./table_sync/config_decorator"
17
- require_relative "./table_sync/dsl"
18
- require_relative "./table_sync/receiving_handler"
19
- require_relative "./table_sync/base_publisher"
20
- require_relative "./table_sync/publisher"
21
- require_relative "./table_sync/batch_publisher"
22
- require_relative "./table_sync/orm_adapter/active_record"
23
- require_relative "./table_sync/orm_adapter/sequel"
24
- require_relative "./table_sync/model/active_record"
25
- require_relative "./table_sync/model/sequel"
26
- require_relative "./table_sync/instrument"
27
- require_relative "./table_sync/instrument_adapter/active_support"
28
- require_relative "./table_sync/naming_resolver/active_record"
29
- require_relative "./table_sync/naming_resolver/sequel"
10
+ require_relative "table_sync/version"
11
+ require_relative "table_sync/errors"
12
+ require_relative "table_sync/plugins"
13
+ require_relative "table_sync/event_actions"
14
+ require_relative "table_sync/event_actions/data_wrapper"
15
+ require_relative "table_sync/config"
16
+ require_relative "table_sync/config/callback_registry"
17
+ require_relative "table_sync/config_decorator"
18
+ require_relative "table_sync/dsl"
19
+ require_relative "table_sync/receiving_handler"
20
+ require_relative "table_sync/base_publisher"
21
+ require_relative "table_sync/publisher"
22
+ require_relative "table_sync/batch_publisher"
23
+ require_relative "table_sync/orm_adapter/active_record"
24
+ require_relative "table_sync/orm_adapter/sequel"
25
+ require_relative "table_sync/model/active_record"
26
+ require_relative "table_sync/model/sequel"
27
+ require_relative "table_sync/instrument"
28
+ require_relative "table_sync/instrument_adapter/active_support"
29
+ require_relative "table_sync/naming_resolver/active_record"
30
+ require_relative "table_sync/naming_resolver/sequel"
31
+
32
+ # @api public
33
+ # @since 2.2.0
34
+ extend Plugins::AccessMixin
30
35
 
31
36
  class << self
32
37
  include Memery
@@ -38,8 +43,8 @@ module TableSync
38
43
  attr_accessor :routing_metadata_callable
39
44
  attr_accessor :notifier
40
45
 
41
- def sync(*args)
42
- orm.setup_sync(*args)
46
+ def sync(klass, **opts)
47
+ orm.setup_sync(klass, opts)
43
48
  end
44
49
 
45
50
  def orm=(val)
@@ -2,13 +2,16 @@
2
2
 
3
3
  class TableSync::BatchPublisher < TableSync::BasePublisher
4
4
  def initialize(object_class, original_attributes_array, **options)
5
- @object_class = object_class.constantize
6
5
  @original_attributes_array = original_attributes_array.map do |hash|
7
6
  filter_safe_for_serialization(hash.deep_symbolize_keys)
8
7
  end
9
- @confirm = options[:confirm] || true
10
- @routing_key = options[:routing_key] || resolve_routing_key
8
+
9
+ @object_class = object_class.constantize
10
+ @confirm = options[:confirm] || true
11
+ @routing_key = options[:routing_key] || resolve_routing_key
11
12
  @push_original_attributes = options[:push_original_attributes] || false
13
+ @headers = options[:headers]
14
+ @event = options[:event] || :update
12
15
  end
13
16
 
14
17
  def publish
@@ -27,7 +30,7 @@ class TableSync::BatchPublisher < TableSync::BasePublisher
27
30
 
28
31
  private
29
32
 
30
- attr_reader :original_attributes_array, :routing_key
33
+ attr_reader :original_attributes_array, :routing_key, :headers, :event
31
34
 
32
35
  def push_original_attributes?
33
36
  @push_original_attributes
@@ -57,14 +60,14 @@ class TableSync::BatchPublisher < TableSync::BasePublisher
57
60
  {}
58
61
  end
59
62
 
60
- def attr_for_metadata
63
+ def attrs_for_metadata
61
64
  {}
62
65
  end
63
66
 
64
67
  def params
65
68
  {
66
69
  **super,
67
- headers: nil,
70
+ headers: headers,
68
71
  }
69
72
  end
70
73
 
@@ -80,10 +83,6 @@ class TableSync::BatchPublisher < TableSync::BasePublisher
80
83
  }
81
84
  end
82
85
 
83
- def event
84
- :update
85
- end
86
-
87
86
  def attributes_for_sync
88
87
  return original_attributes_array if push_original_attributes?
89
88
 
@@ -44,7 +44,7 @@ module TableSync
44
44
 
45
45
  # wrapper for proc-value, this wrapper receives all params (model, version, project_id...)
46
46
  # and filters them for proc-value
47
- unified_block = proc { |hash = {}| block.call(hash.slice(*params)) }
47
+ unified_block = proc { |hash = {}| block.call(**hash.slice(*params)) }
48
48
 
49
49
  # set wrapped proc-value as ivar value
50
50
  instance_variable_set(ivar, unified_block)
@@ -38,4 +38,26 @@ module TableSync
38
38
  MSG
39
39
  end
40
40
  end
41
+
42
+ # @api public
43
+ # @since 2.2.0
44
+ PluginError = Class.new(Error)
45
+
46
+ # @api public
47
+ # @since 2.2.0
48
+ class UnregisteredPluginError < PluginError
49
+ # @param plugin_name [Any]
50
+ def initialize(plugin_name)
51
+ super("#{plugin_name} plugin is not registered")
52
+ end
53
+ end
54
+
55
+ # @api public
56
+ # @since 2.2.0
57
+ class AlreadyRegisteredPluginError < PluginError
58
+ # @param plugin_name [Any]
59
+ def initialize(plugin_name)
60
+ super("#{plugin_name} plugin already exists")
61
+ end
62
+ end
41
63
  end
@@ -3,7 +3,7 @@
3
3
  module TableSync::Instrument
4
4
  module_function
5
5
 
6
- def notify(*args)
7
- TableSync.notifier&.notify(*args)
6
+ def notify(**args)
7
+ TableSync.notifier&.notify(**args)
8
8
  end
9
9
  end
@@ -115,7 +115,7 @@ module TableSync::Model
115
115
  end
116
116
 
117
117
  def row_to_hash(row)
118
- row.attributes.each_with_object({}) { |(k, v), o| o[k.to_sym] = v }
118
+ row.attributes.transform_keys(&:to_sym)
119
119
  end
120
120
  end
121
121
  end
@@ -20,7 +20,7 @@ module TableSync::ORMAdapter
20
20
  object.attributes
21
21
  end
22
22
 
23
- def setup_sync(klass, **opts)
23
+ def setup_sync(klass, opts)
24
24
  debounce_time = opts.delete(:debounce_time)
25
25
 
26
26
  klass.instance_exec do
@@ -20,7 +20,7 @@ module TableSync::ORMAdapter
20
20
  object.values
21
21
  end
22
22
 
23
- def setup_sync(klass, **opts)
23
+ def setup_sync(klass, opts)
24
24
  if_predicate = to_predicate(opts.delete(:if), true)
25
25
  unless_predicate = to_predicate(opts.delete(:unless), false)
26
26
  debounce_time = opts.delete(:debounce_time)
@@ -40,24 +40,21 @@ module TableSync::ORMAdapter
40
40
  end
41
41
 
42
42
  def register_callbacks(klass, if_predicate, unless_predicate, debounce_time)
43
- { create: :created, update: :updated }.each do |event, state|
43
+ { create: :created, update: :updated, destroy: :destroyed }.each do |event, state|
44
44
  klass.send(:define_method, :"after_#{event}") do
45
45
  if instance_eval(&if_predicate) && !instance_eval(&unless_predicate)
46
46
  db.after_commit do
47
- TableSync::Publisher.new(self.class.name, values,
48
- state: state, debounce_time: debounce_time).publish
47
+ TableSync::Publisher.new(
48
+ self.class.name,
49
+ values,
50
+ state: state,
51
+ debounce_time: debounce_time,
52
+ ).publish
49
53
  end
50
54
  end
51
- super()
52
- end
53
- end
54
55
 
55
- klass.send(:define_method, :after_destroy) do
56
- # publish anyway
57
- db.after_commit do
58
- TableSync::Publisher.new(self.class.name, values, state: :destroyed).publish
56
+ super()
59
57
  end
60
- super()
61
58
  end
62
59
  end
63
60
  end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api public
4
+ # @since 2.2.0
5
+ module TableSync::Plugins
6
+ require_relative "plugins/registry"
7
+ require_relative "plugins/access_mixin"
8
+ require_relative "plugins/abstract"
9
+
10
+ # @since 2.2.0
11
+ @plugin_registry = Registry.new
12
+ # @since 2.2.0
13
+ @access_lock = Mutex.new
14
+
15
+ class << self
16
+ # @param plugin_name [Symbol, String]
17
+ # @return [void]
18
+ #
19
+ # @api public
20
+ # @since 2.2.0
21
+ def load(plugin_name)
22
+ thread_safe { plugin_registry[plugin_name].load! }
23
+ end
24
+
25
+ # @return [Array<String>]
26
+ #
27
+ # @api public
28
+ # @since 2.2.0
29
+ def loaded_plugins
30
+ thread_safe { plugin_registry.loaded.keys }
31
+ end
32
+
33
+ # @return [Array<String>]
34
+ #
35
+ # @api public
36
+ # @since 2.2.0
37
+ def names
38
+ thread_safe { plugin_registry.names }
39
+ end
40
+
41
+ # @param plugin_name [Symbol, String]
42
+ # @return [void]
43
+ #
44
+ # @api private
45
+ # @since 2.2.0
46
+ def register_plugin(plugin_name, plugin_module)
47
+ thread_safe { plugin_registry[plugin_name] = plugin_module }
48
+ end
49
+
50
+ private
51
+
52
+ # @return [TableSync::Plugins::Registry]
53
+ #
54
+ # @api private
55
+ # @since 2.2.0
56
+ attr_reader :plugin_registry
57
+
58
+ # @return [Mutex]
59
+ #
60
+ # @api private
61
+ # @since 2.2.0
62
+ attr_reader :access_lock
63
+
64
+ # @return [void]
65
+ #
66
+ # @api private
67
+ # @since 2.2.0
68
+ def thread_safe
69
+ access_lock.synchronize { yield if block_given? }
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 2.2.0
5
+ class TableSync::Plugins::Abstract
6
+ class << self
7
+ # @param child_klass [Class]
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 2.2.0
12
+ def inherited(child_klass)
13
+ child_klass.instance_variable_set(:@__loaded__, false)
14
+ child_klass.instance_variable_set(:@__lock__, Mutex.new)
15
+ super
16
+ end
17
+
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 2.2.0
22
+ def load!
23
+ __thread_safe__ do
24
+ unless @__loaded__
25
+ @__loaded__ = true
26
+ install!
27
+ end
28
+ end
29
+ end
30
+
31
+ # @return [Boolean]
32
+ #
33
+ # @api private
34
+ # @since 2.2.0
35
+ def loaded?
36
+ __thread_safe__ { @__loaded__ }
37
+ end
38
+
39
+ private
40
+
41
+ # @return [void]
42
+ #
43
+ # @api private
44
+ # @since 2.2.0
45
+ def install!; end
46
+
47
+ # @return [Any]
48
+ #
49
+ # @api private
50
+ # @since 2.2.0
51
+ def __thread_safe__
52
+ @__lock__.synchronize { yield }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 2.2.0
5
+ module TableSync::Plugins::AccessMixin
6
+ # @param plugin_name [Symbol, String]
7
+ # @return [void]
8
+ #
9
+ # @see TableSync::Plugins
10
+ #
11
+ # @api public
12
+ # @since 2.2.0
13
+ def plugin(plugin_name)
14
+ TableSync::Plugins.load(plugin_name)
15
+ end
16
+ alias_method :enable, :plugin
17
+ alias_method :load, :plugin
18
+
19
+ # @return [Array<String>]
20
+ #
21
+ # @see TableSync::Plugins
22
+ #
23
+ # @api public
24
+ # @since 2.2.0
25
+ def plugins
26
+ TableSync::Plugins.names
27
+ end
28
+
29
+ # @return [Hash<String,Class<TableSync::Plugins::Abstract>>]
30
+ #
31
+ # @api private
32
+ # @since 2.2.0
33
+ def loaded_plugins
34
+ TableSync::Plugins.loaded_plugins
35
+ end
36
+ alias_method :enabled_plugins, :loaded_plugins
37
+
38
+ # @param plugin_name [String, Symbol]
39
+ # @param plugin_klass [Class<TableSync::Plugins::Abstract>]
40
+ # @return [void]
41
+ #
42
+ # @see TableSync::Plugins
43
+ #
44
+ # @api public
45
+ # @since 2.2.0
46
+ def register_plugin(plugin_name, plugin_klass)
47
+ TableSync::Plugins.register_plugin(plugin_name, plugin_klass)
48
+ end
49
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 2.2.0
5
+ class TableSync::Plugins::Registry
6
+ include Enumerable
7
+
8
+ # @return [void]
9
+ #
10
+ # @api private
11
+ # @since 2.2.0
12
+ def initialize
13
+ @plugin_set = {}
14
+ @access_lock = Mutex.new
15
+ end
16
+
17
+ # @param plugin_name [Symbol, String]
18
+ # @return [TableSync::Plugins::Abstract]
19
+ #
20
+ # @api private
21
+ # @since 2.2.0
22
+ def [](plugin_name)
23
+ thread_safe { fetch(plugin_name) }
24
+ end
25
+
26
+ # @param plugin_name [Symbol, String]
27
+ # @param plugin_module [TableSync::Plugins::Abstract]
28
+ # @return [void]
29
+ #
30
+ # @api private
31
+ # @since 2.2.0
32
+ def register(plugin_name, plugin_module)
33
+ thread_safe { apply(plugin_name, plugin_module) }
34
+ end
35
+ alias_method :[]=, :register
36
+
37
+ # @return [Array<String>]
38
+ #
39
+ # @api private
40
+ # @since 2.2.0
41
+ def names
42
+ thread_safe { plugin_names }
43
+ end
44
+
45
+ # @return [Hash<String,Class<TableSync::Plugins::Abstract>>]
46
+ #
47
+ # @api private
48
+ # @since 2.2.0
49
+ def loaded
50
+ thread_safe { loaded_plugins }
51
+ end
52
+
53
+ # @param block [Block]
54
+ # @return [Enumerable]
55
+ #
56
+ # @api private
57
+ # @since 2.2.0
58
+ def each(&block)
59
+ thread_safe { iterate(&block) }
60
+ end
61
+
62
+ private
63
+
64
+ # @return [Hash]
65
+ #
66
+ # @api private
67
+ # @since 2.2.0
68
+ attr_reader :plugin_set
69
+
70
+ # @return [Mutex]
71
+ #
72
+ # @api private
73
+ # @since 2.2.0
74
+ attr_reader :access_lock
75
+
76
+ # @return [void]
77
+ #
78
+ # @api private
79
+ # @since 2.2.0
80
+ def thread_safe
81
+ access_lock.synchronize { yield if block_given? }
82
+ end
83
+
84
+ # @return [Array<String>]
85
+ #
86
+ # @api private
87
+ # @since 2.2.0
88
+ def plugin_names
89
+ plugin_set.keys
90
+ end
91
+
92
+ # @param block [Block]
93
+ # @return [Enumerable]
94
+ #
95
+ # @api private
96
+ # @since 2.2.0
97
+ def iterate(&block)
98
+ block_given? ? plugin_set.each_pair(&block) : plugin_set.each_pair
99
+ end
100
+
101
+ # @param plugin_name [String]
102
+ # @return [Boolean]
103
+ #
104
+ # @api private
105
+ # @since 2.2.0
106
+ def registered?(plugin_name)
107
+ plugin_set.key?(plugin_name)
108
+ end
109
+
110
+ # @return [Array<TableSync::Plugins::Abstract>]
111
+ #
112
+ # @api private
113
+ # @since 2.2.0
114
+ def loaded_plugins
115
+ plugin_set.select { |_plugin_name, plugin_module| plugin_module.loaded? }
116
+ end
117
+
118
+ # @param plugin_name [Symbol, String]
119
+ # @param plugin_module [TableSync::Plugins::Abstract]
120
+ # @return [void]
121
+ #
122
+ # @raise [TableSync::AlreadyRegisteredPluginError]
123
+ #
124
+ # @api private
125
+ # @since 2.2.0
126
+ def apply(plugin_name, plugin_module)
127
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
128
+ raise(TableSync::AlreadyRegisteredPluginError.new(plugin_name)) if registered?(plugin_name)
129
+ plugin_set[plugin_name] = plugin_module
130
+ end
131
+
132
+ # @param plugin_name [Symbol, String]
133
+ # @return [TableSync::Plugins::Abstract]
134
+ #
135
+ # @raise [TableSync::UnregisteredPluginError]
136
+ #
137
+ # @api private
138
+ # @since 2.2.0
139
+ def fetch(plugin_name)
140
+ plugin_name = indifferently_accessible_plugin_name(plugin_name)
141
+ raise(TableSync::UnregisteredPluginError.new(plugin_name)) unless registered?(plugin_name)
142
+ plugin_set[plugin_name]
143
+ end
144
+
145
+ # @param key [Symbol, String]
146
+ # @return [String]
147
+ #
148
+ # @api private
149
+ # @since 2.2.0
150
+ def indifferently_accessible_plugin_name(plugin_name)
151
+ plugin_name.to_s
152
+ end
153
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TableSync
4
- VERSION = "1.13.0"
4
+ VERSION = "2.3.0"
5
5
  end
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
  require "table_sync/version"
6
6
 
7
7
  Gem::Specification.new do |spec|
8
- spec.required_ruby_version = ">= 2.3.8"
8
+ spec.required_ruby_version = ">= 2.5.6"
9
9
 
10
10
  spec.name = "table_sync"
11
11
  spec.version = TableSync::VERSION
@@ -32,11 +32,11 @@ Gem::Specification.new do |spec|
32
32
 
33
33
  spec.add_development_dependency "coveralls", "~> 0.8"
34
34
  spec.add_development_dependency "rspec", "~> 3.8"
35
- spec.add_development_dependency "rubocop-config-umbrellio", "~> 0.74"
35
+ spec.add_development_dependency "rubocop-config-umbrellio", "~> 0.81"
36
36
  spec.add_development_dependency "simplecov", "~> 0.16"
37
37
 
38
- spec.add_development_dependency "activejob", ">= 4.2.11"
39
- spec.add_development_dependency "activerecord"
38
+ spec.add_development_dependency "activejob", ">= 6.0"
39
+ spec.add_development_dependency "activerecord", ">= 6.0"
40
40
  spec.add_development_dependency "pg", "~> 0.18"
41
41
  spec.add_development_dependency "sequel"
42
42
  spec.add_development_dependency "timecop"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.13.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-02 00:00:00.000000000 Z
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: memery
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '0.74'
89
+ version: '0.81'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '0.74'
96
+ version: '0.81'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: simplecov
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -114,28 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 4.2.11
117
+ version: '6.0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: 4.2.11
124
+ version: '6.0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: activerecord
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: '6.0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: '6.0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: pg
141
141
  requirement: !ruby/object:Gem::Requirement
@@ -248,11 +248,13 @@ files:
248
248
  - ".travis.yml"
249
249
  - CHANGELOG.md
250
250
  - Gemfile
251
+ - Gemfile.lock
251
252
  - LICENSE.md
252
253
  - README.md
253
254
  - Rakefile
254
255
  - bin/console
255
256
  - bin/setup
257
+ - docs/development.md
256
258
  - docs/synopsis.md
257
259
  - lib/table_sync.rb
258
260
  - lib/table_sync/base_publisher.rb
@@ -275,6 +277,10 @@ files:
275
277
  - lib/table_sync/naming_resolver/sequel.rb
276
278
  - lib/table_sync/orm_adapter/active_record.rb
277
279
  - lib/table_sync/orm_adapter/sequel.rb
280
+ - lib/table_sync/plugins.rb
281
+ - lib/table_sync/plugins/abstract.rb
282
+ - lib/table_sync/plugins/access_mixin.rb
283
+ - lib/table_sync/plugins/registry.rb
278
284
  - lib/table_sync/publisher.rb
279
285
  - lib/table_sync/receiving_handler.rb
280
286
  - lib/table_sync/version.rb
@@ -292,14 +298,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
292
298
  requirements:
293
299
  - - ">="
294
300
  - !ruby/object:Gem::Version
295
- version: 2.3.8
301
+ version: 2.5.6
296
302
  required_rubygems_version: !ruby/object:Gem::Requirement
297
303
  requirements:
298
304
  - - ">="
299
305
  - !ruby/object:Gem::Version
300
306
  version: '0'
301
307
  requirements: []
302
- rubygems_version: 3.0.3
308
+ rubygems_version: 3.1.2
303
309
  signing_key:
304
310
  specification_version: 4
305
311
  summary: DB Table synchronization between microservices based on Model's event system