table_sync 1.8.0 → 1.9.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: cfa9b3d17de49a2591644329464d45ba1ddfc6b9a56c76db6eb6c061b439f3e4
4
- data.tar.gz: 7438f913929bd7eb6ae0b6e2d22fcb145b41a62d714aba7e989dcf2868bc7d70
3
+ metadata.gz: '079ab25e5512270ad9c1161f2a0f239fccb7954b5fbe56814605c39a72a87890'
4
+ data.tar.gz: 51b8c5718e91e03aaf7ce45421670999ef83ad7aaefea3961198a09f678149c2
5
5
  SHA512:
6
- metadata.gz: ed0babc48e2b1918ba4ae126215083182c6a3eadec3f79136b68322e2d2563ef02871b82aa86d5f310c77bc8303fc6a38042d35dfba95dab71b7bea653bfb658
7
- data.tar.gz: 11783a0f991fb7d3b39b18e820a82a3075e0f6690ab0bd0d1c5fcb229fa2a0090df673ceacc4e3ec05bc722a42f8657fdd376f18f8f715f27c838efdde5c357b
6
+ metadata.gz: fed258e3f7e24eed98df488c1b5d8ccef4732af5629001695c8053bcd239a46e52b79fef61d9febd627c7c44fe77b7d785f9f4b613aee8492161ec19f2d82288
7
+ data.tar.gz: baf41f7542804dadcdb2c29861bfe82724bdeb743c9b986cec943f0875b97568429c01c6afb4409e49b4f45680a0df5ea951d3bf5c06e874aed6d66a9ed16577
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [1.9.0] - 2019-07-23
5
+ ### Added
6
+ - add notifications
7
+
4
8
  ## [1.8.0] - 2019-07-23
5
9
  ### Added
6
10
  - `debounce_time` option for publishing
data/docs/synopsis.md CHANGED
@@ -80,6 +80,8 @@ TableSync.routing_metadata_callable = -> (klass, attributes) { attributes.slice(
80
80
  - `TableSync.exchange_name` defines the exchange name used for publishing (optional, falls back
81
81
  to default Rabbit gem configuration).
82
82
 
83
+ - `TableSync.notifier` is a module that provides publish and recieve notifications.
84
+
83
85
  # Manual publishing
84
86
 
85
87
  `TableSync::Publisher.new(object_class, original_attributes, confirm: true, state: :updated, debounce_time: 45)`
@@ -251,5 +253,49 @@ You can set callbacks like this:
251
253
  before_commit on: event, &block
252
254
  after_commit on: event, &block
253
255
  ```
254
- TableSync performs this callbacks after transaction commit as to avoid side effects. Block receives array of
255
- record attributes.
256
+ TableSync performs this callbacks after transaction commit as to avoid side effects. Block receives array of record attributes.
257
+
258
+ ### Notifications
259
+
260
+ #### ActiveSupport adapter
261
+
262
+ You can use an already existing ActiveSupport adapter:
263
+ ```ruby
264
+ TableSync.notifier = TableSync::InstrumentAdapter::ActiveSupport
265
+ ```
266
+
267
+ This instrumentation API is provided by Active Support. It allows to subscribe to notifications:
268
+
269
+ ```ruby
270
+ ActiveSupport::Notifications.subscribe(/tablesync/) do |name, start, finish, id, payload|
271
+ # do something
272
+ end
273
+ ```
274
+
275
+ Types of events available:
276
+ `"tablesync.receive.update"`, `"tablesync.receive.destroy"`, `"tablesync.publish.update"`
277
+ and `"tablesync.publish.destroy"`.
278
+
279
+ You have access to the payload, which contains `event`, `direction`, `table` and `count`.
280
+
281
+ ```
282
+ {
283
+ :event => :update, # one of update / destroy
284
+ :direction => :publish, # one of publish / receive
285
+ :table => "users",
286
+ :count => 1
287
+ }
288
+ ```
289
+
290
+ See more at https://guides.rubyonrails.org/active_support_instrumentation.html
291
+
292
+
293
+ #### Custom adapters
294
+
295
+ You can also create a custom adapter. It is expected to respond to the following method:
296
+
297
+ ```ruby
298
+ def notify(table:, event:, direction:, count:)
299
+ # processes data about table_sync event
300
+ end
301
+ ```
@@ -17,8 +17,10 @@ class TableSync::BatchPublisher < TableSync::BasePublisher
17
17
 
18
18
  def publish_now
19
19
  return unless need_publish?
20
-
21
20
  Rabbit.publish(params)
21
+
22
+ TableSync::Instrument.notify table: TableSync.orm.table_name(object_class), event: event,
23
+ count: publishing_data[:attributes].size, direction: :publish
22
24
  end
23
25
 
24
26
  private
@@ -71,11 +73,15 @@ class TableSync::BatchPublisher < TableSync::BasePublisher
71
73
  def publishing_data
72
74
  {
73
75
  **super,
74
- event: :update,
76
+ event: event,
75
77
  metadata: {},
76
78
  }
77
79
  end
78
80
 
81
+ def event
82
+ :update
83
+ end
84
+
79
85
  def attributes_for_sync
80
86
  return original_attributes_array if push_original_attributes?
81
87
 
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TableSync::Instrument
4
+ module_function
5
+
6
+ def notify(*args)
7
+ TableSync.notifier&.notify(*args)
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TableSync::InstrumentAdapter
4
+ module ActiveSupport
5
+ module_function
6
+
7
+ def notify(table:, event:, direction:, count: 1)
8
+ ::ActiveSupport::Notifications.instrument "tablesync.#{direction}.#{event}",
9
+ count: count,
10
+ table: table.to_s,
11
+ event: event,
12
+ direction: direction
13
+ end
14
+ end
15
+ end
@@ -53,7 +53,7 @@ module TableSync::Model
53
53
  def upsert(data:, target_keys:, version_key:, first_sync_time_key:, default_values:)
54
54
  data = Array.wrap(data)
55
55
 
56
- transaction do
56
+ result = transaction do
57
57
  data.map do |datum|
58
58
  conditions = datum.select { |k| target_keys.include?(k) }
59
59
 
@@ -71,13 +71,25 @@ module TableSync::Model
71
71
  row_to_hash(row)
72
72
  end.compact
73
73
  end
74
+
75
+ TableSync::Instrument.notify(
76
+ table: table_name, event: :update, count: result.count, direction: :receive,
77
+ )
78
+
79
+ result
74
80
  end
75
81
 
76
82
  def destroy(data)
77
- transaction do
83
+ result = transaction do
78
84
  row = raw_model.lock("FOR UPDATE").find_by(data)&.destroy!
79
85
  [row_to_hash(row)]
80
86
  end
87
+
88
+ TableSync::Instrument.notify(
89
+ table: table_name, event: :destroy, count: result.count, direction: :receive,
90
+ )
91
+
92
+ result
81
93
  end
82
94
 
83
95
  def transaction(&block)
@@ -99,6 +111,10 @@ module TableSync::Model
99
111
  { schema: schema, name: name }
100
112
  end
101
113
 
114
+ def table_name
115
+ table_info[:name]
116
+ end
117
+
102
118
  def db
103
119
  @raw_model.connection
104
120
  end
@@ -28,17 +28,24 @@ module TableSync::Model
28
28
  insert_data.each { |datum| datum[first_sync_time_key] = Time.current }
29
29
  end
30
30
 
31
- dataset.returning
32
- .insert_conflict(
33
- target: target_keys,
34
- update: upd_spec,
35
- update_where: version_condition,
36
- )
37
- .multi_insert(insert_data)
31
+ result = dataset.returning
32
+ .insert_conflict(
33
+ target: target_keys,
34
+ update: upd_spec,
35
+ update_where: version_condition,
36
+ )
37
+ .multi_insert(insert_data)
38
+
39
+ TableSync::Instrument.notify table: table_name, count: result.count,
40
+ event: :update, direction: :receive
41
+ result
38
42
  end
39
43
 
40
44
  def destroy(data)
41
- dataset.returning.where(data).delete
45
+ result = dataset.returning.where(data).delete
46
+ TableSync::Instrument.notify table: table_name, count: result.count,
47
+ event: :destroy, direction: :receive
48
+ result
42
49
  end
43
50
 
44
51
  def transaction(&block)
@@ -16,6 +16,10 @@ module TableSync::ORMAdapter
16
16
  object.attributes
17
17
  end
18
18
 
19
+ def table_name(object)
20
+ object.table_name
21
+ end
22
+
19
23
  def setup_sync(klass, **opts)
20
24
  debounce_time = opts.delete(:debounce_time)
21
25
 
@@ -16,6 +16,10 @@ module TableSync::ORMAdapter
16
16
  object.values
17
17
  end
18
18
 
19
+ def table_name(object)
20
+ object.table_name
21
+ end
22
+
19
23
  def setup_sync(klass, **opts)
20
24
  if_predicate = to_predicate(opts.delete(:if), true)
21
25
  unless_predicate = to_predicate(opts.delete(:unless), false)
@@ -34,6 +34,8 @@ class TableSync::Publisher < TableSync::BasePublisher
34
34
  return if !object && !destroyed?
35
35
 
36
36
  Rabbit.publish(params)
37
+ TableSync::Instrument.notify table: TableSync.orm.table_name(object_class),
38
+ event: event, direction: :publish
37
39
  end
38
40
 
39
41
  private
@@ -77,7 +79,7 @@ class TableSync::Publisher < TableSync::BasePublisher
77
79
  def publishing_data
78
80
  {
79
81
  **super,
80
- event: (destroyed? ? :destroy : :update),
82
+ event: event,
81
83
  metadata: { created: created? },
82
84
  }
83
85
  end
@@ -100,6 +102,10 @@ class TableSync::Publisher < TableSync::BasePublisher
100
102
  TableSync.orm.find(object_class, needle)
101
103
  end
102
104
 
105
+ def event
106
+ destroyed? ? :destroy : :update
107
+ end
108
+
103
109
  def needle
104
110
  original_attributes.slice(*primary_keys)
105
111
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TableSync
4
- VERSION = "1.8.0"
4
+ VERSION = "1.9.0"
5
5
  end
data/lib/table_sync.rb CHANGED
@@ -22,6 +22,8 @@ module TableSync
22
22
  require_relative "./table_sync/orm_adapter/sequel"
23
23
  require_relative "./table_sync/model/active_record"
24
24
  require_relative "./table_sync/model/sequel"
25
+ require_relative "./table_sync/instrument"
26
+ require_relative "./table_sync/instrument_adapter/active_support"
25
27
 
26
28
  class << self
27
29
  include Memery
@@ -31,6 +33,7 @@ module TableSync
31
33
  attr_accessor :routing_key_callable
32
34
  attr_accessor :exchange_name
33
35
  attr_accessor :routing_metadata_callable
36
+ attr_accessor :notifier
34
37
 
35
38
  def sync(*args)
36
39
  orm.setup_sync(*args)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: table_sync
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
@@ -263,6 +263,8 @@ files:
263
263
  - lib/table_sync/dsl.rb
264
264
  - lib/table_sync/errors.rb
265
265
  - lib/table_sync/event_actions.rb
266
+ - lib/table_sync/instrument.rb
267
+ - lib/table_sync/instrument_adapter/active_support.rb
266
268
  - lib/table_sync/model/active_record.rb
267
269
  - lib/table_sync/model/sequel.rb
268
270
  - lib/table_sync/orm_adapter/active_record.rb