disc 0.0.21 → 0.0.22
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 +4 -4
- data/.travis.yml +21 -0
- data/README.md +5 -5
- data/lib/disc/version.rb +1 -1
- data/lib/disc.rb +17 -4
- data/test/disc_test.rb +98 -54
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c6bf616dea2ead6c544788565f1b487ddaedeffa
|
4
|
+
data.tar.gz: 191da0a289ac1ec6b1b60d76d547e996b7e56083
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 83c6e1a7cf0aaba55e156097a8f02f772227854fb93fcca59d10acd15df8dff8b1d4dc1582af091b1e926f2d5b011f2d122a64eb53223f2d841fbe87ea45485f
|
7
|
+
data.tar.gz: 212a4df34ad33ad7865e934e46964517aa77a6127d9545653ee148f9cdfcbfa3bebad9903577e35163939d9888df6e6a1cf2428022224b38319923ea1858dddf
|
data/.travis.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2
|
4
|
+
sudo: false
|
5
|
+
cache:
|
6
|
+
bundler: false
|
7
|
+
directories:
|
8
|
+
- disque
|
9
|
+
- gems
|
10
|
+
before_install:
|
11
|
+
- test -d disque/.git || git clone -n https://github.com/antirez/disque.git
|
12
|
+
- cd disque && git fetch origin && git checkout -f master && make && cd ..
|
13
|
+
install:
|
14
|
+
- export GEM_HOME=$PWD/gems/$RUBY_VERSION
|
15
|
+
- export GEM_PATH=$GEM_HOME:$GEM_PATH
|
16
|
+
- export PATH=$GEM_HOME/bin:$PWD/disque/src:$PATH
|
17
|
+
- mkdir -p $GEM_HOME
|
18
|
+
- which dep || gem install dep
|
19
|
+
- dep install
|
20
|
+
before_script: disque-server --daemonize yes
|
21
|
+
script: make test
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Disc
|
1
|
+
# Disc [](https://travis-ci.org/pote/disc)
|
2
2
|
|
3
3
|
Disc fills the gap between your Ruby service objects and [antirez](http://antirez.com/)'s wonderful [Disque](https://github.com/antirez/disque) backend.
|
4
4
|
|
@@ -58,10 +58,10 @@ Disc fills the gap between your Ruby service objects and [antirez](http://antire
|
|
58
58
|
```bash
|
59
59
|
$ QUEUES=urgent,default disc -r ./disc_init.rb
|
60
60
|
```
|
61
|
-
|
61
|
+
|
62
62
|
## Notes about Jobs
|
63
63
|
|
64
|
-
Jobs are fairly
|
64
|
+
Jobs are fairly straightforward Ruby classes, internally Disc serializes them to MessagePack so they can be stored in Disque, this has a few implications:
|
65
65
|
|
66
66
|
* Don't enqueue complex objects! Instead of `user`, enqueue `user.id`!
|
67
67
|
* If your job takes multiple arguments, you'll want to pass all those arguments in the first parameter of `#enqueue` as an array.
|
@@ -72,7 +72,7 @@ Example:
|
|
72
72
|
class ComplexJob
|
73
73
|
include Disc::Job
|
74
74
|
disc queue: 'urgent'
|
75
|
-
|
75
|
+
|
76
76
|
def perform(first_parameter, second_parameter)
|
77
77
|
# do things...
|
78
78
|
end
|
@@ -191,7 +191,7 @@ more information.
|
|
191
191
|
## Acknowledgements
|
192
192
|
|
193
193
|
* To [@foca](https://github.com/foca) for helping me ship a quality thing and putting up with my constant whining.
|
194
|
-
* To [@antirez](https://github
|
194
|
+
* To [@antirez](https://github.com/antirez) for Redis, Disque, and his refreshing way of programming wonderful tools.
|
195
195
|
* To [@soveran](https://github.com/soveran) for pushing me to work on this and publishing gems that keep me enjoying ruby.
|
196
196
|
* To [all contributors](https://github.com/pote/disc/graphs/contributors)
|
197
197
|
|
data/lib/disc/version.rb
CHANGED
data/lib/disc.rb
CHANGED
@@ -28,6 +28,14 @@ class Disc
|
|
28
28
|
@disque_timeout = timeout
|
29
29
|
end
|
30
30
|
|
31
|
+
def self.default_queue
|
32
|
+
@default_queue ||= 'default'
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.default_queue=(queue)
|
36
|
+
@default_queue = queue
|
37
|
+
end
|
38
|
+
|
31
39
|
def self.on_error(exception, job)
|
32
40
|
$stderr.puts exception
|
33
41
|
end
|
@@ -101,7 +109,8 @@ class Disc
|
|
101
109
|
@disque = disque
|
102
110
|
end
|
103
111
|
|
104
|
-
def disc(
|
112
|
+
def disc(queue: nil, **options)
|
113
|
+
@queue = queue
|
105
114
|
@disc_options = options
|
106
115
|
end
|
107
116
|
|
@@ -110,10 +119,14 @@ class Disc
|
|
110
119
|
end
|
111
120
|
|
112
121
|
def queue
|
113
|
-
|
122
|
+
@queue || Disc.default_queue
|
114
123
|
end
|
115
124
|
|
116
|
-
def enqueue(args = [], at: nil, queue: nil)
|
125
|
+
def enqueue(args = [], at: nil, queue: nil, **options)
|
126
|
+
options = disc_options.merge(options).tap do |opt|
|
127
|
+
opt[:delay] = at.to_time.to_i - DateTime.now.to_time.to_i unless at.nil?
|
128
|
+
end
|
129
|
+
|
117
130
|
disque.push(
|
118
131
|
queue || self.queue,
|
119
132
|
{
|
@@ -121,7 +134,7 @@ class Disc
|
|
121
134
|
arguments: Array(args)
|
122
135
|
}.to_msgpack,
|
123
136
|
Disc.disque_timeout,
|
124
|
-
|
137
|
+
options
|
125
138
|
)
|
126
139
|
end
|
127
140
|
end
|
data/test/disc_test.rb
CHANGED
@@ -2,6 +2,7 @@ require 'cutest'
|
|
2
2
|
require 'disc'
|
3
3
|
require 'msgpack'
|
4
4
|
require 'pty'
|
5
|
+
require 'timeout'
|
5
6
|
|
6
7
|
require_relative '../examples/echoer'
|
7
8
|
# class Echoer
|
@@ -30,10 +31,29 @@ require_relative '../examples/failer'
|
|
30
31
|
# end
|
31
32
|
|
32
33
|
prepare do
|
34
|
+
Disc.disque_timeout = 1 # 1ms so we don't wait at all.
|
33
35
|
Disc.disque.call('DEBUG', 'FLUSHALL')
|
34
36
|
end
|
35
37
|
|
36
38
|
scope do
|
39
|
+
# Runs a given command, yielding the stdout (as an IO) and the PID (a String).
|
40
|
+
# Makes sure the process finishes after the block runs.
|
41
|
+
def run(command)
|
42
|
+
out, _, pid = PTY.spawn(command)
|
43
|
+
yield out, pid
|
44
|
+
ensure
|
45
|
+
Process.kill("KILL", pid)
|
46
|
+
sleep 0.1 # Make sure we give it time to finish.
|
47
|
+
end
|
48
|
+
|
49
|
+
# Checks whether a process is running.
|
50
|
+
def is_running?(pid)
|
51
|
+
Process.getpgid(pid)
|
52
|
+
true
|
53
|
+
rescue Errno::ESRCH
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
37
57
|
test 'jobs are enqueued to the correct Disque queue with appropriate parameters and class' do
|
38
58
|
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3])
|
39
59
|
|
@@ -59,16 +79,16 @@ scope do
|
|
59
79
|
end
|
60
80
|
|
61
81
|
test 'enqueue at timestamp behaves properly' do
|
62
|
-
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], at: Time.now +
|
82
|
+
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], at: Time.now + 1)
|
63
83
|
|
64
84
|
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
65
85
|
assert jobs.empty?
|
66
86
|
|
67
|
-
sleep
|
87
|
+
sleep 0.5
|
68
88
|
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
69
89
|
assert jobs.empty?
|
70
90
|
|
71
|
-
sleep
|
91
|
+
sleep 0.5
|
72
92
|
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
73
93
|
assert jobs.any?
|
74
94
|
assert_equal 1, jobs.size
|
@@ -85,68 +105,92 @@ scope do
|
|
85
105
|
end
|
86
106
|
|
87
107
|
test 'jobs are executed' do
|
88
|
-
|
89
|
-
Echoer.enqueue(['one argument', { random: 'data' }, 3])
|
90
|
-
|
91
|
-
cout, _, pid = PTY.spawn(
|
92
|
-
'QUEUES=test,default ruby -Ilib bin/disc -r ./examples/echoer'
|
93
|
-
)
|
94
|
-
sleep 0.5
|
108
|
+
Echoer.enqueue(['one argument', { random: 'data' }, 3])
|
95
109
|
|
110
|
+
run('QUEUES=test ruby -Ilib bin/disc -r ./examples/echoer') do |cout, pid|
|
111
|
+
output = Timeout.timeout(1) { cout.take(3) }
|
96
112
|
jobs = Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1)
|
97
113
|
assert jobs.nil?
|
98
|
-
|
99
|
-
matched = false
|
100
|
-
counter = 0
|
101
|
-
while !matched && counter < 3
|
102
|
-
counter += 1
|
103
|
-
matched = cout.gets.match(/First: one argument, Second: {"random"=>"data"}, Third: 3/)
|
104
|
-
end
|
105
|
-
|
106
|
-
assert matched
|
107
|
-
ensure
|
108
|
-
Process.kill("KILL", pid)
|
114
|
+
assert output.grep(/First: one argument, Second: {"random"=>"data"}, Third: 3/).any?
|
109
115
|
end
|
110
116
|
end
|
111
117
|
|
112
118
|
test 'Disc.on_error will catch unhandled exceptions and keep disc alive' do
|
113
|
-
|
114
|
-
Failer.enqueue('this can only end positively')
|
115
|
-
|
116
|
-
cout, _, pid = PTY.spawn(
|
117
|
-
'QUEUES=test ruby -Ilib bin/disc -r ./examples/failer'
|
118
|
-
)
|
119
|
-
sleep 0.5
|
119
|
+
Failer.enqueue('this can only end positively')
|
120
120
|
|
121
|
+
run('QUEUES=test ruby -Ilib bin/disc -r ./examples/failer') do |cout, pid|
|
122
|
+
output = Timeout.timeout(1) { cout.take(5) }
|
121
123
|
jobs = Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1)
|
122
124
|
assert jobs.nil?
|
123
125
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
}
|
130
|
-
|
131
|
-
while tasks.values.include?(false) && counter < 5
|
132
|
-
counter += 1
|
133
|
-
output = cout.gets
|
134
|
-
|
135
|
-
tasks[:reported_error] = true if output.match(/<insert error reporting here>/)
|
136
|
-
tasks[:printed_message] = true if output.match(/this can only end positively/)
|
137
|
-
tasks[:printed_job] = true if output.match(/Failer/)
|
138
|
-
end
|
139
|
-
|
140
|
-
assert !tasks.values.include?(false)
|
141
|
-
|
142
|
-
begin
|
143
|
-
Process.getpgid(pid)
|
144
|
-
assert true
|
145
|
-
rescue Errno::ESRCH
|
146
|
-
assert false
|
147
|
-
end
|
148
|
-
ensure
|
149
|
-
Process.kill("KILL", pid)
|
126
|
+
assert output.grep(/<insert error reporting here>/).any?
|
127
|
+
assert output.grep(/this can only end positively/).any?
|
128
|
+
assert output.grep(/Failer/).any?
|
129
|
+
|
130
|
+
assert is_running?(pid)
|
150
131
|
end
|
151
132
|
end
|
133
|
+
|
134
|
+
test 'enqueue supports replicate' do
|
135
|
+
error = Echoer.enqueue(['one argument', { random: 'data' }, 3], replicate: 100) rescue $!
|
136
|
+
|
137
|
+
assert_equal RuntimeError, error.class
|
138
|
+
assert_equal "NOREPL Not enough reachable nodes for the requested replication level", error.message
|
139
|
+
end
|
140
|
+
|
141
|
+
test 'enqueue supports delay' do
|
142
|
+
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], delay: 2)
|
143
|
+
|
144
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
145
|
+
assert jobs.empty?
|
146
|
+
|
147
|
+
sleep 1
|
148
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
149
|
+
assert jobs.empty?
|
150
|
+
|
151
|
+
sleep 2
|
152
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
153
|
+
assert jobs.any?
|
154
|
+
assert_equal 1, jobs.size
|
155
|
+
end
|
156
|
+
|
157
|
+
test 'enqueue supports retry' do
|
158
|
+
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], retry: 1)
|
159
|
+
|
160
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
161
|
+
assert jobs.any?
|
162
|
+
assert_equal 1, jobs.size
|
163
|
+
|
164
|
+
sleep 1.5
|
165
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
166
|
+
assert jobs.any?
|
167
|
+
assert_equal 1, jobs.size
|
168
|
+
end
|
169
|
+
|
170
|
+
test 'enqueue supports ttl' do
|
171
|
+
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], ttl: 1)
|
172
|
+
|
173
|
+
sleep 1.5
|
174
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
175
|
+
assert jobs.empty?
|
176
|
+
end
|
177
|
+
|
178
|
+
test 'enqueue supports maxlen' do
|
179
|
+
Echoer.enqueue(['one argument', { random: 'data' }, 3], maxlen: 1)
|
180
|
+
# disque off by-one bug? see: https://github.com/antirez/disque/issues/109
|
181
|
+
Echoer.enqueue(['one argument', { random: 'data' }, 3], maxlen: 1)
|
182
|
+
error = Echoer.enqueue(['one argument', { random: 'data' }, 3], maxlen: 1) rescue $!
|
183
|
+
|
184
|
+
assert_equal RuntimeError, error.class
|
185
|
+
assert_equal "MAXLEN Queue is already longer than the specified MAXLEN count", error.message
|
186
|
+
end
|
187
|
+
|
188
|
+
test 'enqueue supports async' do
|
189
|
+
jobid = Echoer.enqueue(['one argument', { random: 'data' }, 3], async: true)
|
190
|
+
|
191
|
+
sleep 1 # async is too fast to reliably assert an empty queue, let's wait instead
|
192
|
+
jobs = Array(Disc.disque.fetch(from: ['test'], timeout: Disc.disque_timeout, count: 1))
|
193
|
+
assert jobs.any?
|
194
|
+
assert_equal 1, jobs.size
|
195
|
+
end
|
152
196
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: disc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- pote
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: disque
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- ".env.sample"
|
64
64
|
- ".gems"
|
65
65
|
- ".gitignore"
|
66
|
+
- ".travis.yml"
|
66
67
|
- 13Floor-circulo-1.png
|
67
68
|
- CONTRIBUTING.md
|
68
69
|
- LICENSE
|