elastic_queue 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.rubocop.yml +20 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/LICENSE +20 -0
- data/README.md +12 -0
- data/Rakefile +25 -0
- data/elastic_queue.gemspec +28 -0
- data/lib/elastic_queue/base.rb +52 -0
- data/lib/elastic_queue/filters.rb +47 -0
- data/lib/elastic_queue/percolation.rb +42 -0
- data/lib/elastic_queue/persistence.rb +68 -0
- data/lib/elastic_queue/query.rb +62 -0
- data/lib/elastic_queue/query_options.rb +48 -0
- data/lib/elastic_queue/queueable.rb +66 -0
- data/lib/elastic_queue/results.rb +67 -0
- data/lib/elastic_queue/search.rb +5 -0
- data/lib/elastic_queue/sorts.rb +23 -0
- data/lib/elastic_queue/version.rb +3 -0
- data/lib/elastic_queue.rb +7 -0
- data/spec/factories.rb +64 -0
- data/spec/lib/elastic_queue_functional_spec.rb +276 -0
- data/spec/lib/elastic_queue_unit_spec.rb +220 -0
- data/spec/spec_helper.rb +24 -0
- data/spec/support/elastic_queue_helper.rb +18 -0
- metadata +175 -0
data/spec/factories.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
sequence :email_address do |n|
|
3
|
+
"testy#{n}@example.com"
|
4
|
+
end
|
5
|
+
|
6
|
+
sequence :user_id do
|
7
|
+
(10000...10005).to_a.sample
|
8
|
+
end
|
9
|
+
|
10
|
+
sequence :agent_fee_sales_session_status do
|
11
|
+
['active', 'dead'].sample
|
12
|
+
end
|
13
|
+
|
14
|
+
factory :agent_fee_sales_session do
|
15
|
+
agent
|
16
|
+
status { generate(:agent_fee_sales_session_status) }
|
17
|
+
assigned_to { generate(:user_id) }
|
18
|
+
assigned_at Time.parse('2013-12-02 08:40:33')
|
19
|
+
expires_at Time.parse('2014-06-02 08:40:33')
|
20
|
+
follow_up Time.parse('2013-12-17 06:00:00')
|
21
|
+
hot '1'
|
22
|
+
priority 'high'
|
23
|
+
created_at Time.parse('2013-11-18 14:36:05')
|
24
|
+
updated_at Time.parse('2013-12-17 11:31:08')
|
25
|
+
factory :null_follow_up_agent_fee_sales_session do
|
26
|
+
follow_up nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
factory :agent do
|
31
|
+
after(:build) { |agent| agent.class.skip_callback(:save, :after, :notate_changes) }
|
32
|
+
user
|
33
|
+
company
|
34
|
+
status 'active'
|
35
|
+
name_on_license 'Testy'
|
36
|
+
license_type 'Salesperson'
|
37
|
+
license_number '111111'
|
38
|
+
license_state 'CA'
|
39
|
+
broker_name 'Ali'
|
40
|
+
years_in_real_estate '12 years'
|
41
|
+
end
|
42
|
+
|
43
|
+
factory :company do
|
44
|
+
name 'Flywheel'
|
45
|
+
address '233 Post st.'
|
46
|
+
city 'San Francisco'
|
47
|
+
state 'CA'
|
48
|
+
zip '94104'
|
49
|
+
end
|
50
|
+
|
51
|
+
factory :user do
|
52
|
+
after(:build) { |user| user.class.skip_callback(:save, :after, :notate_changes) }
|
53
|
+
email { generate(:email_address) }
|
54
|
+
login { |u| u.email }
|
55
|
+
password '1234567'
|
56
|
+
first_name 'Testy'
|
57
|
+
last_name 'Testerson'
|
58
|
+
phone_office '415-555-5555'
|
59
|
+
factory :agent_user do
|
60
|
+
user_type 'agent'
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require 'elasticsearch'
|
2
|
+
require 'spec_helper'
|
3
|
+
require_relative '../../lib/elastic_queue'
|
4
|
+
|
5
|
+
describe 'searching:' do
|
6
|
+
before(:all) do
|
7
|
+
class TestQueue < ElasticQueue::Base
|
8
|
+
models :agent_fee_sales_session, :agent
|
9
|
+
end
|
10
|
+
@test_queue = TestQueue
|
11
|
+
AgentFeeSalesSession.send(:include, ElasticQueueable)
|
12
|
+
AgentFeeSalesSession.send(:queue_attributes, :agent_id, :status, :assigned_to_id, :assigned_at, :expires_at, :follow_up, :priority, :hot, :created_at, :updated_at, :first_name, :last_name, :email)
|
13
|
+
Agent.send(:include, ElasticQueueable)
|
14
|
+
Agent.send(:queue_attributes, :status, :license_state)
|
15
|
+
@count = 10
|
16
|
+
@count.times { FactoryGirl.create(:agent_fee_sales_session) }
|
17
|
+
@test_queue.index_models
|
18
|
+
refresh_index
|
19
|
+
end
|
20
|
+
|
21
|
+
after(:all) do
|
22
|
+
AgentFeeSalesSession.all.each(&:delete)
|
23
|
+
Agent.all.each(&:delete)
|
24
|
+
test_search_client.indices.delete index: 'test_queue'
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#search' do
|
28
|
+
|
29
|
+
it 'returns an ElasticQueueResults object' do
|
30
|
+
expect(@test_queue.search('Testy AND Testerson').class).to be(ElasticQueueResults)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'searches a search string against default search fields' do
|
34
|
+
a = AgentFeeSalesSession.first
|
35
|
+
a.first_name = 'Zesty'
|
36
|
+
a.save
|
37
|
+
@test_queue.index_models
|
38
|
+
refresh_index
|
39
|
+
expect(@test_queue.search('Testy AND Testerson').count).to be(@count - 1)
|
40
|
+
expect(@test_queue.search('Zesty').count).to be(1)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'searches a search string against specific search fields' do
|
44
|
+
pending 'yagni'
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'eager loads models when asked to' do
|
48
|
+
expect(@test_queue.search('Testy Testerson', {}, { agent_fee_sales_session: :agent }).first.association(:agent).loaded?).to be(true)
|
49
|
+
expect(@test_queue.search('Testy Testerson', {}, { agent_fee_sales_session: [agent: :user] }).first.agent.association(:user).loaded?).to be(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'does not eager load when not asked to' do
|
53
|
+
expect(@test_queue.search('Testy Testerson').first.association(:agent).loaded?).to be(false)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'paginates' do
|
57
|
+
expect(@test_queue.search('Testy Testerson', { per_page: 1 }).count).to be(1)
|
58
|
+
first_page = @test_queue.search('Testy Testerson', { per_page: 1, page: 1 })
|
59
|
+
second_page = @test_queue.search('Testy Testerson', { per_page: 1, page: 2 })
|
60
|
+
expect(first_page.first.id != second_page.first.id).to be(true)
|
61
|
+
expect(second_page.results.current_page.to_s).to eq('2')
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can sort results by a term' do
|
65
|
+
order = @test_queue.search('Testy Testerson', { order_by: :assigned_to_id }).map(&:assigned_to)
|
66
|
+
expect(order).to eq(order.sort)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'can sort in ascending and decending order' do
|
70
|
+
order_desc = @test_queue.search('Testy Testerson', { order_by: :id, order: :desc }).map(&:id)
|
71
|
+
order_asc = @test_queue.search('Testy Testerson', { order_by: :id, order: :asc }).map(&:id)
|
72
|
+
expect(order_desc.reverse).to eq(order_asc)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#queue' do
|
78
|
+
|
79
|
+
describe 'with params hashes' do
|
80
|
+
|
81
|
+
it 'returns all records if not passed any parameters' do
|
82
|
+
expect(@test_queue.queue().length).to be(@count*2)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'returns models' do
|
86
|
+
expect(@test_queue.queue().first).to be_a(ActiveRecord::Base)
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'with eager loading' do
|
90
|
+
|
91
|
+
it 'eager loads when asked to' do
|
92
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session }, { agent_fee_sales_session: :agent }).first.association(:agent).loaded?).to be(true)
|
93
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session }, { agent_fee_sales_session: [agent: :user] }).first.agent.association(:user).loaded?).to be(true)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'does not eager load when not asked to' do
|
97
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session }).first.association(:agent).loaded?).to be(false)
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'properly orders eager loaded models, including across models' do
|
101
|
+
order_with_eager_loading = @test_queue.queue({ model: [:agent_fee_sales_session, :agent], order_by: :id }, { agent_fee_sales_session: :agent, agent: :user }).map(&:id)
|
102
|
+
order_without_eager_loading = @test_queue.queue({ model: [:agent_fee_sales_session, :agent], order_by: :id }).map(&:id)
|
103
|
+
expect(order_with_eager_loading <=> order_without_eager_loading).to be(0)
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
describe 'with queue options' do
|
109
|
+
|
110
|
+
it 'can recover gracefully from bad searches' do
|
111
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session, sort_by: 'non_attribute', non_attribute: true })).to_not raise_error
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'accepts either strings or symbols' do
|
115
|
+
with_strings = @test_queue.queue({ model: 'agent_fee_sales_session', status: 'active' }).map(&:id)
|
116
|
+
with_symbols = @test_queue.queue({ model: :agent_fee_sales_session, status: :active }).map(&:id)
|
117
|
+
expect(with_symbols).to eq(with_strings)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'can search across multiple models' do
|
121
|
+
pending
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'can filter by a term' do
|
125
|
+
expect(@test_queue.queue({ status: :active }).map(&:status).uniq).to eq(['active'])
|
126
|
+
expect(@test_queue.queue({ status: :fake_status })).to eq([])
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'can filter by a term even if some of the models it includes don\'t have that term' do
|
130
|
+
pending 'verify specification for this'
|
131
|
+
# agent_id = AgentFeeSalesSession.first.agent_id
|
132
|
+
# license_state = Agent.first.license_state
|
133
|
+
# expect(@test_queue.queue({ agent_id: agent_id }).length).to be(1)
|
134
|
+
# expect(@test_queue.queue({ agent_id: agent_id, license_state: license_state }).length).to be(1)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'can filter by a range' do
|
138
|
+
the_beginning_of_time = (Date.today - 10.years).to_time
|
139
|
+
agent_fee_sales_session_created_before = Time.now
|
140
|
+
expect(@test_queue.queue({ created_at_between: [the_beginning_of_time, Time.now] }).length).to be(@count)
|
141
|
+
# expect(@test_queue.queued({ created_at_between: [the_beginning_of_time, agent_fee_sales_session_created_before] }).map{ |model| model.class.to_s }.uniq).to eq(['AgentFeeSalesSession'])
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'can take multiple values for one term' do #or filter
|
145
|
+
id_1, id_2 = AgentFeeSalesSession.first(2).map(&:id)
|
146
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session, id: [id_1, id_2] }).length).to be(2)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'can filter out a term' do #not filter
|
150
|
+
id_1 = AgentFeeSalesSession.first.id
|
151
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session, id_not: [id_1] }).length).to be(@count - 1)
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'can filter on null values (also tests #null_filter)' do
|
155
|
+
before(:all) do
|
156
|
+
@null_valued_record = FactoryGirl.create(:null_follow_up_agent_fee_sales_session)
|
157
|
+
@test_queue.index_models
|
158
|
+
refresh_index
|
159
|
+
end
|
160
|
+
|
161
|
+
after(:all) do
|
162
|
+
@null_valued_record.delete
|
163
|
+
@test_queue.index_models
|
164
|
+
refresh_index
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'can filter for null values' do #null_filter
|
168
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session, follow_up_null: true }).length).to be(1)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'can filter against null values' do #null_filter
|
172
|
+
expect(@test_queue.queue({ model: :agent_fee_sales_session, follow_up_null: false }).length).to be(@count)
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'can sort results by a term' do
|
178
|
+
order = @test_queue.queue({ model: [:agent_fee_sales_session], order_by: :assigned_to_id }).map(&:assigned_to)
|
179
|
+
expect(order).to eq(order.sort)
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'can sort in ascending and decending order' do
|
183
|
+
order_desc = @test_queue.queue({ model: ['agent_fee_sales_session', 'agent'], order_by: :id, order: :desc }).map(&:id)
|
184
|
+
order_asc = @test_queue.queue({ model: ['agent_fee_sales_session', 'agent'], order_by: :id, order: :asc }).map(&:id)
|
185
|
+
expect(order_desc.reverse).to eq(order_asc)
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'can sort results by multiple terms' do
|
189
|
+
sql_order = AgentFeeSalesSession.order('assigned_to ASC, id DESC').pluck(:id)
|
190
|
+
elastic_queue_order = @test_queue.queue({ model: :agent_fee_sales_session, order_by: [ [:assigned_to_id, :asc], [:id, :desc] ] }).map(&:id)
|
191
|
+
expect(elastic_queue_order).to eq(sql_order)
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
describe 'with chainable methods' do
|
199
|
+
|
200
|
+
describe '#models_include' do
|
201
|
+
|
202
|
+
it 'eager loads models' do
|
203
|
+
expect(@test_queue.model_includes(:agent_fee_sales_session, :agent).queue({ model: :agent_fee_sales_session }).first.association(:agent).loaded?).to be(true)
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
|
208
|
+
describe '#page, #per_page' do
|
209
|
+
it 'paginates results' do
|
210
|
+
page_1_ids = @test_queue.page(1).per_page(2).queue({ model: :agent_fee_sales_session }).map(&:id)
|
211
|
+
page_2_ids = @test_queue.page(2).per_page(2).queue({ model: :agent_fee_sales_session }).map(&:id)
|
212
|
+
expect(page_1_ids & page_2_ids).to eq([])
|
213
|
+
end
|
214
|
+
|
215
|
+
it 'returns the last page of results if asked for too high of a page number' do
|
216
|
+
expect(@test_queue.page(@count*2).per_page(2).queue({ model: :agent_fee_sales_session })).to_not eq([])
|
217
|
+
end
|
218
|
+
|
219
|
+
end
|
220
|
+
|
221
|
+
describe 'dynamic methods' do
|
222
|
+
|
223
|
+
it 'return the same results as passing an options hash' do
|
224
|
+
chained_dynamic_methods_search = @test_queue.model(:agent_fee_sales_session).order_by([:assigned_to_id, :asc]).order_by([:id, :desc]).queue.map(&:id)
|
225
|
+
options_hash_search = @test_queue.queue({ model: :agent_fee_sales_session, order_by: [ [:assigned_to_id, :asc], [:id, :desc] ] }).map(&:id)
|
226
|
+
expect(chained_dynamic_methods_search).to eq(options_hash_search)
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'isn\'t picky about how you enter array values' do
|
230
|
+
pending 'what do I mean by this?'
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'does not break method_missing' do
|
234
|
+
expect{ @test_queue.fake_method }.to raise_error(NoMethodError)
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'does not break respond_to?' do
|
238
|
+
expect(!@test_queue.respond_to?(:fake_method) && @test_queue.respond_to?(:to_s)).to be(true)
|
239
|
+
end
|
240
|
+
|
241
|
+
it 'provides methods for every queue attribute of an indexed model' do
|
242
|
+
AgentFeeSalesSession.queue_attribute_method_names.each do |attr_name| # relies on elastic_queueable module
|
243
|
+
@test_queue.respond_to?(attr_name) || fail
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'provides *_before, *_after, *_not, *_null, *_greater_than and *_less_than methods for every queue attribute of an indexed model' do
|
248
|
+
AgentFeeSalesSession.queue_attribute_method_names.each do |attr_name| # relies on elastic_queueable module
|
249
|
+
['_before', '_after', '_not', '_null', '_greater_than', '_less_than'].each do |suffix|
|
250
|
+
@test_queue.respond_to?("#{attr_name.to_s}#{suffix}".to_sym) || fail
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
|
261
|
+
describe '#queue_count' do
|
262
|
+
it 'returns the same number of records as #queue' do
|
263
|
+
expect(@test_queue.queue_count({})).to eq(@test_queue.queue({}).count)
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'works with chainable methods' do
|
267
|
+
pending
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
describe '#queue_with_data' do
|
273
|
+
pending
|
274
|
+
end
|
275
|
+
|
276
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'elasticsearch'
|
2
|
+
require 'spec_helper'
|
3
|
+
require_relative '../../lib/elastic_queue'
|
4
|
+
|
5
|
+
describe ElasticQueue do
|
6
|
+
|
7
|
+
before(:all) do
|
8
|
+
class TestQueue < ElasticQueue::Base
|
9
|
+
models :agent_fee_sales_session, :agent
|
10
|
+
end
|
11
|
+
@test_queue = TestQueue
|
12
|
+
AgentFeeSalesSession.send(:include, ElasticQueueable)
|
13
|
+
AgentFeeSalesSession.send(:queue_attributes, :agent_id, :status, :assigned_to_id, :assigned_at, :expires_at, :follow_up, :priority, :hot, :created_at, :updated_at)
|
14
|
+
Agent.send(:include, ElasticQueueable)
|
15
|
+
Agent.send(:queue_attributes, :status, :license_state)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe 'naming:' do
|
19
|
+
|
20
|
+
describe '#index_name' do
|
21
|
+
it 'returns the correct index name' do
|
22
|
+
expect('test_queue') == @test_queue.index_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#model_names' do #Randomized with seed 41805 will cause this to fail 'cause we already sent models to TestQueue in the next block
|
27
|
+
it 'complains if the user hasn\'t set any models' do
|
28
|
+
class TestQueue < ElasticQueue::Base
|
29
|
+
end
|
30
|
+
expect{TestQueue2.model_names}.to raise_error(NotImplementedError)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns the correct model names' do
|
34
|
+
expect(@test_queue.model_names).to eq([:agent_fee_sales_session, :agent])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'index management' do
|
41
|
+
|
42
|
+
before(:each) do
|
43
|
+
@model = FactoryGirl.create(:agent_fee_sales_session)
|
44
|
+
end
|
45
|
+
|
46
|
+
after(:each) do
|
47
|
+
if test_search_client.indices.exists index: 'test_queue'
|
48
|
+
test_search_client.indices.delete index: 'test_queue'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#index_exists?' do
|
53
|
+
|
54
|
+
it 'returns false for a non-existing index' do
|
55
|
+
class TestQueue < ElasticQueue::Base
|
56
|
+
end
|
57
|
+
expect(TestQueue3.index_exists?).to eq(false)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'returns true for an existing index' do
|
61
|
+
test_search_client.indices.create index: 'test_queue'
|
62
|
+
expect(@test_queue.index_exists?).to eq(true)
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe '#initialize_index' do
|
68
|
+
pending
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#create_or_recreate_index' do
|
72
|
+
pending
|
73
|
+
end
|
74
|
+
|
75
|
+
describe '#create_index' do
|
76
|
+
pending
|
77
|
+
end
|
78
|
+
|
79
|
+
describe '#delete_index' do
|
80
|
+
pending
|
81
|
+
end
|
82
|
+
|
83
|
+
describe '#index_models' do
|
84
|
+
|
85
|
+
it 'should create the index' do
|
86
|
+
@test_queue.index_models
|
87
|
+
expect(test_search_client.indices.exists index: 'test_queue').to eq(true)
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should index the models' do
|
91
|
+
@test_queue.index_models
|
92
|
+
refresh_index
|
93
|
+
expect((query_all)['hits']['hits'].first['_source']['model']).to eq('agent_fee_sales_session')
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should overwrite the old index if it already exists' do
|
97
|
+
pending 'is this really testing what I think it is?'
|
98
|
+
@test_queue.index_models
|
99
|
+
refresh_index
|
100
|
+
first_id = query_all['hits']['hits'].last['_source']['id']
|
101
|
+
@model.delete
|
102
|
+
@model2 = FactoryGirl.create(:agent_fee_sales_session)
|
103
|
+
@test_queue.index_models
|
104
|
+
refresh_index
|
105
|
+
second_id = query_all['hits']['hits'].last['_source']['id']
|
106
|
+
expect(first_id == second_id).to eq(false)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
describe 'record management' do
|
114
|
+
|
115
|
+
before(:each) do
|
116
|
+
@count = 10
|
117
|
+
@count.times{ FactoryGirl.create(:agent_fee_sales_session) }
|
118
|
+
@test_queue.index_models
|
119
|
+
refresh_index
|
120
|
+
@model = FactoryGirl.create(:agent_fee_sales_session)
|
121
|
+
end
|
122
|
+
|
123
|
+
after(:each) do
|
124
|
+
AgentFeeSalesSession.all.each(&:delete)
|
125
|
+
test_search_client.indices.delete index: 'test_queue'
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#index_model' do
|
129
|
+
|
130
|
+
it 'should add the model to the index' do
|
131
|
+
before_index = query_all['hits']['hits'].map{ |hit| hit['_source']['id'].to_i }
|
132
|
+
expect(before_index.include?(@model.id)).to be(false) # ensure the test is doing what we expect
|
133
|
+
@test_queue.index_model(@model)
|
134
|
+
refresh_index
|
135
|
+
after_index = query_all['hits']['hits'].map{ |hit| hit['_source']['id'].to_i }
|
136
|
+
expect(after_index.include?(@model.id)).to be(true)
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
describe '#upsert_model' do
|
142
|
+
it 'should update an already existing record' do
|
143
|
+
now = Time.now.to_s
|
144
|
+
record = AgentFeeSalesSession.first
|
145
|
+
record.follow_up = now
|
146
|
+
record.save
|
147
|
+
record.reload
|
148
|
+
@test_queue.upsert_model(record)
|
149
|
+
refresh_index
|
150
|
+
query = { 'filter' => { 'and' => [{ 'term' => { 'model' => 'agent_fee_sales_session' } }, { 'term' => { 'id' => record.id.to_s } }] } }
|
151
|
+
query_index = test_search_client.search index: 'test_queue', body: query.to_json
|
152
|
+
expect(Time.parse(query_index['hits']['hits'].first['_source']['follow_up']).to_s).to eq(record.follow_up.to_s)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should insert a non-existing record' do
|
156
|
+
query = { 'filter' => { 'term' => { 'model' => 'agent_fee_sales_session' } } }
|
157
|
+
before_upsert = test_search_client.search index: 'test_queue', size: @count * 2, body: query.to_json
|
158
|
+
@test_queue.upsert_model(@model)
|
159
|
+
refresh_index
|
160
|
+
after_upsert = test_search_client.search index: 'test_queue', size: @count * 2, body: query.to_json
|
161
|
+
expect(before_upsert['hits']['total'] + 1).to be(after_upsert['hits']['total'])
|
162
|
+
expect(after_upsert['hits']['hits'].map{ |hit| hit['_source']['id'].to_i }.include?(@model.id)).to eq(true)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
describe '#remove_model' do
|
167
|
+
it 'should remove a given model from the index' do
|
168
|
+
to_remove = AgentFeeSalesSession.first
|
169
|
+
@test_queue.remove_model(to_remove)
|
170
|
+
refresh_index
|
171
|
+
query = { 'filter' => { 'term' => { 'model' => 'agent_fee_sales_session' } } }
|
172
|
+
after_removal = test_search_client.search index: 'test_queue', size: @count, body: query.to_json
|
173
|
+
expect(after_removal['hits']['hits'].map{ |hit| hit['_source']['id'].to_i }.include?(to_remove.id)).to eq(false)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
describe 'percolation' do
|
180
|
+
|
181
|
+
before(:each) do
|
182
|
+
@test_queue.index_models
|
183
|
+
refresh_index
|
184
|
+
@model = FactoryGirl.create(:agent_fee_sales_session)
|
185
|
+
end
|
186
|
+
|
187
|
+
after(:each) do
|
188
|
+
AgentFeeSalesSession.all.each(&:delete)
|
189
|
+
test_search_client.indices.delete index: 'test_queue'
|
190
|
+
end
|
191
|
+
|
192
|
+
describe '#register_percolator_query' do
|
193
|
+
pending
|
194
|
+
end
|
195
|
+
|
196
|
+
describe '#reverse_search' do
|
197
|
+
pending
|
198
|
+
end
|
199
|
+
|
200
|
+
describe '#unregister_percolator_query' do
|
201
|
+
pending
|
202
|
+
end
|
203
|
+
|
204
|
+
describe '#list_percolator_queries' do
|
205
|
+
pending
|
206
|
+
end
|
207
|
+
|
208
|
+
describe '#model_in_queue?' do
|
209
|
+
it 'should return true for a model that would be in the queue' do
|
210
|
+
expect(@test_queue.model_in_queue?(@model, { model: :agent_fee_sales_session })).to be(true)
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'should return false for a model that would not be in the queue' do
|
214
|
+
expect(@test_queue.model_in_queue?(@model, { model: :agent })).to be(false)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
+
require 'rspec'
|
3
|
+
require 'rspec/autorun'
|
4
|
+
|
5
|
+
require 'factory_girl'
|
6
|
+
require File.expand_path('../../lib/elastic_queue', __FILE__)
|
7
|
+
require 'support/elastic_queue_helper'
|
8
|
+
|
9
|
+
# Requires supporting ruby files with custom matchers and macros, etc,
|
10
|
+
# in spec/support/ and its subdirectories.
|
11
|
+
# Dir['spec/support/**/*.rb'].each { |f| require f }
|
12
|
+
# require_relative '../../lib/elastic_queue'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
config.color_enabled = true
|
21
|
+
|
22
|
+
config.include FactoryGirl::Syntax::Methods
|
23
|
+
config.include(ElasticQueueHelper)
|
24
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ElasticQueueHelper
|
2
|
+
|
3
|
+
TEST_SEARCH_CLIENT = Elasticsearch::Client.new
|
4
|
+
|
5
|
+
def test_search_client
|
6
|
+
TEST_SEARCH_CLIENT
|
7
|
+
end
|
8
|
+
|
9
|
+
def refresh_index
|
10
|
+
# forces the index to refresh itself so the search doesn't happen before the models are done being added to the index
|
11
|
+
TEST_SEARCH_CLIENT.indices.refresh index: 'test_queue'
|
12
|
+
end
|
13
|
+
|
14
|
+
def query_all
|
15
|
+
query = { 'query' => {'match_all' => {} } }.to_json
|
16
|
+
TEST_SEARCH_CLIENT.search index: 'test_queue', body: query, size: 500
|
17
|
+
end
|
18
|
+
end
|