massive 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/massive.rb +9 -0
- data/lib/massive/file_serializer.rb +9 -0
- data/lib/massive/job.rb +21 -1
- data/lib/massive/process.rb +1 -1
- data/lib/massive/process_serializer.rb +5 -0
- data/lib/massive/step.rb +1 -1
- data/lib/massive/version.rb +1 -1
- data/spec/models/massive/file_serializer_spec.rb +40 -0
- data/spec/models/massive/job_spec.rb +64 -0
- data/spec/models/massive/process_serializer_spec.rb +14 -0
- data/spec/models/massive/process_spec.rb +37 -75
- data/spec/models/massive/step_spec.rb +2 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0ad236ec732665de7fcf03668e8ce4675da4344
|
4
|
+
data.tar.gz: acba7ff61e45ff129881fa0d86b49480eaa85912
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c922037b0dc37a497a6cced3880e88436912e6d3c8ff35ab8fc80c18f3375fbf4262551ea66ad82b7c5d065d0b20cb168c752400c28382df774027423687fe3
|
7
|
+
data.tar.gz: 122c02cc041df10b737ac8d6457d2bda985bb2930037672df0da4febe828648a9029829c08161597e9a5def1442e3f176062856fb15f52b7d4b72965f3d3c3b7
|
data/Gemfile.lock
CHANGED
data/lib/massive.rb
CHANGED
@@ -22,6 +22,7 @@ module Massive
|
|
22
22
|
|
23
23
|
autoload :ProcessSerializer, 'massive/process_serializer'
|
24
24
|
autoload :StepSerializer, 'massive/step_serializer'
|
25
|
+
autoload :FileSerializer, 'massive/file_serializer'
|
25
26
|
|
26
27
|
module Authenticators
|
27
28
|
autoload :S3, 'massive/authenticators/s3'
|
@@ -33,6 +34,14 @@ module Massive
|
|
33
34
|
@redis ||= Resque.redis
|
34
35
|
end
|
35
36
|
|
37
|
+
def self.split_jobs
|
38
|
+
@split_jobs
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.split_jobs=(value)
|
42
|
+
@split_jobs = value
|
43
|
+
end
|
44
|
+
|
36
45
|
def self.storage_config
|
37
46
|
@storage_config
|
38
47
|
end
|
data/lib/massive/job.rb
CHANGED
@@ -26,7 +26,26 @@ module Massive
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.queue
|
29
|
-
|
29
|
+
if split_jobs
|
30
|
+
:"#{queue_prefix}_#{Kernel.rand(split_jobs) + 1}"
|
31
|
+
else
|
32
|
+
queue_prefix
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.queue_prefix(value=nil)
|
37
|
+
@queue_prefix = value if !value.nil?
|
38
|
+
@queue_prefix || :massive_job
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.split_jobs(value=nil)
|
42
|
+
@split_jobs = value if !value.nil?
|
43
|
+
@split_jobs.nil? ? Massive.split_jobs : @split_jobs
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.cancel_when_failed(value=nil)
|
47
|
+
@cancel_when_failed = value if !value.nil?
|
48
|
+
@cancel_when_failed
|
30
49
|
end
|
31
50
|
|
32
51
|
def enqueue
|
@@ -101,6 +120,7 @@ module Massive
|
|
101
120
|
step.save
|
102
121
|
notify(:failed)
|
103
122
|
|
123
|
+
process.cancel if self.class.cancel_when_failed
|
104
124
|
raise e
|
105
125
|
end
|
106
126
|
|
data/lib/massive/process.rb
CHANGED
@@ -3,10 +3,15 @@ module Massive
|
|
3
3
|
attributes :id, :created_at, :updated_at, :processed_percentage
|
4
4
|
attribute :completed?, key: :completed
|
5
5
|
|
6
|
+
has_one :file
|
6
7
|
has_many :steps
|
7
8
|
|
8
9
|
def id
|
9
10
|
object.id.to_s
|
10
11
|
end
|
12
|
+
|
13
|
+
def include_file?
|
14
|
+
object.respond_to?(:file)
|
15
|
+
end
|
11
16
|
end
|
12
17
|
end
|
data/lib/massive/step.rb
CHANGED
@@ -9,7 +9,7 @@ module Massive
|
|
9
9
|
include Massive::Locking
|
10
10
|
include Massive::Notifications
|
11
11
|
|
12
|
-
|
12
|
+
belongs_to :process, class_name: 'Massive::Process'
|
13
13
|
embeds_many :jobs, class_name: 'Massive::Job'
|
14
14
|
|
15
15
|
field :total_count, type: Integer
|
data/lib/massive/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Massive::FileSerializer do
|
4
|
+
let(:headers) { ['name', 'description', 'price'] }
|
5
|
+
let(:sample_data) { [['Some name', 'Some desc', 1234], ['Other name', 'Other desc', 5678]] }
|
6
|
+
let(:file) { Massive::File.new(url: 'http://some.url.com', encoding: 'utf8', col_sep: ';', total_count: 1234, use_headers: true, headers: headers, sample_data: sample_data) }
|
7
|
+
subject(:serialized) { described_class.new(file).as_json(root: false) }
|
8
|
+
|
9
|
+
it "serializes file id as string" do
|
10
|
+
serialized[:id].should eq(file.id.to_s)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "serializes url" do
|
14
|
+
serialized[:url].should eq(file.url)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "serializes encoding" do
|
18
|
+
serialized[:encoding].should eq(file.encoding)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "serializes col_sep" do
|
22
|
+
serialized[:col_sep].should eq(file.col_sep)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "serializes total_count" do
|
26
|
+
serialized[:total_count].should eq(file.total_count)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "serializes use_headers" do
|
30
|
+
serialized[:use_headers].should eq(file.use_headers)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "serializes headers" do
|
34
|
+
serialized[:headers].should eq(file.headers)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "serializes sample_data" do
|
38
|
+
serialized[:sample_data].should eq(file.sample_data)
|
39
|
+
end
|
40
|
+
end
|
@@ -8,6 +8,8 @@ describe Massive::Job do
|
|
8
8
|
let(:step) { process.steps.build }
|
9
9
|
subject(:job) { step.jobs.build }
|
10
10
|
|
11
|
+
before { job.stub(:process).and_return(process) }
|
12
|
+
|
11
13
|
describe ".perform" do
|
12
14
|
before do
|
13
15
|
Massive::Process.stub(:find_job).with(process.id, step.id, job.id).and_return(job)
|
@@ -20,9 +22,57 @@ describe Massive::Job do
|
|
20
22
|
end
|
21
23
|
|
22
24
|
describe ".queue" do
|
25
|
+
after { Massive::Job.queue_prefix(:massive_job) }
|
26
|
+
|
23
27
|
it "should be massive_job" do
|
24
28
|
Massive::Job.queue.should eq(:massive_job)
|
25
29
|
end
|
30
|
+
|
31
|
+
it "should use queue_prefix" do
|
32
|
+
Massive::Job.queue_prefix(:my_job_queue)
|
33
|
+
Massive::Job.queue.should eq(:my_job_queue)
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when Massive.split_jobs is set to 100" do
|
37
|
+
before { Massive.split_jobs = 100 }
|
38
|
+
after { Massive.split_jobs = false }
|
39
|
+
|
40
|
+
it "should be massive_job_XXX where XXX is a random number" do
|
41
|
+
values = 10000.times.inject({}) do |memo, index|
|
42
|
+
match = Massive::Job.queue.to_s.match(/massive_job_(\d+)/)
|
43
|
+
memo[match[1].to_i] ||= 0
|
44
|
+
memo[match[1].to_i] += 1
|
45
|
+
memo
|
46
|
+
end
|
47
|
+
|
48
|
+
(1..100).each do |key|
|
49
|
+
expect(values.keys.sort).to include(key)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should use the queue prefix" do
|
54
|
+
Massive::Job.queue_prefix(:my_job_queue)
|
55
|
+
expect(Massive::Job.queue.to_s).to start_with('my_job_queue')
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when Job split_jobs is set to 10" do
|
59
|
+
before { Massive::Job.split_jobs 200 }
|
60
|
+
after { Massive::Job.split_jobs false }
|
61
|
+
|
62
|
+
it "should be massive_job_XXX where XXX is a random number between 1 and 10" do
|
63
|
+
values = 10000.times.inject({}) do |memo, index|
|
64
|
+
match = Massive::Job.queue.to_s.match(/massive_job_(\d+)/)
|
65
|
+
memo[match[1].to_i] ||= 0
|
66
|
+
memo[match[1].to_i] += 1
|
67
|
+
memo
|
68
|
+
end
|
69
|
+
|
70
|
+
(1..200).each do |key|
|
71
|
+
expect(values.keys.sort).to include(key)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
26
76
|
end
|
27
77
|
|
28
78
|
describe "#enqueue" do
|
@@ -219,6 +269,20 @@ describe Massive::Job do
|
|
219
269
|
rescue StandardError, SignalException
|
220
270
|
end
|
221
271
|
end
|
272
|
+
|
273
|
+
context "when it is configured to cancel when failed" do
|
274
|
+
before { Massive::Job.cancel_when_failed true }
|
275
|
+
after { Massive::Job.cancel_when_failed false }
|
276
|
+
|
277
|
+
it "cancels the process" do
|
278
|
+
expect(process).to receive(:cancel)
|
279
|
+
|
280
|
+
begin
|
281
|
+
job.work
|
282
|
+
rescue StandardError, SignalException
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
222
286
|
end
|
223
287
|
|
224
288
|
context "when an error occurs" do
|
@@ -35,4 +35,18 @@ describe Massive::ProcessSerializer do
|
|
35
35
|
serialized[:completed].should be_false
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
context "when it does not respond to file" do
|
40
|
+
it "does not serializes file" do
|
41
|
+
serialized[:file].should be_blank
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when it responds to file" do
|
46
|
+
let(:process) { Massive::FileProcess.new }
|
47
|
+
|
48
|
+
it "serializes file" do
|
49
|
+
serialized[:file].should be_present
|
50
|
+
end
|
51
|
+
end
|
38
52
|
end
|
@@ -1,81 +1,45 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe Massive::Process do
|
4
|
-
subject(:process) { Massive::Process.
|
4
|
+
subject(:process) { Massive::Process.create }
|
5
5
|
|
6
6
|
describe "#enqueue_next" do
|
7
|
-
context "when there
|
8
|
-
let
|
9
|
-
let!(:second_step) { process.steps.build }
|
10
|
-
let!(:third_step) { process.steps.build }
|
7
|
+
context "when there is a next steps" do
|
8
|
+
let(:step) { process.steps.create }
|
11
9
|
|
12
10
|
before do
|
13
|
-
|
14
|
-
second_step.stub(:reload).and_return(second_step)
|
15
|
-
third_step.stub(:reload).and_return(third_step)
|
11
|
+
process.stub(:next_step).and_return(step)
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
process.enqueue_next
|
22
|
-
end
|
23
|
-
|
24
|
-
it "does not enqueue the other steps" do
|
25
|
-
second_step.should_not_receive(:enqueue)
|
26
|
-
third_step.should_not_receive(:enqueue)
|
27
|
-
process.enqueue_next
|
28
|
-
end
|
14
|
+
it "enqueues the step" do
|
15
|
+
step.should_receive(:enqueue)
|
16
|
+
process.enqueue_next
|
29
17
|
end
|
18
|
+
end
|
30
19
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
it "does not enqueue the first step" do
|
35
|
-
first_step.should_not_receive(:enqueue)
|
36
|
-
process.enqueue_next
|
37
|
-
end
|
38
|
-
|
39
|
-
it "enqueues the second step" do
|
40
|
-
second_step.should_receive(:enqueue)
|
41
|
-
process.enqueue_next
|
42
|
-
end
|
43
|
-
|
44
|
-
it "does not enqueue the third step" do
|
45
|
-
third_step.should_not_receive(:enqueue)
|
46
|
-
process.enqueue_next
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
context "and the first one is enqueued" do
|
51
|
-
before { first_step.stub(:enqueued?).and_return(true) }
|
52
|
-
|
53
|
-
it "does not enqueue the next step" do
|
54
|
-
second_step.should_not_receive(:enqueue)
|
55
|
-
process.enqueue_next
|
56
|
-
end
|
20
|
+
context "when there is no next step" do
|
21
|
+
before do
|
22
|
+
process.stub(:next_step).and_return(nil)
|
57
23
|
end
|
58
24
|
|
59
|
-
|
60
|
-
|
61
|
-
process.steps.each do |step|
|
62
|
-
step.finished_at = Time.now
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
it "does not enqueue any of the steps" do
|
67
|
-
process.steps.each do |step|
|
68
|
-
step.should_not_receive(:enqueue)
|
69
|
-
end
|
70
|
-
|
25
|
+
it "does not raise error" do
|
26
|
+
expect {
|
71
27
|
process.enqueue_next
|
72
|
-
|
28
|
+
}.to_not raise_error
|
73
29
|
end
|
74
30
|
end
|
75
31
|
end
|
76
32
|
|
77
33
|
describe "#next_step" do
|
78
|
-
let!(:step) { process.steps.
|
34
|
+
let!(:step) { process.steps.create }
|
35
|
+
|
36
|
+
before do
|
37
|
+
steps = double('Array')
|
38
|
+
process.stub(:steps).and_return(steps)
|
39
|
+
steps.stub(:not_completed).and_return(steps)
|
40
|
+
steps.stub(:not_started).and_return(steps)
|
41
|
+
steps.stub(:first).and_return(step)
|
42
|
+
end
|
79
43
|
|
80
44
|
context "when the step is enqueued" do
|
81
45
|
before { step.stub(:enqueued?).and_return(true) }
|
@@ -84,14 +48,14 @@ describe Massive::Process do
|
|
84
48
|
end
|
85
49
|
|
86
50
|
context "when the step is not enqueued" do
|
51
|
+
before { step.stub(:enqueued?).and_return(false) }
|
52
|
+
|
87
53
|
its(:next_step) { should eq step }
|
88
54
|
end
|
89
55
|
end
|
90
56
|
|
91
57
|
describe ".find_step" do
|
92
|
-
let!(:step) { process.steps.
|
93
|
-
|
94
|
-
before { process.save }
|
58
|
+
let!(:step) { process.steps.create }
|
95
59
|
|
96
60
|
it "returns the step with id within the process" do
|
97
61
|
Massive::Process.find_step(process.id, step.id).should eq(step)
|
@@ -99,10 +63,8 @@ describe Massive::Process do
|
|
99
63
|
end
|
100
64
|
|
101
65
|
describe ".find_job" do
|
102
|
-
let!(:step) { process.steps.
|
103
|
-
let!(:job) { step.jobs.
|
104
|
-
|
105
|
-
before { process.save }
|
66
|
+
let!(:step) { process.steps.create }
|
67
|
+
let!(:job) { step.jobs.create }
|
106
68
|
|
107
69
|
it "returns the job with id within the step of the process" do
|
108
70
|
Massive::Process.find_job(process.id, step.id, job.id).should eq(job)
|
@@ -110,8 +72,8 @@ describe Massive::Process do
|
|
110
72
|
end
|
111
73
|
|
112
74
|
describe "#processed_percentage" do
|
113
|
-
let(:step_1) { process.steps.
|
114
|
-
let(:step_2) { process.steps.
|
75
|
+
let(:step_1) { process.steps.create(weight: 9) }
|
76
|
+
let(:step_2) { process.steps.create }
|
115
77
|
|
116
78
|
context "when the process have not started" do
|
117
79
|
before do
|
@@ -162,19 +124,19 @@ describe Massive::Process do
|
|
162
124
|
end
|
163
125
|
|
164
126
|
context "when the total weight of the steps is zero" do
|
165
|
-
let(:step_1) { process.steps.
|
166
|
-
let(:step_2) { process.steps.
|
127
|
+
let(:step_1) { process.steps.create(weight: 0) }
|
128
|
+
let(:step_2) { process.steps.create(weight: 0) }
|
167
129
|
|
168
130
|
its(:processed_percentage) { should eq 0 }
|
169
131
|
end
|
170
132
|
end
|
171
133
|
|
172
134
|
describe "#completed?" do
|
173
|
-
let!(:step_1) { process.steps.build }
|
174
|
-
let!(:step_2) { process.steps.build }
|
175
|
-
|
176
135
|
before { process.save }
|
177
136
|
|
137
|
+
let!(:step_1) { process.steps.create }
|
138
|
+
let!(:step_2) { process.steps.create }
|
139
|
+
|
178
140
|
context "when the steps are incompleted steps" do
|
179
141
|
its(:completed?) { should be_false }
|
180
142
|
end
|
@@ -190,8 +152,8 @@ describe Massive::Process do
|
|
190
152
|
end
|
191
153
|
|
192
154
|
describe "#failed?" do
|
193
|
-
let!(:step_1) { process.steps.
|
194
|
-
let!(:step_2) { process.steps.
|
155
|
+
let!(:step_1) { process.steps.create }
|
156
|
+
let!(:step_2) { process.steps.create }
|
195
157
|
|
196
158
|
before { process.save }
|
197
159
|
|
@@ -7,6 +7,8 @@ describe Massive::Step do
|
|
7
7
|
let(:process) { Massive::Process.new }
|
8
8
|
subject(:step) { process.steps.build }
|
9
9
|
|
10
|
+
before { step.stub(:process).and_return(process) }
|
11
|
+
|
10
12
|
describe ".perform" do
|
11
13
|
before do
|
12
14
|
Massive::Process.stub(:find_step).with(process.id, step.id).and_return(step)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: massive
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vicente Mundim
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: resque
|
@@ -91,6 +91,7 @@ files:
|
|
91
91
|
- lib/massive/file.rb
|
92
92
|
- lib/massive/file_job.rb
|
93
93
|
- lib/massive/file_process.rb
|
94
|
+
- lib/massive/file_serializer.rb
|
94
95
|
- lib/massive/file_step.rb
|
95
96
|
- lib/massive/job.rb
|
96
97
|
- lib/massive/locking.rb
|
@@ -113,6 +114,7 @@ files:
|
|
113
114
|
- spec/models/massive/authenticators/s3_spec.rb
|
114
115
|
- spec/models/massive/cancelling_spec.rb
|
115
116
|
- spec/models/massive/file_job_spec.rb
|
117
|
+
- spec/models/massive/file_serializer_spec.rb
|
116
118
|
- spec/models/massive/file_spec.rb
|
117
119
|
- spec/models/massive/file_step_spec.rb
|
118
120
|
- spec/models/massive/job_spec.rb
|
@@ -160,6 +162,7 @@ test_files:
|
|
160
162
|
- spec/models/massive/authenticators/s3_spec.rb
|
161
163
|
- spec/models/massive/cancelling_spec.rb
|
162
164
|
- spec/models/massive/file_job_spec.rb
|
165
|
+
- spec/models/massive/file_serializer_spec.rb
|
163
166
|
- spec/models/massive/file_spec.rb
|
164
167
|
- spec/models/massive/file_step_spec.rb
|
165
168
|
- spec/models/massive/job_spec.rb
|