massive 0.3.0 → 0.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6add55169f9bbe782d2ee00b8a033a21aae4d9cb
4
- data.tar.gz: 3e7ef6017201515489a3e8f04fb41b8669b701cd
3
+ metadata.gz: d0ad236ec732665de7fcf03668e8ce4675da4344
4
+ data.tar.gz: acba7ff61e45ff129881fa0d86b49480eaa85912
5
5
  SHA512:
6
- metadata.gz: a2470c8e5230e4b2f4e12a47e93722e16da720971c15c67179aa8f053a1907c1322309f19fdef0572c43211d0b56f62a7d159d6a0c25422ab61cd339deab9a18
7
- data.tar.gz: 2e48d557a63fa84092f83acabca19ba70b3d21559bbb0f96f25dee3ee97c16b96e0daac07ccf26c40377046787184d8c5810ec1f00b9831ad54f100073a73b5f
6
+ metadata.gz: 1c922037b0dc37a497a6cced3880e88436912e6d3c8ff35ab8fc80c18f3375fbf4262551ea66ad82b7c5d065d0b20cb168c752400c28382df774027423687fe3
7
+ data.tar.gz: 122c02cc041df10b737ac8d6457d2bda985bb2930037672df0da4febe828648a9029829c08161597e9a5def1442e3f176062856fb15f52b7d4b72965f3d3c3b7
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- massive (0.3.0)
4
+ massive (0.4.0)
5
5
  active_model_serializers
6
6
  file_processor (= 0.2.0)
7
7
  mongoid (~> 4.0.0.beta)
@@ -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
@@ -0,0 +1,9 @@
1
+ module Massive
2
+ class FileSerializer < ActiveModel::Serializer
3
+ attributes :id, :url, :encoding, :col_sep, :total_count, :use_headers, :headers, :sample_data
4
+
5
+ def id
6
+ object.id.to_s
7
+ end
8
+ end
9
+ end
@@ -26,7 +26,26 @@ module Massive
26
26
  end
27
27
 
28
28
  def self.queue
29
- :massive_job
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
 
@@ -5,7 +5,7 @@ module Massive
5
5
 
6
6
  field :cancelled_at, type: Time
7
7
 
8
- embeds_many :steps, class_name: 'Massive::Step'
8
+ has_many :steps, class_name: 'Massive::Step', dependent: :destroy
9
9
 
10
10
  def self.find_step(process_id, step_id)
11
11
  find(process_id).steps.find(step_id)
@@ -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
@@ -9,7 +9,7 @@ module Massive
9
9
  include Massive::Locking
10
10
  include Massive::Notifications
11
11
 
12
- embedded_in :process, class_name: 'Massive::Process'
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
@@ -1,3 +1,3 @@
1
1
  module Massive
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -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.new }
4
+ subject(:process) { Massive::Process.create }
5
5
 
6
6
  describe "#enqueue_next" do
7
- context "when there are steps" do
8
- let!(:first_step) { process.steps.build }
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
- first_step.stub(:reload).and_return(first_step)
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
- context "and none of them are completed" do
19
- it "enqueues the first step" do
20
- first_step.should_receive(:enqueue)
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
- context "and the first one is completed, but the second one is not" do
32
- before { first_step.finished_at = Time.now }
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
- context "but all of them are completed" do
60
- before do
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
- end
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.build }
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.build }
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.build }
103
- let!(:job) { step.jobs.build }
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.build(weight: 9) }
114
- let(:step_2) { process.steps.build }
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.build(weight: 0) }
166
- let(:step_2) { process.steps.build(weight: 0) }
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.build }
194
- let!(:step_2) { process.steps.build }
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.3.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: 2014-05-15 00:00:00.000000000 Z
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