table_sync 2.3.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +21 -0
  3. data/CHANGELOG.md +57 -0
  4. data/Gemfile.lock +85 -80
  5. data/README.md +4 -2
  6. data/docs/message_protocol.md +24 -0
  7. data/docs/notifications.md +45 -0
  8. data/docs/publishing.md +147 -0
  9. data/docs/receiving.md +341 -0
  10. data/lib/table_sync.rb +16 -31
  11. data/lib/table_sync/errors.rb +39 -23
  12. data/lib/table_sync/publishing.rb +11 -0
  13. data/lib/table_sync/{base_publisher.rb → publishing/base_publisher.rb} +1 -1
  14. data/lib/table_sync/{batch_publisher.rb → publishing/batch_publisher.rb} +4 -4
  15. data/lib/table_sync/{orm_adapter → publishing/orm_adapter}/active_record.rb +3 -7
  16. data/lib/table_sync/{orm_adapter → publishing/orm_adapter}/sequel.rb +2 -6
  17. data/lib/table_sync/{publisher.rb → publishing/publisher.rb} +4 -4
  18. data/lib/table_sync/receiving.rb +14 -0
  19. data/lib/table_sync/receiving/config.rb +218 -0
  20. data/lib/table_sync/receiving/config_decorator.rb +27 -0
  21. data/lib/table_sync/receiving/dsl.rb +28 -0
  22. data/lib/table_sync/receiving/handler.rb +136 -0
  23. data/lib/table_sync/{model → receiving/model}/active_record.rb +43 -36
  24. data/lib/table_sync/receiving/model/sequel.rb +83 -0
  25. data/lib/table_sync/utils.rb +9 -0
  26. data/lib/table_sync/utils/interface_checker.rb +103 -0
  27. data/lib/table_sync/utils/proc_array.rb +17 -0
  28. data/lib/table_sync/utils/proc_keywords_resolver.rb +46 -0
  29. data/lib/table_sync/version.rb +1 -1
  30. data/table_sync.gemspec +2 -1
  31. metadata +45 -33
  32. data/docs/development.md +0 -43
  33. data/docs/synopsis.md +0 -336
  34. data/lib/table_sync/config.rb +0 -105
  35. data/lib/table_sync/config/callback_registry.rb +0 -53
  36. data/lib/table_sync/config_decorator.rb +0 -38
  37. data/lib/table_sync/dsl.rb +0 -25
  38. data/lib/table_sync/event_actions.rb +0 -96
  39. data/lib/table_sync/event_actions/data_wrapper.rb +0 -7
  40. data/lib/table_sync/event_actions/data_wrapper/base.rb +0 -23
  41. data/lib/table_sync/event_actions/data_wrapper/destroy.rb +0 -19
  42. data/lib/table_sync/event_actions/data_wrapper/update.rb +0 -21
  43. data/lib/table_sync/model/sequel.rb +0 -88
  44. data/lib/table_sync/plugins.rb +0 -72
  45. data/lib/table_sync/plugins/abstract.rb +0 -55
  46. data/lib/table_sync/plugins/access_mixin.rb +0 -49
  47. data/lib/table_sync/plugins/registry.rb +0 -153
  48. data/lib/table_sync/receiving_handler.rb +0 -76
@@ -1,72 +0,0 @@
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
@@ -1,55 +0,0 @@
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
@@ -1,49 +0,0 @@
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
@@ -1,153 +0,0 @@
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,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class TableSync::ReceivingHandler < Rabbit::EventHandler
4
- extend TableSync::DSL
5
-
6
- attribute :event
7
- attribute :model
8
- attribute :version
9
-
10
- def call
11
- raise TableSync::UndefinedConfig.new(model) if configs.blank?
12
-
13
- configs.each do |config|
14
- next unless config.allow_event?(event)
15
-
16
- data = processed_data(config)
17
- next if data.empty?
18
-
19
- case event
20
- when :update
21
- config.model.transaction do
22
- config.update(data)
23
- end
24
- when :destroy
25
- config.destroy(data.values.first)
26
- else
27
- raise "Unknown event: #{event}"
28
- end
29
- end
30
- end
31
-
32
- private
33
-
34
- def data=(data)
35
- @data = data[:attributes]
36
- end
37
-
38
- def event=(name)
39
- super(name.to_sym)
40
- end
41
-
42
- def model=(name)
43
- super(name.to_s)
44
- end
45
-
46
- def configs
47
- @configs ||= self.class.configs[model]
48
- &.map { |c| ::TableSync::ConfigDecorator.new(c, self) }
49
- end
50
-
51
- def processed_data(config)
52
- parts = config.partitions&.transform_keys { |k| config.model.class.new(k) } ||
53
- { config.model => Array.wrap(data) }
54
-
55
- parts.transform_values! do |data_part|
56
- data_part.map do |row|
57
- original_row_for_data = row.dup
58
- row = row.dup
59
-
60
- config.mapping_overrides.each do |before, after|
61
- row[after] = row.delete(before)
62
- end
63
-
64
- only = config.only
65
- row, missed = row.partition { |key, _| key.in?(only) }.map(&:to_h)
66
-
67
- row.deep_merge!(config.rest_key => missed) if config.rest_key
68
- row[config.version_key] = version
69
-
70
- row.merge!(config.additional_data(original_row_for_data))
71
-
72
- row unless config.skip(original_row_for_data)
73
- end.compact.presence
74
- end.compact
75
- end
76
- end