sad 1.3.0 → 1.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.
- 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:
|