sad 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -1
- data/Gemfile.lock +10 -0
- data/README.md +34 -1
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/lib/sad/config.rb +20 -0
- data/lib/sad/payload.rb +37 -4
- data/lib/sad/server.rb +23 -5
- data/lib/sad/worker.rb +4 -2
- data/sad.gemspec +9 -2
- data/test/test_perform_with_exception.rb +20 -0
- data/test/test_sad.rb +6 -3
- metadata +36 -3
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -4,9 +4,11 @@ GEM
|
|
4
4
|
activesupport (3.2.13)
|
5
5
|
i18n (= 0.6.1)
|
6
6
|
multi_json (~> 1.0)
|
7
|
+
coderay (1.0.9)
|
7
8
|
daemons (1.1.9)
|
8
9
|
em-hiredis (0.2.1)
|
9
10
|
hiredis (~> 0.4.0)
|
11
|
+
eventmachine (1.0.3)
|
10
12
|
git (1.2.5)
|
11
13
|
hiredis (0.4.5)
|
12
14
|
i18n (0.6.1)
|
@@ -16,10 +18,16 @@ GEM
|
|
16
18
|
rake
|
17
19
|
rdoc
|
18
20
|
json (1.7.7)
|
21
|
+
method_source (0.8.1)
|
19
22
|
multi_json (1.7.2)
|
23
|
+
pry (0.9.12)
|
24
|
+
coderay (~> 1.0.5)
|
25
|
+
method_source (~> 0.8)
|
26
|
+
slop (~> 3.4)
|
20
27
|
rake (10.0.4)
|
21
28
|
rdoc (4.0.0)
|
22
29
|
json (~> 1.4)
|
30
|
+
slop (3.4.4)
|
23
31
|
|
24
32
|
PLATFORMS
|
25
33
|
ruby
|
@@ -28,5 +36,7 @@ DEPENDENCIES
|
|
28
36
|
activesupport
|
29
37
|
daemons
|
30
38
|
em-hiredis
|
39
|
+
eventmachine
|
31
40
|
jeweler
|
32
41
|
json
|
42
|
+
pry
|
data/README.md
CHANGED
@@ -41,7 +41,6 @@ EM.run{
|
|
41
41
|
|
42
42
|
两个运行环境都要有SadJob这个测试类的定义存在
|
43
43
|
|
44
|
-
--------
|
45
44
|
|
46
45
|
## 在项目中使用
|
47
46
|
|
@@ -90,6 +89,40 @@ Sad::Config.namespace = 'MyBackgroundJobQueue'
|
|
90
89
|
6181 ?? S 0:02.61 Sad-2
|
91
90
|
6522 s002 R+ 0:00.00 grep Sad
|
92
91
|
|
92
|
+
|
93
|
+
## 测试
|
94
|
+
|
95
|
+
启动一个队列
|
96
|
+
|
97
|
+
```sh
|
98
|
+
bundle exec rake sad:restart COUNT=1 QUEUE=MySadJob DIR=./tmp/pids
|
99
|
+
```
|
100
|
+
|
101
|
+
执行最简单的测试
|
102
|
+
|
103
|
+
```sh
|
104
|
+
bundle exec ruby ./test/test_sad.rb
|
105
|
+
```
|
106
|
+
|
107
|
+
执行异常任务测试,异常是指Klass.perform函数执行时出现异常,如果是异步任务,没办法知道异常,因为执行完perform后,代码运行环境已经脱离sad了,需要人工自己处理.
|
108
|
+
|
109
|
+
当Klass.perform出错时,会延时重试,重试三次后,如果还有错误,则放弃该任务.
|
110
|
+
|
111
|
+
```sh
|
112
|
+
bundle exec ruby ./test/test_perform_with_exception.rb
|
113
|
+
```
|
114
|
+
|
115
|
+
在异步模式的代码中,异常如果被抛给top level的运行时的话,则代码无法控制,所以有异常的时候一定要捕获到,写在类似errback的回调中,对于Sad的重试,自动重试只能保证perform执行没问题,如果在callback中出错,则需要用户手工将该任务重新enqueue来实现重试的机制。
|
116
|
+
|
117
|
+
## 任务配置
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
SadJob.enqueue(1,2,3,4,5){|payload|
|
121
|
+
# delay -> 当sad进程得到该任务时并不立即执行,而是延迟多干秒后执行
|
122
|
+
payload.sad_args['delay'] = 5
|
123
|
+
}
|
124
|
+
```
|
125
|
+
|
93
126
|
## Contributing to sad
|
94
127
|
|
95
128
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
data/lib/sad/config.rb
CHANGED
@@ -9,6 +9,10 @@ module Sad
|
|
9
9
|
@_namespace || 'SadQueue'
|
10
10
|
end
|
11
11
|
|
12
|
+
def queue(q)
|
13
|
+
[Sad::Config.namespace, q].join ':'
|
14
|
+
end
|
15
|
+
|
12
16
|
def redis=(uri)
|
13
17
|
@_redis_url = uri
|
14
18
|
end
|
@@ -16,6 +20,22 @@ module Sad
|
|
16
20
|
def redis
|
17
21
|
@_redis ||= EM::Hiredis.connect(@_redis_url)
|
18
22
|
end
|
23
|
+
|
24
|
+
def interval=(int)
|
25
|
+
@_interval = int.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
def interval
|
29
|
+
@_interval ||= 3
|
30
|
+
end
|
31
|
+
|
32
|
+
def max_retry=(int)
|
33
|
+
@_max_retry = int.to_i
|
34
|
+
end
|
35
|
+
|
36
|
+
def max_retry
|
37
|
+
@_max_retry ||= 3
|
38
|
+
end
|
19
39
|
end
|
20
40
|
end
|
21
41
|
end
|
data/lib/sad/payload.rb
CHANGED
@@ -1,22 +1,55 @@
|
|
1
|
+
require "json"
|
2
|
+
|
1
3
|
module Sad
|
2
4
|
class Payload
|
3
|
-
attr_accessor :klass, :args
|
5
|
+
attr_accessor :klass, :args, :sad_args
|
4
6
|
|
5
|
-
def initialize(klass, args)
|
7
|
+
def initialize(klass, args = [], sad_args = {})
|
6
8
|
@klass = klass
|
7
9
|
@args = args
|
10
|
+
@sad_args = {
|
11
|
+
'retry' => 0,
|
12
|
+
'delay' => 0
|
13
|
+
}.update(sad_args)
|
8
14
|
end
|
9
15
|
|
10
16
|
def encode
|
11
17
|
{
|
12
18
|
'klass' => @klass,
|
13
|
-
'args' => @args
|
19
|
+
'args' => @args,
|
20
|
+
'sad_args' => @sad_args
|
14
21
|
}.to_json
|
15
22
|
end
|
16
23
|
|
24
|
+
# 执行任务
|
25
|
+
# 当执行任务的perform出错时
|
26
|
+
# 重试1至::Sad::Config.max_retry次
|
27
|
+
# 每次重试时,延迟重试次数*::Sad::Config.interval的时长后,再enqueue
|
28
|
+
def perform
|
29
|
+
begin
|
30
|
+
@klass.constantize.send :perform, *@args
|
31
|
+
rescue Exception => e
|
32
|
+
if self.sad_args['retry'] and (self.sad_args['retry'].to_i < ::Sad::Config.max_retry)
|
33
|
+
self.sad_args['retry'] = self.sad_args['retry'].to_i + 1
|
34
|
+
self.sad_args['delay'] = ::Sad::Config.interval * self.sad_args['retry']
|
35
|
+
self.enqueue
|
36
|
+
else
|
37
|
+
STDERR.puts "Payload perform error for #{self.sad_args['retry']} retrys:\n#{self.inspect}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def enqueue
|
43
|
+
::Sad::Config.redis.rpush(self.sad_args['queue'], self.encode)
|
44
|
+
end
|
45
|
+
|
17
46
|
def self.decode(json)
|
18
47
|
h = JSON.parse(json)
|
19
|
-
|
48
|
+
if h['sad_args'] or h['sad_args'] != ''
|
49
|
+
self.new(h['klass'], h['args'], h['sad_args'])
|
50
|
+
else
|
51
|
+
self.new(h['klass'], h['args'])
|
52
|
+
end
|
20
53
|
end
|
21
54
|
end
|
22
55
|
end
|
data/lib/sad/server.rb
CHANGED
@@ -4,7 +4,7 @@ module Sad
|
|
4
4
|
def run(queue)
|
5
5
|
@_shutdown = false
|
6
6
|
register_signal
|
7
|
-
fetch(
|
7
|
+
fetch(Sad::Config.queue(queue))
|
8
8
|
end
|
9
9
|
|
10
10
|
def fetch(queue)
|
@@ -13,17 +13,34 @@ module Sad
|
|
13
13
|
if data
|
14
14
|
STDOUT.puts '-'*15 + data.inspect + '-'*15
|
15
15
|
payload = Payload.decode(data)
|
16
|
-
|
16
|
+
payload_call(payload)
|
17
17
|
end
|
18
|
-
|
18
|
+
fetch_with_interval(queue)
|
19
19
|
}
|
20
20
|
request.errback{
|
21
|
+
STDERR.puts 'error with redis request.'
|
22
|
+
fetch_with_interval(queue)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_with_interval(queue)
|
27
|
+
EM.add_timer(::Sad::Config.interval){
|
21
28
|
fetch(queue) unless shutdown?
|
22
29
|
}
|
23
30
|
end
|
24
31
|
|
25
|
-
def
|
26
|
-
|
32
|
+
def payload_call(payload)
|
33
|
+
# 如果该任务有延时执行要求,
|
34
|
+
# 则在定时器执行时将其延时的key删掉,
|
35
|
+
# 再重新入队
|
36
|
+
if payload.sad_args['delay'] and payload.sad_args['delay'] != '' and payload.sad_args['delay'] != 0
|
37
|
+
EM.add_timer(payload.sad_args['delay'].to_i){
|
38
|
+
payload.sad_args.delete('delay')
|
39
|
+
payload.enqueue
|
40
|
+
}
|
41
|
+
else
|
42
|
+
payload.perform
|
43
|
+
end
|
27
44
|
end
|
28
45
|
|
29
46
|
def register_signal
|
@@ -43,6 +60,7 @@ module Sad
|
|
43
60
|
|
44
61
|
def shutdown
|
45
62
|
@_shutdown = true
|
63
|
+
EM.stop
|
46
64
|
end
|
47
65
|
end
|
48
66
|
end
|
data/lib/sad/worker.rb
CHANGED
@@ -6,12 +6,14 @@ module Sad
|
|
6
6
|
else
|
7
7
|
nil
|
8
8
|
end
|
9
|
-
|
9
|
+
Sad::Config.queue(name)
|
10
10
|
end
|
11
11
|
|
12
12
|
def enqueue(*args)
|
13
13
|
payload = ::Sad::Payload.new(self.to_s, args)
|
14
|
-
|
14
|
+
payload.sad_args['queue'] = queue_name
|
15
|
+
yield payload if block_given?
|
16
|
+
payload.enqueue
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
data/sad.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "sad"
|
8
|
-
s.version = "1.
|
8
|
+
s.version = "1.4.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["\u{5d14}\u{5ce5}"]
|
12
|
-
s.date = "2013-04-
|
12
|
+
s.date = "2013-04-27"
|
13
13
|
s.description = "a simple em baseed background job worker."
|
14
14
|
s.email = "zheng.cuizh@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
"lib/tasks/sad.rake",
|
35
35
|
"sad.gemspec",
|
36
36
|
"test/helper.rb",
|
37
|
+
"test/test_perform_with_exception.rb",
|
37
38
|
"test/test_sad.rb"
|
38
39
|
]
|
39
40
|
s.homepage = "http://github.com/charlescui/sad"
|
@@ -48,22 +49,28 @@ Gem::Specification.new do |s|
|
|
48
49
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
50
|
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
50
51
|
s.add_runtime_dependency(%q<activesupport>, [">= 0"])
|
52
|
+
s.add_runtime_dependency(%q<eventmachine>, [">= 0"])
|
51
53
|
s.add_runtime_dependency(%q<em-hiredis>, [">= 0"])
|
52
54
|
s.add_runtime_dependency(%q<daemons>, [">= 0"])
|
53
55
|
s.add_runtime_dependency(%q<json>, [">= 0"])
|
56
|
+
s.add_runtime_dependency(%q<pry>, [">= 0"])
|
54
57
|
else
|
55
58
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
56
59
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
60
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
57
61
|
s.add_dependency(%q<em-hiredis>, [">= 0"])
|
58
62
|
s.add_dependency(%q<daemons>, [">= 0"])
|
59
63
|
s.add_dependency(%q<json>, [">= 0"])
|
64
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
60
65
|
end
|
61
66
|
else
|
62
67
|
s.add_dependency(%q<jeweler>, [">= 0"])
|
63
68
|
s.add_dependency(%q<activesupport>, [">= 0"])
|
69
|
+
s.add_dependency(%q<eventmachine>, [">= 0"])
|
64
70
|
s.add_dependency(%q<em-hiredis>, [">= 0"])
|
65
71
|
s.add_dependency(%q<daemons>, [">= 0"])
|
66
72
|
s.add_dependency(%q<json>, [">= 0"])
|
73
|
+
s.add_dependency(%q<pry>, [">= 0"])
|
67
74
|
end
|
68
75
|
end
|
69
76
|
|
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift(File.dirname __FILE__)
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class SadJob
|
5
|
+
extend ::Sad::Worker
|
6
|
+
|
7
|
+
def self.queue
|
8
|
+
'MySadJob'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.perform(*args)
|
12
|
+
raise RuntimeError, 'Error for test!!!!'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
EM.run {
|
17
|
+
EM::PeriodicTimer.new(3){
|
18
|
+
SadJob.enqueue('this is some args', {:hello => 'code'})
|
19
|
+
}
|
20
|
+
}
|
data/test/test_sad.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
$:.unshift(File.dirname __FILE__)
|
1
2
|
require 'helper'
|
2
3
|
|
3
4
|
class SadJob
|
@@ -13,6 +14,8 @@ class SadJob
|
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
16
|
-
EM
|
17
|
-
|
18
|
-
}
|
17
|
+
EM.run{
|
18
|
+
EM::PeriodicTimer.new(3){
|
19
|
+
SadJob.enqueue('this is some args', {:hello => 'code'})
|
20
|
+
}
|
21
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-04-
|
12
|
+
date: 2013-04-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: jeweler
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: eventmachine
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: em-hiredis
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,6 +107,22 @@ dependencies:
|
|
91
107
|
- - ! '>='
|
92
108
|
- !ruby/object:Gem::Version
|
93
109
|
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: pry
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
94
126
|
description: a simple em baseed background job worker.
|
95
127
|
email: zheng.cuizh@gmail.com
|
96
128
|
executables: []
|
@@ -116,6 +148,7 @@ files:
|
|
116
148
|
- lib/tasks/sad.rake
|
117
149
|
- sad.gemspec
|
118
150
|
- test/helper.rb
|
151
|
+
- test/test_perform_with_exception.rb
|
119
152
|
- test/test_sad.rb
|
120
153
|
homepage: http://github.com/charlescui/sad
|
121
154
|
licenses:
|
@@ -132,7 +165,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
165
|
version: '0'
|
133
166
|
segments:
|
134
167
|
- 0
|
135
|
-
hash:
|
168
|
+
hash: -1386435798103601784
|
136
169
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
170
|
none: false
|
138
171
|
requirements:
|