eq 0.0.1 → 0.1.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.
- data/.gitignore +1 -0
- data/README.md +51 -11
- data/TODO.md +10 -0
- data/benchmarks/all.rb +13 -0
- data/benchmarks/parallel.rb +23 -0
- data/benchmarks/queue_backend_benchmark.rb +27 -0
- data/benchmarks/queueing.rb +13 -23
- data/benchmarks/working.rb +14 -25
- data/eq.gemspec +12 -2
- data/examples/queueing.rb +2 -2
- data/examples/scheduling.rb +19 -0
- data/examples/simple_usage.rb +20 -8
- data/examples/working.rb +2 -2
- data/lib/eq-queueing.rb +4 -13
- data/lib/eq-queueing/backends.rb +30 -1
- data/lib/eq-queueing/backends/leveldb.rb +232 -0
- data/lib/eq-queueing/backends/sequel.rb +34 -17
- data/lib/eq-queueing/queue.rb +26 -20
- data/lib/eq-scheduling.rb +33 -0
- data/lib/eq-scheduling/scheduler.rb +19 -0
- data/lib/eq-web.rb +5 -0
- data/lib/eq-web/server.rb +39 -0
- data/lib/eq-web/views/index.erb +45 -0
- data/lib/eq-working.rb +15 -7
- data/lib/eq-working/worker.rb +30 -3
- data/lib/eq.rb +39 -31
- data/lib/eq/boot/all.rb +1 -0
- data/lib/eq/boot/scheduling.rb +1 -0
- data/lib/eq/error.rb +4 -0
- data/lib/eq/job.rb +22 -16
- data/lib/eq/version.rb +1 -1
- data/log/.gitkeep +1 -0
- data/spec/lib/eq-queueing/backends/leveldb_spec.rb +32 -0
- data/spec/lib/eq-queueing/backends/sequel_spec.rb +5 -4
- data/spec/lib/eq-queueing/queue_spec.rb +27 -58
- data/spec/lib/eq-queueing_spec.rb +16 -0
- data/spec/lib/eq-scheduling_spec.rb +7 -0
- data/spec/lib/eq-working/worker_spec.rb +13 -0
- data/spec/lib/eq/job_spec.rb +16 -11
- data/spec/lib/eq_spec.rb +1 -1
- data/spec/mocks/a_job.rb +4 -0
- data/spec/mocks/a_unique_job.rb +6 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/support/shared_examples_for_queue.rb +60 -31
- metadata +80 -8
- data/lib/eq-working/manager.rb +0 -31
- data/lib/eq-working/system.rb +0 -10
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EQ do
|
4
|
+
context 'transient queueing' do
|
5
|
+
it "won't survives at least a dying queue actor" do
|
6
|
+
# setup a in-memory queue backend
|
7
|
+
EQ.config {|c| c.queue = 'sequel'; c.sequel = 'sqlite:/'}
|
8
|
+
EQ.boot :queue
|
9
|
+
EQ.queue.push AJob
|
10
|
+
EQ.queue.count.should == 1
|
11
|
+
EQ.shutdown
|
12
|
+
EQ.boot :queue
|
13
|
+
EQ.queue.count.should == 0
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/spec/lib/eq/job_spec.rb
CHANGED
@@ -1,26 +1,31 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe EQ::Job do
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
describe EQ::Job do
|
4
|
+
|
5
|
+
it 'creates a job with payload' do
|
6
|
+
job = EQ::Job.new nil, EQ::Job, ['bar', 'foo']
|
7
|
+
job.id.should == nil
|
8
|
+
job.queue.should == "EQ::Job"
|
9
|
+
job.job_class.should == EQ::Job
|
10
|
+
job.payload.should == ['bar', 'foo']
|
7
11
|
end
|
8
12
|
|
9
|
-
it '
|
10
|
-
|
11
|
-
job
|
12
|
-
job.
|
13
|
+
it 'creates a job without payload' do
|
14
|
+
job = EQ::Job.new nil, EQ::Job
|
15
|
+
job.id.should == nil
|
16
|
+
job.queue.should == "EQ::Job"
|
17
|
+
job.job_class.should == EQ::Job
|
18
|
+
job.payload.should == nil
|
13
19
|
end
|
14
20
|
|
15
|
-
it 'performs using
|
21
|
+
it 'performs using queue.perform(*payload)' do
|
16
22
|
class MyJob
|
17
23
|
def self.perform(*args)
|
18
24
|
{result: args}
|
19
25
|
end
|
20
26
|
end
|
21
27
|
my_job_args = [1,2,3]
|
22
|
-
|
23
|
-
job = EQ::Job.load(1, serialized_payload)
|
28
|
+
job = EQ::Job.new(nil, MyJob, my_job_args)
|
24
29
|
job.perform.should == {result: my_job_args}
|
25
30
|
end
|
26
31
|
end
|
data/spec/lib/eq_spec.rb
CHANGED
data/spec/mocks/a_job.rb
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -4,8 +4,14 @@
|
|
4
4
|
# loaded once.
|
5
5
|
#
|
6
6
|
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
|
8
|
+
require 'fileutils'
|
9
|
+
|
7
10
|
require File.join(File.dirname(__FILE__), '..', 'lib', 'eq', 'boot', 'all')
|
8
11
|
Dir[File.join(File.dirname(__FILE__), '/support/**/*.rb')].each {|f| require f; puts f}
|
12
|
+
Dir[File.join(File.dirname(__FILE__), '/mocks/**/*.rb')].each {|f| require f; puts f}
|
13
|
+
|
14
|
+
Celluloid.logger = Logger.new(File.join(File.dirname(__FILE__), '..', 'log', 'rspec.log'))
|
9
15
|
|
10
16
|
RSpec.configure do |config|
|
11
17
|
config.treat_symbols_as_metadata_keys_with_true_values = true
|
@@ -17,6 +23,12 @@ RSpec.configure do |config|
|
|
17
23
|
# the seed, which is printed after each run.
|
18
24
|
# --seed 1234
|
19
25
|
config.order = 'random'
|
26
|
+
|
27
|
+
config.before :suite do
|
28
|
+
# cleanup rspec files
|
29
|
+
FileUtils.rm_rf 'tmp/rspec'
|
30
|
+
FileUtils.mkdir_p 'tmp/rspec'
|
31
|
+
end
|
20
32
|
end
|
21
33
|
|
22
34
|
require "timecop"
|
@@ -1,75 +1,104 @@
|
|
1
1
|
shared_examples_for 'queue backend' do
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
let(:eq_job) { EQ::Job.new(nil, AJob, 'foo') }
|
3
|
+
|
4
|
+
it 'has no jobs at the beginning' do
|
5
|
+
subject.count(:jobs).should == 0
|
6
|
+
subject.count(:waiting).should == 0
|
7
|
+
subject.count(:working).should == 0
|
7
8
|
end
|
8
|
-
end
|
9
9
|
|
10
|
-
shared_examples_for 'abstract queue' do
|
11
10
|
it 'pushes jobs' do
|
12
|
-
subject.
|
13
|
-
subject.
|
14
|
-
subject.
|
15
|
-
subject.
|
16
|
-
subject.working_count.should == 0
|
11
|
+
subject.push(eq_job).should_not be_nil # job_id
|
12
|
+
subject.count(:jobs).should == 1
|
13
|
+
subject.count(:waiting).should == 1
|
14
|
+
subject.count(:working).should == 0
|
17
15
|
end
|
18
16
|
|
19
17
|
it 'reserves jobs' do
|
20
|
-
id = subject.push
|
21
|
-
subject.
|
22
|
-
subject.
|
23
|
-
subject.
|
24
|
-
subject.
|
25
|
-
|
26
|
-
subject.
|
18
|
+
id = subject.push eq_job
|
19
|
+
subject.count(:jobs).should == 1
|
20
|
+
subject.count(:waiting).should == 1
|
21
|
+
subject.count(:working).should == 0
|
22
|
+
job = subject.reserve
|
23
|
+
id.should == job.id
|
24
|
+
subject.count(:jobs).should == 1
|
25
|
+
subject.count(:waiting).should == 0
|
26
|
+
subject.count(:working).should == 1
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'pops jobs' do
|
30
30
|
subject.pop(1).should be_false # no job
|
31
|
-
subject.push
|
32
|
-
subject.
|
31
|
+
job_id = subject.push eq_job
|
32
|
+
subject.count(:jobs).should == 1
|
33
|
+
subject.count(:waiting).should == 1
|
34
|
+
subject.count(:working).should == 0
|
35
|
+
subject.pop(job_id).should be_true # one job
|
36
|
+
subject.count(:jobs).should == 0
|
37
|
+
subject.count(:waiting).should == 0
|
38
|
+
subject.count(:working).should == 0
|
33
39
|
subject.pop(1).should be_false # again no job"
|
34
40
|
end
|
35
41
|
|
42
|
+
it 'clears jobs' do
|
43
|
+
10.times { subject.push(eq_job) }
|
44
|
+
subject.count.should == 10
|
45
|
+
subject.clear
|
46
|
+
subject.count.should == 0
|
47
|
+
end
|
48
|
+
|
36
49
|
it 'puts working job back on waiting when they timeout via #requeue_timed_out_jobs' do
|
37
50
|
# freeze time on start of 1986
|
38
51
|
Timecop.freeze(Time.new(1986)) do
|
39
52
|
|
40
53
|
# create a job
|
41
|
-
id = subject.push
|
54
|
+
id = subject.push eq_job
|
42
55
|
|
43
56
|
# start working
|
44
57
|
data = subject.reserve
|
45
58
|
|
46
59
|
# no on working at the beginning
|
47
|
-
subject.
|
48
|
-
subject.
|
60
|
+
subject.count(:waiting).should == 0
|
61
|
+
subject.count(:working).should == 1
|
49
62
|
|
50
63
|
# no one will be re-enqueued
|
51
64
|
subject.requeue_timed_out_jobs.should == 0
|
52
65
|
|
53
66
|
# no on working after senseless re-enqueueing
|
54
|
-
subject.
|
55
|
-
subject.
|
56
|
-
|
67
|
+
subject.count(:waiting).should == 0
|
68
|
+
subject.count(:working).should == 1
|
57
69
|
end
|
58
70
|
|
59
71
|
# freeze the time to 10s in the future
|
60
72
|
Timecop.freeze(Time.new(1986, 01, 01, 00, 00, EQ.config.job_timeout)) do
|
61
73
|
|
62
74
|
# nothing happened yet...
|
63
|
-
subject.
|
64
|
-
subject.
|
75
|
+
subject.count(:waiting).should == 0
|
76
|
+
subject.count(:working).should == 1
|
65
77
|
|
66
78
|
# this time one will be re-enqueued
|
67
79
|
subject.requeue_timed_out_jobs.should == 1
|
68
80
|
|
69
81
|
# now the old job is available again
|
70
|
-
subject.
|
71
|
-
subject.
|
82
|
+
subject.count(:waiting).should == 1
|
83
|
+
subject.count(:working).should == 0
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'unique jobs' do
|
88
|
+
it 'does not enqueue multiple times when args are the same' do
|
89
|
+
subject.count.should == 0
|
90
|
+
id = subject.push EQ::Job.new(nil, AUniqueJob)
|
91
|
+
subject.count.should == 1
|
92
|
+
id = subject.push EQ::Job.new(nil, AUniqueJob)
|
93
|
+
subject.count.should == 1
|
94
|
+
end
|
72
95
|
|
96
|
+
it 'does enqueue multiple times when args differ' do
|
97
|
+
subject.count.should == 0
|
98
|
+
id = subject.push EQ::Job.new(nil, AUniqueJob, 'foo')
|
99
|
+
subject.count.should == 1
|
100
|
+
id = subject.push EQ::Job.new(nil, AUniqueJob, 'bar')
|
101
|
+
subject.count.should == 2
|
73
102
|
end
|
74
103
|
end
|
75
104
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-09-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: celluloid
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sinatra
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: clockwork
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
30
62
|
- !ruby/object:Gem::Dependency
|
31
63
|
name: sequel
|
32
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -35,7 +67,7 @@ dependencies:
|
|
35
67
|
- - ! '>='
|
36
68
|
- !ruby/object:Gem::Version
|
37
69
|
version: '0'
|
38
|
-
type: :
|
70
|
+
type: :development
|
39
71
|
prerelease: false
|
40
72
|
version_requirements: !ruby/object:Gem::Requirement
|
41
73
|
none: false
|
@@ -44,14 +76,30 @@ dependencies:
|
|
44
76
|
- !ruby/object:Gem::Version
|
45
77
|
version: '0'
|
46
78
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
79
|
+
name: sqlite3
|
48
80
|
requirement: !ruby/object:Gem::Requirement
|
49
81
|
none: false
|
50
82
|
requirements:
|
51
83
|
- - ! '>='
|
52
84
|
- !ruby/object:Gem::Version
|
53
85
|
version: '0'
|
54
|
-
type: :
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: leveldb-ruby
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
55
103
|
prerelease: false
|
56
104
|
version_requirements: !ruby/object:Gem::Requirement
|
57
105
|
none: false
|
@@ -155,31 +203,49 @@ files:
|
|
155
203
|
- LICENSE
|
156
204
|
- README.md
|
157
205
|
- Rakefile
|
206
|
+
- TODO.md
|
207
|
+
- benchmarks/all.rb
|
208
|
+
- benchmarks/parallel.rb
|
209
|
+
- benchmarks/queue_backend_benchmark.rb
|
158
210
|
- benchmarks/queueing.rb
|
159
211
|
- benchmarks/working.rb
|
160
212
|
- eq.gemspec
|
161
213
|
- examples/queueing.rb
|
214
|
+
- examples/scheduling.rb
|
162
215
|
- examples/simple_usage.rb
|
163
216
|
- examples/working.rb
|
164
217
|
- lib/eq-queueing.rb
|
165
218
|
- lib/eq-queueing/backends.rb
|
219
|
+
- lib/eq-queueing/backends/leveldb.rb
|
166
220
|
- lib/eq-queueing/backends/sequel.rb
|
167
221
|
- lib/eq-queueing/queue.rb
|
222
|
+
- lib/eq-scheduling.rb
|
223
|
+
- lib/eq-scheduling/scheduler.rb
|
224
|
+
- lib/eq-web.rb
|
225
|
+
- lib/eq-web/server.rb
|
226
|
+
- lib/eq-web/views/index.erb
|
168
227
|
- lib/eq-working.rb
|
169
|
-
- lib/eq-working/manager.rb
|
170
|
-
- lib/eq-working/system.rb
|
171
228
|
- lib/eq-working/worker.rb
|
172
229
|
- lib/eq.rb
|
173
230
|
- lib/eq/boot/all.rb
|
174
231
|
- lib/eq/boot/queueing.rb
|
232
|
+
- lib/eq/boot/scheduling.rb
|
175
233
|
- lib/eq/boot/working.rb
|
234
|
+
- lib/eq/error.rb
|
176
235
|
- lib/eq/job.rb
|
177
236
|
- lib/eq/logging.rb
|
178
237
|
- lib/eq/version.rb
|
238
|
+
- log/.gitkeep
|
239
|
+
- spec/lib/eq-queueing/backends/leveldb_spec.rb
|
179
240
|
- spec/lib/eq-queueing/backends/sequel_spec.rb
|
180
241
|
- spec/lib/eq-queueing/queue_spec.rb
|
242
|
+
- spec/lib/eq-queueing_spec.rb
|
243
|
+
- spec/lib/eq-scheduling_spec.rb
|
244
|
+
- spec/lib/eq-working/worker_spec.rb
|
181
245
|
- spec/lib/eq/job_spec.rb
|
182
246
|
- spec/lib/eq_spec.rb
|
247
|
+
- spec/mocks/a_job.rb
|
248
|
+
- spec/mocks/a_unique_job.rb
|
183
249
|
- spec/spec_helper.rb
|
184
250
|
- spec/support/shared_examples_for_queue.rb
|
185
251
|
homepage: https://github.com/dpree/eq
|
@@ -208,10 +274,16 @@ specification_version: 3
|
|
208
274
|
summary: Based on Celluloid (multi-threading) and Sequel (SQLite3, MySQL, PostgreSQL,
|
209
275
|
...).
|
210
276
|
test_files:
|
277
|
+
- spec/lib/eq-queueing/backends/leveldb_spec.rb
|
211
278
|
- spec/lib/eq-queueing/backends/sequel_spec.rb
|
212
279
|
- spec/lib/eq-queueing/queue_spec.rb
|
280
|
+
- spec/lib/eq-queueing_spec.rb
|
281
|
+
- spec/lib/eq-scheduling_spec.rb
|
282
|
+
- spec/lib/eq-working/worker_spec.rb
|
213
283
|
- spec/lib/eq/job_spec.rb
|
214
284
|
- spec/lib/eq_spec.rb
|
285
|
+
- spec/mocks/a_job.rb
|
286
|
+
- spec/mocks/a_unique_job.rb
|
215
287
|
- spec/spec_helper.rb
|
216
288
|
- spec/support/shared_examples_for_queue.rb
|
217
289
|
has_rdoc:
|
data/lib/eq-working/manager.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module EQ::Working
|
2
|
-
class Manager
|
3
|
-
include Celluloid
|
4
|
-
include EQ::Logging
|
5
|
-
|
6
|
-
def initialize
|
7
|
-
run!
|
8
|
-
end
|
9
|
-
|
10
|
-
# polls the EQ.queue via EQ.queue.reserve
|
11
|
-
def run
|
12
|
-
debug "worker manager running"
|
13
|
-
loop do
|
14
|
-
if EQ.queue && job = EQ.queue.reserve
|
15
|
-
debug "got #{job.inspect}"
|
16
|
-
if worker = EQ::Working.worker_pool
|
17
|
-
debug ' - found worker'
|
18
|
-
worker.process! job
|
19
|
-
else
|
20
|
-
debug ' - no worker'
|
21
|
-
end
|
22
|
-
else
|
23
|
-
# currently no job
|
24
|
-
end
|
25
|
-
sleep 0.01
|
26
|
-
end
|
27
|
-
rescue Celluloid::DeadActorError
|
28
|
-
retry
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|