table_sync 5.1.0 → 6.0

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/Gemfile.lock +3 -3
  4. data/README.md +3 -0
  5. data/docs/publishing/configuration.md +143 -0
  6. data/docs/publishing/manual.md +155 -0
  7. data/docs/publishing/publishers.md +162 -0
  8. data/docs/publishing.md +35 -105
  9. data/lib/table_sync/errors.rb +31 -22
  10. data/lib/table_sync/event.rb +35 -0
  11. data/lib/table_sync/orm_adapter/active_record.rb +25 -0
  12. data/lib/table_sync/orm_adapter/base.rb +92 -0
  13. data/lib/table_sync/orm_adapter/sequel.rb +29 -0
  14. data/lib/table_sync/publishing/batch.rb +53 -0
  15. data/lib/table_sync/publishing/data/objects.rb +50 -0
  16. data/lib/table_sync/publishing/data/raw.rb +27 -0
  17. data/lib/table_sync/publishing/helpers/attributes.rb +63 -0
  18. data/lib/table_sync/publishing/helpers/debounce.rb +134 -0
  19. data/lib/table_sync/publishing/helpers/objects.rb +39 -0
  20. data/lib/table_sync/publishing/message/base.rb +73 -0
  21. data/lib/table_sync/publishing/message/batch.rb +14 -0
  22. data/lib/table_sync/publishing/message/raw.rb +54 -0
  23. data/lib/table_sync/publishing/message/single.rb +13 -0
  24. data/lib/table_sync/publishing/params/base.rb +66 -0
  25. data/lib/table_sync/publishing/params/batch.rb +23 -0
  26. data/lib/table_sync/publishing/params/raw.rb +7 -0
  27. data/lib/table_sync/publishing/params/single.rb +31 -0
  28. data/lib/table_sync/publishing/raw.rb +21 -0
  29. data/lib/table_sync/publishing/single.rb +65 -0
  30. data/lib/table_sync/publishing.rb +20 -5
  31. data/lib/table_sync/receiving/config.rb +6 -4
  32. data/lib/table_sync/receiving/handler.rb +10 -6
  33. data/lib/table_sync/receiving.rb +0 -2
  34. data/lib/table_sync/setup/active_record.rb +22 -0
  35. data/lib/table_sync/setup/base.rb +67 -0
  36. data/lib/table_sync/setup/sequel.rb +26 -0
  37. data/lib/table_sync/version.rb +1 -1
  38. data/lib/table_sync.rb +31 -8
  39. metadata +28 -7
  40. data/lib/table_sync/publishing/base_publisher.rb +0 -110
  41. data/lib/table_sync/publishing/batch_publisher.rb +0 -109
  42. data/lib/table_sync/publishing/orm_adapter/active_record.rb +0 -32
  43. data/lib/table_sync/publishing/orm_adapter/sequel.rb +0 -57
  44. data/lib/table_sync/publishing/publisher.rb +0 -129
@@ -0,0 +1,67 @@
1
+ # frozen-string_literal: true
2
+
3
+ module TableSync::Setup
4
+ class Base
5
+ include Tainbox
6
+
7
+ EVENTS = %i[create update destroy].freeze
8
+ INVALID_EVENT = Class.new(StandardError)
9
+ INVALID_CONDITION = Class.new(StandardError)
10
+
11
+ attribute :object_class
12
+ attribute :debounce_time
13
+ attribute :on
14
+ attribute :if_condition
15
+ attribute :unless_condition
16
+
17
+ def initialize(attrs)
18
+ super(attrs)
19
+
20
+ self.on = Array.wrap(on).map(&:to_sym)
21
+
22
+ self.if_condition ||= proc { true }
23
+ self.unless_condition ||= proc { false }
24
+
25
+ raise INVALID_EVENTS unless valid_events?
26
+ raise INVALID_CONDITION unless valid_conditions?
27
+ end
28
+
29
+ def register_callbacks
30
+ applicable_events.each { |event| define_after_commit(event) }
31
+ end
32
+
33
+ private
34
+
35
+ # VALIDATION
36
+
37
+ def valid_events?
38
+ on.all? { |event| event.in?(EVENTS) }
39
+ end
40
+
41
+ def valid_conditions?
42
+ if_condition.is_a?(Proc) && unless_condition.is_a?(Proc)
43
+ end
44
+
45
+ # EVENTS
46
+
47
+ def applicable_events
48
+ on.presence || EVENTS
49
+ end
50
+
51
+ # CREATING HOOKS
52
+
53
+ # :nocov:
54
+ def define_after_commit(event)
55
+ raise NotImplementedError
56
+ end
57
+ # :nocov:
58
+
59
+ def options_exposed_for_block
60
+ {
61
+ if: if_condition,
62
+ unless: unless_condition,
63
+ debounce_time: debounce_time,
64
+ }
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,26 @@
1
+ # frozen-string_literal: true
2
+
3
+ module TableSync::Setup
4
+ class Sequel < Base
5
+ private
6
+
7
+ def define_after_commit(event)
8
+ options = options_exposed_for_block
9
+
10
+ object_class.define_method("after_#{event}".to_sym) do
11
+ if instance_eval(&options[:if]) && !instance_eval(&options[:unless])
12
+ db.after_commit do
13
+ TableSync::Publishing::Single.new(
14
+ object_class: self.class.name,
15
+ original_attributes: values,
16
+ event: event,
17
+ debounce_time: options[:debounce_time],
18
+ ).publish_later
19
+ end
20
+ end
21
+
22
+ super()
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module TableSync
4
- VERSION = "5.1.0"
4
+ VERSION = "6.0"
5
5
  end
data/lib/table_sync.rb CHANGED
@@ -8,39 +8,62 @@ require "active_support/core_ext/object/blank"
8
8
  require "active_support/core_ext/numeric/time"
9
9
 
10
10
  module TableSync
11
+ require_relative "table_sync/event"
11
12
  require_relative "table_sync/utils"
12
13
  require_relative "table_sync/version"
13
14
  require_relative "table_sync/errors"
15
+
14
16
  require_relative "table_sync/instrument"
15
17
  require_relative "table_sync/instrument_adapter/active_support"
18
+
16
19
  require_relative "table_sync/naming_resolver/active_record"
17
20
  require_relative "table_sync/naming_resolver/sequel"
21
+
22
+ require_relative "table_sync/orm_adapter/base"
23
+ require_relative "table_sync/orm_adapter/active_record"
24
+ require_relative "table_sync/orm_adapter/sequel"
25
+
18
26
  require_relative "table_sync/receiving"
19
27
  require_relative "table_sync/publishing"
20
28
 
29
+ require_relative "table_sync/setup/base"
30
+ require_relative "table_sync/setup/active_record"
31
+ require_relative "table_sync/setup/sequel"
32
+
21
33
  class << self
22
- attr_accessor :publishing_job_class_callable
34
+ attr_accessor :raise_on_empty_message
35
+ attr_accessor :single_publishing_job_class_callable
23
36
  attr_accessor :batch_publishing_job_class_callable
24
37
  attr_accessor :routing_key_callable
25
38
  attr_accessor :exchange_name
26
- attr_accessor :routing_metadata_callable
39
+ attr_accessor :headers_callable
27
40
  attr_accessor :notifier
41
+
28
42
  attr_reader :orm
29
43
  attr_reader :publishing_adapter
30
44
  attr_reader :receiving_model
45
+ attr_reader :setup
31
46
 
32
- def sync(klass, **opts)
33
- publishing_adapter.setup_sync(klass, opts)
47
+ def sync(object_class, **options)
48
+ setup.new(
49
+ object_class: object_class,
50
+ on: options[:on],
51
+ if_condition: options[:if],
52
+ unless_condition: options[:unless],
53
+ debounce_time: options[:debounce_time],
54
+ ).register_callbacks
34
55
  end
35
56
 
36
57
  def orm=(val)
37
58
  case val
38
59
  when :active_record
39
- @publishing_adapter = Publishing::ORMAdapter::ActiveRecord
40
- @receiving_model = Receiving::Model::ActiveRecord
60
+ @publishing_adapter = TableSync::ORMAdapter::ActiveRecord
61
+ @receiving_model = Receiving::Model::ActiveRecord
62
+ @setup = TableSync::Setup::ActiveRecord
41
63
  when :sequel
42
- @publishing_adapter = Publishing::ORMAdapter::Sequel
43
- @receiving_model = Receiving::Model::Sequel
64
+ @publishing_adapter = TableSync::ORMAdapter::Sequel
65
+ @receiving_model = Receiving::Model::Sequel
66
+ @setup = TableSync::Setup::Sequel
44
67
  else
45
68
  raise ORMNotSupported.new(val.inspect)
46
69
  end
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: 5.1.0
4
+ version: '6.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umbrellio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-09 00:00:00.000000000 Z
11
+ date: 2021-10-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: memery
@@ -271,19 +271,37 @@ files:
271
271
  - docs/message_protocol.md
272
272
  - docs/notifications.md
273
273
  - docs/publishing.md
274
+ - docs/publishing/configuration.md
275
+ - docs/publishing/manual.md
276
+ - docs/publishing/publishers.md
274
277
  - docs/receiving.md
275
278
  - lib/table_sync.rb
276
279
  - lib/table_sync/errors.rb
280
+ - lib/table_sync/event.rb
277
281
  - lib/table_sync/instrument.rb
278
282
  - lib/table_sync/instrument_adapter/active_support.rb
279
283
  - lib/table_sync/naming_resolver/active_record.rb
280
284
  - lib/table_sync/naming_resolver/sequel.rb
285
+ - lib/table_sync/orm_adapter/active_record.rb
286
+ - lib/table_sync/orm_adapter/base.rb
287
+ - lib/table_sync/orm_adapter/sequel.rb
281
288
  - lib/table_sync/publishing.rb
282
- - lib/table_sync/publishing/base_publisher.rb
283
- - lib/table_sync/publishing/batch_publisher.rb
284
- - lib/table_sync/publishing/orm_adapter/active_record.rb
285
- - lib/table_sync/publishing/orm_adapter/sequel.rb
286
- - lib/table_sync/publishing/publisher.rb
289
+ - lib/table_sync/publishing/batch.rb
290
+ - lib/table_sync/publishing/data/objects.rb
291
+ - lib/table_sync/publishing/data/raw.rb
292
+ - lib/table_sync/publishing/helpers/attributes.rb
293
+ - lib/table_sync/publishing/helpers/debounce.rb
294
+ - lib/table_sync/publishing/helpers/objects.rb
295
+ - lib/table_sync/publishing/message/base.rb
296
+ - lib/table_sync/publishing/message/batch.rb
297
+ - lib/table_sync/publishing/message/raw.rb
298
+ - lib/table_sync/publishing/message/single.rb
299
+ - lib/table_sync/publishing/params/base.rb
300
+ - lib/table_sync/publishing/params/batch.rb
301
+ - lib/table_sync/publishing/params/raw.rb
302
+ - lib/table_sync/publishing/params/single.rb
303
+ - lib/table_sync/publishing/raw.rb
304
+ - lib/table_sync/publishing/single.rb
287
305
  - lib/table_sync/receiving.rb
288
306
  - lib/table_sync/receiving/config.rb
289
307
  - lib/table_sync/receiving/config_decorator.rb
@@ -291,6 +309,9 @@ files:
291
309
  - lib/table_sync/receiving/handler.rb
292
310
  - lib/table_sync/receiving/model/active_record.rb
293
311
  - lib/table_sync/receiving/model/sequel.rb
312
+ - lib/table_sync/setup/active_record.rb
313
+ - lib/table_sync/setup/base.rb
314
+ - lib/table_sync/setup/sequel.rb
294
315
  - lib/table_sync/utils.rb
295
316
  - lib/table_sync/utils/interface_checker.rb
296
317
  - lib/table_sync/utils/proc_array.rb
@@ -1,110 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TableSync::Publishing::BasePublisher
4
- include Memery
5
-
6
- BASE_SAFE_JSON_TYPES = [NilClass, String, TrueClass, FalseClass, Numeric, Symbol].freeze
7
- NOT_MAPPED = Object.new
8
-
9
- private
10
-
11
- attr_accessor :object_class
12
-
13
- # @!method job_callable
14
- # @!method job_callable_error_message
15
- # @!method attrs_for_callables
16
- # @!method attrs_for_routing_key
17
- # @!method attrs_for_metadata
18
- # @!method attributes_for_sync
19
-
20
- memoize def current_time
21
- Time.current
22
- end
23
-
24
- memoize def primary_keys
25
- Array(object_class.primary_key).map(&:to_sym)
26
- end
27
-
28
- memoize def attributes_for_sync_defined?
29
- object_class.method_defined?(:attributes_for_sync)
30
- end
31
-
32
- def resolve_routing_key
33
- routing_key_callable.call(object_class.name, attrs_for_routing_key)
34
- end
35
-
36
- def metadata
37
- TableSync.routing_metadata_callable&.call(object_class.name, attrs_for_metadata)
38
- end
39
-
40
- def confirm?
41
- @confirm
42
- end
43
-
44
- def routing_key_callable
45
- return TableSync.routing_key_callable if TableSync.routing_key_callable
46
- raise "Can't publish, set TableSync.routing_key_callable"
47
- end
48
-
49
- def filter_safe_for_serialization(object)
50
- case object
51
- when Array
52
- object.each_with_object([]) do |value, memo|
53
- value = filter_safe_for_serialization(value)
54
- memo << value if object_mapped?(value)
55
- end
56
- when Hash
57
- object.each_with_object({}) do |(key, value), memo|
58
- key = filter_safe_for_serialization(key)
59
- value = filter_safe_hash_values(value)
60
- memo[key] = value if object_mapped?(key) && object_mapped?(value)
61
- end
62
- when Float::INFINITY
63
- NOT_MAPPED
64
- when *BASE_SAFE_JSON_TYPES
65
- object
66
- else # rubocop:disable Lint/DuplicateBranch
67
- NOT_MAPPED
68
- end
69
- end
70
-
71
- def filter_safe_hash_values(value)
72
- case value
73
- when Symbol
74
- value.to_s
75
- else
76
- filter_safe_for_serialization(value)
77
- end
78
- end
79
-
80
- def object_mapped?(object)
81
- object != NOT_MAPPED
82
- end
83
-
84
- def job_class
85
- job_callable ? job_callable.call : raise(job_callable_error_message)
86
- end
87
-
88
- def publishing_data
89
- {
90
- model: object_class.try(:table_sync_model_name) || object_class.name,
91
- attributes: attributes_for_sync,
92
- version: current_time.to_f,
93
- }
94
- end
95
-
96
- def params
97
- params = {
98
- event: :table_sync,
99
- data: publishing_data,
100
- confirm_select: confirm?,
101
- routing_key: routing_key,
102
- realtime: true,
103
- headers: metadata,
104
- }
105
-
106
- params[:exchange_name] = TableSync.exchange_name if TableSync.exchange_name
107
-
108
- params
109
- end
110
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TableSync::Publishing::BatchPublisher < TableSync::Publishing::BasePublisher
4
- def initialize(object_class, original_attributes_array, **options)
5
- @original_attributes_array = original_attributes_array.map do |hash|
6
- filter_safe_for_serialization(hash.deep_symbolize_keys)
7
- end
8
-
9
- @object_class = object_class.constantize
10
- @confirm = options[:confirm] || true
11
- @routing_key = options[:routing_key] || resolve_routing_key
12
- @push_original_attributes = options[:push_original_attributes] || false
13
- @headers = options[:headers]
14
- @event = options[:event] || :update
15
- end
16
-
17
- def publish
18
- enqueue_job
19
- end
20
-
21
- def publish_now
22
- return unless need_publish?
23
- Rabbit.publish(params)
24
-
25
- model_naming = TableSync.publishing_adapter.model_naming(object_class)
26
- TableSync::Instrument.notify table: model_naming.table, schema: model_naming.schema,
27
- event: event,
28
- count: publishing_data[:attributes].size, direction: :publish
29
- end
30
-
31
- private
32
-
33
- attr_reader :original_attributes_array, :routing_key, :headers, :event
34
-
35
- def push_original_attributes?
36
- @push_original_attributes
37
- end
38
-
39
- def need_publish?
40
- (push_original_attributes? && original_attributes_array.present?) || objects.present?
41
- end
42
-
43
- memoize def objects
44
- needles.map { |needle| TableSync.publishing_adapter.find(object_class, needle) }.compact
45
- end
46
-
47
- def job_callable
48
- TableSync.batch_publishing_job_class_callable
49
- end
50
-
51
- def job_callable_error_message
52
- "Can't publish, set TableSync.batch_publishing_job_class_callable"
53
- end
54
-
55
- def attrs_for_callables
56
- {}
57
- end
58
-
59
- def attrs_for_routing_key
60
- {}
61
- end
62
-
63
- def attrs_for_metadata
64
- {}
65
- end
66
-
67
- def params
68
- {
69
- **super,
70
- headers: headers,
71
- }
72
- end
73
-
74
- def needles
75
- original_attributes_array.map { |original_attributes| original_attributes.slice(*primary_keys) }
76
- end
77
-
78
- def publishing_data
79
- {
80
- **super,
81
- event: event,
82
- metadata: {},
83
- }
84
- end
85
-
86
- def attributes_for_sync
87
- return original_attributes_array if push_original_attributes?
88
-
89
- objects.map do |object|
90
- if attributes_for_sync_defined?
91
- object.attributes_for_sync
92
- else
93
- TableSync.publishing_adapter.attributes(object)
94
- end
95
- end
96
- end
97
-
98
- def enqueue_job
99
- job_class.perform_later(
100
- object_class.name,
101
- original_attributes_array,
102
- enqueue_additional_options,
103
- )
104
- end
105
-
106
- def enqueue_additional_options
107
- { confirm: confirm?, push_original_attributes: push_original_attributes? }
108
- end
109
- end
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TableSync::Publishing::ORMAdapter
4
- module ActiveRecord
5
- module_function
6
-
7
- def model_naming(object)
8
- ::TableSync::NamingResolver::ActiveRecord.new(table_name: object.table_name)
9
- end
10
-
11
- def find(dataset, conditions)
12
- dataset.find_by(conditions)
13
- end
14
-
15
- def attributes(object)
16
- object.attributes
17
- end
18
-
19
- def setup_sync(klass, opts)
20
- debounce_time = opts.delete(:debounce_time)
21
-
22
- klass.instance_exec do
23
- { create: :created, update: :updated, destroy: :destroyed }.each do |event, state|
24
- after_commit(on: event, **opts) do
25
- TableSync::Publishing::Publisher.new(self.class.name, attributes,
26
- state: state, debounce_time: debounce_time).publish
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end
@@ -1,57 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module TableSync::Publishing::ORMAdapter
4
- module Sequel
5
- module_function
6
-
7
- def model_naming(object)
8
- ::TableSync::NamingResolver::Sequel.new(table_name: object.table_name, db: object.db)
9
- end
10
-
11
- def find(dataset, conditions)
12
- dataset.find(conditions)
13
- end
14
-
15
- def attributes(object)
16
- object.values
17
- end
18
-
19
- def setup_sync(klass, opts)
20
- if_predicate = to_predicate(opts.delete(:if), true)
21
- unless_predicate = to_predicate(opts.delete(:unless), false)
22
- debounce_time = opts.delete(:debounce_time)
23
-
24
- if opts.any?
25
- raise "Only :if, :skip_debounce and :unless options are currently " \
26
- "supported for Sequel hooks"
27
- end
28
-
29
- register_callbacks(klass, if_predicate, unless_predicate, debounce_time)
30
- end
31
-
32
- def to_predicate(val, default)
33
- return val.to_proc if val.respond_to?(:to_proc)
34
-
35
- -> (*) { default }
36
- end
37
-
38
- def register_callbacks(klass, if_predicate, unless_predicate, debounce_time)
39
- { create: :created, update: :updated, destroy: :destroyed }.each do |event, state|
40
- klass.send(:define_method, :"after_#{event}") do
41
- if instance_eval(&if_predicate) && !instance_eval(&unless_predicate)
42
- db.after_commit do
43
- TableSync::Publishing::Publisher.new(
44
- self.class.name,
45
- values,
46
- state: state,
47
- debounce_time: debounce_time,
48
- ).publish
49
- end
50
- end
51
-
52
- super()
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,129 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TableSync::Publishing::Publisher < TableSync::Publishing::BasePublisher
4
- DEBOUNCE_TIME = 1.minute
5
-
6
- # 'original_attributes' are not published, they are used to resolve the routing key
7
- def initialize(object_class, original_attributes, **opts)
8
- @object_class = object_class.constantize
9
- @original_attributes = filter_safe_for_serialization(original_attributes.deep_symbolize_keys)
10
- @confirm = opts.fetch(:confirm, true)
11
- @debounce_time = opts[:debounce_time]&.seconds || DEBOUNCE_TIME
12
- @state = opts.fetch(:state, :updated).to_sym
13
- validate_state
14
- end
15
-
16
- def publish
17
- return enqueue_job if destroyed? || debounce_time.zero?
18
-
19
- sync_time = Rails.cache.read(cache_key) || current_time - debounce_time - 1.second
20
- return if sync_time > current_time
21
-
22
- next_sync_time = sync_time + debounce_time
23
- next_sync_time <= current_time ? enqueue_job : enqueue_job(next_sync_time)
24
- end
25
-
26
- def publish_now
27
- # Update request and object does not exist -> skip publishing
28
- return if !object && !destroyed?
29
-
30
- Rabbit.publish(params)
31
- model_naming = TableSync.publishing_adapter.model_naming(object_class)
32
- TableSync::Instrument.notify table: model_naming.table, schema: model_naming.schema,
33
- event: event, direction: :publish
34
- end
35
-
36
- private
37
-
38
- attr_reader :original_attributes
39
- attr_reader :state
40
- attr_reader :debounce_time
41
-
42
- def attrs_for_callables
43
- attributes_for_sync
44
- end
45
-
46
- def attrs_for_routing_key
47
- if object.respond_to?(:attrs_for_routing_key)
48
- object.attrs_for_routing_key
49
- else
50
- attrs_for_callables
51
- end
52
- end
53
-
54
- def attrs_for_metadata
55
- if object.respond_to?(:attrs_for_metadata)
56
- object.attrs_for_metadata
57
- else
58
- attrs_for_callables
59
- end
60
- end
61
-
62
- def job_callable
63
- TableSync.publishing_job_class_callable
64
- end
65
-
66
- def job_callable_error_message
67
- "Can't publish, set TableSync.publishing_job_class_callable"
68
- end
69
-
70
- def enqueue_job(perform_at = current_time)
71
- job = job_class.set(wait_until: perform_at)
72
- job.perform_later(object_class.name, original_attributes, state: state.to_s, confirm: confirm?)
73
- Rails.cache.write(cache_key, perform_at)
74
- end
75
-
76
- def routing_key
77
- resolve_routing_key
78
- end
79
-
80
- def publishing_data
81
- {
82
- **super,
83
- event: event,
84
- metadata: { created: created? },
85
- }
86
- end
87
-
88
- memoize def attributes_for_sync
89
- if destroyed?
90
- if object_class.respond_to?(:table_sync_destroy_attributes)
91
- object_class.table_sync_destroy_attributes(original_attributes)
92
- else
93
- original_attributes
94
- end
95
- elsif attributes_for_sync_defined?
96
- object.attributes_for_sync
97
- else
98
- TableSync.publishing_adapter.attributes(object)
99
- end
100
- end
101
-
102
- memoize def object
103
- TableSync.publishing_adapter.find(object_class, needle)
104
- end
105
-
106
- def event
107
- destroyed? ? :destroy : :update
108
- end
109
-
110
- def needle
111
- original_attributes.slice(*primary_keys)
112
- end
113
-
114
- def cache_key
115
- "#{object_class}/#{needle}_table_sync_time".delete(" ")
116
- end
117
-
118
- def destroyed?
119
- state == :destroyed
120
- end
121
-
122
- def created?
123
- state == :created
124
- end
125
-
126
- def validate_state
127
- raise "Unknown state: #{state.inspect}" unless %i[created updated destroyed].include?(state)
128
- end
129
- end