es-reindex 0.2.1 → 0.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
  SHA1:
3
- metadata.gz: 0bfec9b90b4f6f60bca9fbc2e31b512e91859ee0
4
- data.tar.gz: 34d5f1814a05ad2cb3eeee1427bb8fb1126006a0
3
+ metadata.gz: 142c4bceb879849117f58dea9019a4ad38bebc58
4
+ data.tar.gz: 4676e75a520fe3eb18660000b72b1d4b639ffca2
5
5
  SHA512:
6
- metadata.gz: fa461c5f68ded8c5e1fb03436cc414df23d7c7dd21e8896c29675c21f6d1a5b5114db2a19de2027d0bbd6ccb773441fb9b59781bf1b769b9d60a597e17828ead
7
- data.tar.gz: 0a7288a5c3a040c061f99bdb32f3153789cf76d13827535f3a2a5f866469d65527e4f85d2df1f184c40506fe01ad8afd47bca3f60c3f05cf23332e4963f84b38
6
+ metadata.gz: 896bbe493132b19ed83182fbd83464ec3dae02779ada820b08cac30b7801433ab0213cd6e7f71a56d1a5357d3f2df80bfff90f4c83055ef5883271535f938745
7
+ data.tar.gz: d220120b5a19c873eb0dfc7630a469ce37bc705e2510a8825588fae161a442e33c2ed3462bd3ec54a594930c4df87ea6fff827e933b6e59971b0b81cd5978f68
data/README.markdown CHANGED
@@ -77,8 +77,21 @@ ESReindex.copy! 'http://my_server/index', 'http://my_server/index_copy',
77
77
  after_copy: -> { finish_thing } # Runs after everything is copied over
78
78
  ```
79
79
 
80
+ #### Callbacks (guards)
81
+
82
+ You can also use the `:if` or `:unless` callbacks to prevent the copy/reindexing from occuring if conditions are (un)met. The source client and destination client are passed in:
83
+
84
+ ```ruby
85
+ ESReindex.copy! 'http://my_server/index', 'http://my_server/index_copy',
86
+ if: ->(sclient,dclient) { Time.now.hour > 20 }, # Only copy the indexes if it's after 8pm
87
+ unless: ->(sclient,dclient) { Time.now.strftime("%A") == "Friday" } # Never copy on Fridays
88
+ ```
89
+
90
+ For a more practical example, see the [reindex integration specs](spec/integration/reindex_spec.rb).
91
+
80
92
  ## Changelog
81
93
 
94
+ + __0.3.0__: Add `:if` and `:unless` callbacks
82
95
  + __0.2.1__: [BUGFIX] Improve callback presence check
83
96
  + __0.2.0__: Lots of bugfixes, use elasticsearch client gem, add .reindex! method and callbacks
84
97
  + __0.1.0__: First gem release
data/lib/es-reindex.rb CHANGED
@@ -12,14 +12,14 @@ class ESReindex
12
12
  def self.copy!(src, dst, options = {})
13
13
  self.new(src, dst, options).tap do |reindexer|
14
14
  reindexer.setup_index_urls
15
- reindexer.copy!
15
+ reindexer.copy! if reindexer.okay_to_proceed?
16
16
  end
17
17
  end
18
18
 
19
19
  def self.reindex!(src, dst, options={})
20
20
  self.new(src, dst, options.merge(copy_mappings: false)).tap do |reindexer|
21
21
  reindexer.setup_index_urls
22
- reindexer.copy!
22
+ reindexer.copy! if reindexer.okay_to_proceed?
23
23
  end
24
24
  end
25
25
 
@@ -36,6 +36,14 @@ class ESReindex
36
36
  copy_mappings: true # Copy old mappings/settings
37
37
  }.merge! options
38
38
 
39
+ %w{
40
+ if unless mappings settings before_create after_create before_each after_each after_copy
41
+ }.each do |callback|
42
+ if options[callback.to_sym].present? && !options[callback.to_sym].respond_to?(:call)
43
+ raise ArgumentError, "#{callback} must be a callable object"
44
+ end
45
+ end
46
+
39
47
  @done = 0
40
48
  end
41
49
 
@@ -55,6 +63,14 @@ class ESReindex
55
63
  @dclient = Elasticsearch::Client.new host: durl
56
64
  end
57
65
 
66
+ def okay_to_proceed?
67
+ okay = true
68
+ okay = options[:if].call(sclient, dclient) if options[:if].present?
69
+ okay = (okay && !(options[:unless].call sclient, dclient)) if options[:unless].present?
70
+ log 'Skipping action due to guard callbacks' unless okay
71
+ okay
72
+ end
73
+
58
74
  def copy!
59
75
  log "Copying '#{surl}/#{sidx}' to '#{durl}/#{didx}'#{remove? ? ' with rewriting destination mapping!' : update? ? ' with updating existing documents!' : '.'}"
60
76
  confirm if from_cli?
@@ -97,13 +113,13 @@ class ESReindex
97
113
  create_msg = ""
98
114
  end
99
115
 
100
- options[:before_create].call if options[:before_create] && options[:before_create].respond_to?(:call)
116
+ options[:before_create].try(:call)
101
117
 
102
118
  log "Creating '#{durl}/#{didx}' index#{create_msg}..."
103
119
  dclient.indices.create index: didx, body: { settings: settings, mappings: mappings }
104
120
  log "Succesfully created '#{durl}/#{didx}''#{create_msg}."
105
121
 
106
- options[:after_create].call if options[:after_create] && options[:after_create].respond_to?(:call)
122
+ options[:after_create].try(:call)
107
123
  end
108
124
 
109
125
  true
@@ -141,13 +157,13 @@ class ESReindex
141
157
  while scroll = sclient.scroll(scroll_id: scroll['_scroll_id'], scroll: '10m') and not scroll['hits']['hits'].empty? do
142
158
  bulk = []
143
159
  scroll['hits']['hits'].each do |doc|
144
- options[:before_each].call doc if options[:before_each] && options[:before_each].respond_to?(:call)
160
+ options[:before_each].try(:call)
145
161
  ### === implement possible modifications to the document
146
162
  ### === end modifications to the document
147
163
  base = {'_index' => didx, '_id' => doc['_id'], '_type' => doc['_type'], data: doc['_source']}
148
164
  bulk << {action => base}
149
165
  @done = done + 1
150
- options[:after_each].call doc if options[:after_each] && options[:after_each].respond_to?(:call)
166
+ options[:after_each].try(:call)
151
167
  end
152
168
  unless bulk.empty?
153
169
  dclient.bulk body: bulk
@@ -159,7 +175,7 @@ class ESReindex
159
175
 
160
176
  log "Copy progress: %u/%u done in %s.\n" % [done, total, tm_len]
161
177
 
162
- options[:after_copy].call if options[:after_copy] && options[:after_copy].respond_to?(:call)
178
+ options[:after_copy].try(:call)
163
179
 
164
180
  true
165
181
  end
@@ -1,3 +1,3 @@
1
1
  class ESReindex
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -11,6 +11,16 @@ describe ESReindex do
11
11
  expect(reindexer.options).to eq remove: false, update: true, frame: 1000, from_cli: false, copy_mappings: true
12
12
  end
13
13
 
14
+ context "with invalid callback options" do
15
+ let(:options) { {if: :not_a_proc} }
16
+
17
+ it "fails" do
18
+ expect{
19
+ reindexer
20
+ }.to raise_error ArgumentError, "if must be a callable object"
21
+ end
22
+ end
23
+
14
24
  it "starts with 0 indexes done" do
15
25
  expect(reindexer.done).to eq 0
16
26
  end
@@ -8,7 +8,6 @@ describe "reindex!", type: :integration do
8
8
  let!(:new_klass) { test_klass index_name: new_index_name, attributes: [:foo] }
9
9
 
10
10
  let(:test_post) { original_klass.create id: 1, text: 'test_post' }
11
- let(:test_post_2) { new_klass.create id: 2, text: 'other_post' }
12
11
 
13
12
  # Create the index (test_index) on the test_klass:
14
13
  before do
@@ -19,13 +18,55 @@ describe "reindex!", type: :integration do
19
18
 
20
19
  let(:reindexed_post) { new_klass.find test_post.id }
21
20
 
21
+ let(:reindex) { ESReindex.reindex! "#{ES_HOST}/#{orig_index_name}", "#{ES_HOST}/#{new_index_name}", opts }
22
+ let(:mappings) { ->{ new_klass.mappings } }
23
+ let(:settings) { ->{ new_klass.settings } }
24
+ let(:other_opts) { {} }
25
+ let(:opts) { {mappings: mappings, settings: settings}.merge other_opts }
26
+
22
27
  it "reindexes with the selected mappings" do
23
- ESReindex.reindex! "#{ES_HOST}/#{orig_index_name}", "#{ES_HOST}/#{new_index_name}",
24
- mappings: -> { new_klass.mappings },
25
- settings: -> { new_klass.settings }
28
+ reindex
26
29
 
27
30
  expect(reindexed_post.id).to eq test_post.id
28
31
  expect(reindexed_post.text).to eq test_post.text
29
32
  expect(reindexed_post).to respond_to :foo
30
33
  end
34
+
35
+ context "with a :unless guard" do
36
+ let(:other_opts) do
37
+ {
38
+ unless: ->(sclient,dclient) {
39
+ existing_properties = sclient.indices.get_mapping(index: orig_index_name)[orig_index_name]['mappings']['test_klass']['properties']
40
+ existing_mappings = existing_properties.inject({}) do |result, (k,v)|
41
+ result[k.to_sym] = {type: v['type']}
42
+ result
43
+ end
44
+ new_mappings = klass_to_use_as_source.mappings.to_hash[:test_klass][:properties]
45
+ existing_mappings.sort == new_mappings.sort
46
+ }
47
+ }
48
+ end
49
+
50
+ context "when the unless call returns true" do
51
+ let(:klass_to_use_as_source) { original_klass }
52
+
53
+ it "does not reindex" do
54
+ reindex
55
+ original_klass.refresh_index!
56
+ expect(test_post.id).to be_present
57
+ expect { test_post.foo}.to raise_error NoMethodError
58
+ end
59
+ end
60
+
61
+ context "when the unless call returns false" do
62
+ let(:klass_to_use_as_source) { new_klass }
63
+
64
+ it "reindexes" do
65
+ reindex
66
+ expect(reindexed_post.id).to eq test_post.id
67
+ expect(reindexed_post.text).to eq test_post.text
68
+ expect(reindexed_post).to respond_to :foo
69
+ end
70
+ end
71
+ end
31
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: es-reindex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Aiken
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-09 00:00:00.000000000 Z
12
+ date: 2015-02-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: elasticsearch