worker-army 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +115 -0
- data/VERSION +1 -1
- data/lib/worker_army/base.rb +33 -0
- data/lib/worker_army/client.rb +2 -12
- data/lib/worker_army/queue.rb +22 -11
- data/lib/worker_army/web.rb +1 -1
- data/lib/worker_army/worker.rb +22 -16
- data/worker-army.gemspec +6 -6
- data/{worker-army.yml.sample → worker_army.yml.sample} +1 -0
- metadata +5 -5
- data/README.rdoc +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 927bd98e49089fff441dad39d22b1415e72846e3
|
4
|
+
data.tar.gz: 543b233b40f905bac71fc9378767412de284cfe8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3c8150b9f82e39b7dc5de67659166c975ef39ec8978065fa1f30b7b1842c2fc5e8f524a86093c6df9c7af281692775bb45489e089ae4d2955ce8f59eb936e97e
|
7
|
+
data.tar.gz: 81516c5776426b4b19030eac5ff4c722c22f0713b6c6756e9e1ff504982b77743737faf20090a6826b6630b3ec824670a800c8ad12539839c95be67b1ea32d13
|
data/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# worker-army
|
2
|
+
|
3
|
+
worker-army is a simple redis based worker queue written in ruby for running background jobs with a HTTP/REST interface. It doesn't have any ties to Ruby on Rails and aims to be lightweight and memory efficient.
|
4
|
+
|
5
|
+
worker-army is work in progress and not yet production-ready!
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
To install worker-army, add the gem to your Gemfile:
|
10
|
+
|
11
|
+
gem "worker-army"
|
12
|
+
|
13
|
+
Then run `bundle`. If you're not using Bundler, just `gem install worker-army`.
|
14
|
+
|
15
|
+
## Requirements
|
16
|
+
|
17
|
+
* Ruby 2.1
|
18
|
+
* Redis 2.x
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
Checkout `worker_army.yml.sample` on the available configuration options. Then create your own `~/.worker_army.yml` file.
|
23
|
+
|
24
|
+
If you can't provide or don't want to provide the config file at that location, you can also set environment variables (when you're deploying on heroku for example):
|
25
|
+
|
26
|
+
worker_army_endpoint
|
27
|
+
worker_army_redis_host
|
28
|
+
worker_army_redis_port
|
29
|
+
worker_army_redis_auth
|
30
|
+
worker_army_worker_retry_count
|
31
|
+
worker_army_client_retry_count
|
32
|
+
worker_army_callback_retry_count
|
33
|
+
|
34
|
+
## Server / Queue
|
35
|
+
|
36
|
+
Start the worker-army server by executing:
|
37
|
+
|
38
|
+
$ worker_army
|
39
|
+
|
40
|
+
or use Foreman (checkout `Procfile`)
|
41
|
+
|
42
|
+
$ foreman start
|
43
|
+
|
44
|
+
You easily run the worker-army server on heroku. It should work out of the box. You're just going to have provide the configuration environment variables.
|
45
|
+
|
46
|
+
You can open the server status overview by calling the server root url:
|
47
|
+
|
48
|
+
http://your-worker-army-server.com/
|
49
|
+
|
50
|
+
The status overview returns JSON, so you can easily embed it into your own applications.
|
51
|
+
|
52
|
+
To view the result of a single job execution:
|
53
|
+
|
54
|
+
http://your-worker-army-server.com/jobs/YOUR_JOB_ID
|
55
|
+
|
56
|
+
## Client
|
57
|
+
|
58
|
+
You can push jobs onto the queue with this ruby client (or any other HTTP REST capable mechanism). The ruby client will communicate with the server from anywhere:
|
59
|
+
|
60
|
+
WorkerArmy::Client.push_job("ExampleJob", {"foo" => "bar"}, "http://your-callback-server.com/data-callback?some_id=1234")
|
61
|
+
|
62
|
+
Provide an (optional) URL as the last argument and worker-army will return the job result to the URL as a HTTP POST callback.
|
63
|
+
|
64
|
+
## Workers
|
65
|
+
|
66
|
+
You can start up a worker with a job class assigned with the following:
|
67
|
+
|
68
|
+
$ rake start_worker[ExampleJob]
|
69
|
+
|
70
|
+
## Jobs
|
71
|
+
|
72
|
+
Jobs are just regular ruby classes that look like this:
|
73
|
+
|
74
|
+
class ExampleJob
|
75
|
+
attr_accessor :log
|
76
|
+
|
77
|
+
def perform(data = {})
|
78
|
+
# Your Code
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
This is how the data looks like for example that the worker passes into the `perform` method:
|
83
|
+
|
84
|
+
{
|
85
|
+
"foo"=>"bar",
|
86
|
+
"job_class"=>"ExampleJob",
|
87
|
+
"callback_url"=>"http://your-worker-army-server.com/callback?callback_url=http://your-callback-server.com/data-callback?some_id=1234",
|
88
|
+
"queue_prefix"=>"queue",
|
89
|
+
"job_count"=>1081,
|
90
|
+
"queue_count"=>1,
|
91
|
+
"job_id"=>"9192a85e-320d-4e15-bdc5-2fa41e862370",
|
92
|
+
"queue_name"=>"queue_ExampleJob"
|
93
|
+
}
|
94
|
+
|
95
|
+
The client who created the job will get this in return:
|
96
|
+
|
97
|
+
{
|
98
|
+
"job_count"=>1081,
|
99
|
+
"job_id"=>"9192a85e-320d-4e15-bdc5-2fa41e862370",
|
100
|
+
"queue_count"=>1,
|
101
|
+
"queue_name"=>"queue_ExampleJob",
|
102
|
+
"success"=>true
|
103
|
+
}
|
104
|
+
|
105
|
+
The `success` field indicates if the job creation (not the execution!) was successfull.
|
106
|
+
|
107
|
+
The result of the job execution will be provided via the callback or by manually calling the job data URL (http://your-worker-army-server.com/jobs/YOUR_JOB_ID).
|
108
|
+
|
109
|
+
## Logging
|
110
|
+
|
111
|
+
Per default, worker-army will create a log file in /tmp/worker-army.log.
|
112
|
+
|
113
|
+
## Copyright
|
114
|
+
|
115
|
+
Copyright (c) 2013-2014 Oliver Kiessler. See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.4.
|
1
|
+
0.4.1
|
data/lib/worker_army/base.rb
CHANGED
@@ -15,6 +15,9 @@ module WorkerArmy
|
|
15
15
|
if ENV['worker_army_client_retry_count']
|
16
16
|
config['client_retry_count'] = ENV['worker_army_client_retry_count'].to_i
|
17
17
|
end
|
18
|
+
if ENV['worker_army_callback_retry_count']
|
19
|
+
config['callback_retry_count'] = ENV['worker_army_callback_retry_count'].to_i
|
20
|
+
end
|
18
21
|
if ENV['worker_army_endpoint']
|
19
22
|
config['endpoint'] = ENV['worker_army_endpoint']
|
20
23
|
end
|
@@ -28,6 +31,36 @@ module WorkerArmy
|
|
28
31
|
end
|
29
32
|
config
|
30
33
|
end
|
34
|
+
|
35
|
+
def client_retry_count(conf = nil)
|
36
|
+
if ENV['worker_army_client_retry_count']
|
37
|
+
return ENV['worker_army_client_retry_count'].to_i
|
38
|
+
elsif conf and conf['client_retry_count']
|
39
|
+
return conf['client_retry_count'].to_i
|
40
|
+
else
|
41
|
+
return 10
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def worker_retry_count(conf = nil)
|
47
|
+
if ENV['worker_army_worker_retry_count']
|
48
|
+
return ENV['worker_army_worker_retry_count'].to_i
|
49
|
+
elsif conf and conf['worker_retry_count']
|
50
|
+
return conf['worker_retry_count'].to_i
|
51
|
+
else
|
52
|
+
return 10
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def callback_retry_count(conf = nil)
|
57
|
+
if ENV['worker_army_callback_retry_count']
|
58
|
+
return ENV['worker_army_callback_retry_count'].to_i
|
59
|
+
elsif conf and conf['callback_retry_count']
|
60
|
+
return conf['callback_retry_count'].to_i
|
61
|
+
else
|
62
|
+
return 3
|
63
|
+
end
|
31
64
|
end
|
32
65
|
end
|
33
66
|
end
|
data/lib/worker_army/client.rb
CHANGED
@@ -32,19 +32,9 @@ module WorkerArmy
|
|
32
32
|
end
|
33
33
|
if response and response.body and response.code == 200
|
34
34
|
hash = JSON.parse(response.body)
|
35
|
-
hash.merge(success
|
35
|
+
hash.merge('success' => true)
|
36
36
|
else
|
37
|
-
{ success
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def client_retry_count(conf = nil)
|
42
|
-
if ENV['worker_army_client_retry_count']
|
43
|
-
return ENV['worker_army_client_retry_count'].to_i
|
44
|
-
elsif conf and conf['client_retry_count']
|
45
|
-
return conf['client_retry_count'].to_i
|
46
|
-
else
|
47
|
-
return 10
|
37
|
+
{ 'success' => false }
|
48
38
|
end
|
49
39
|
end
|
50
40
|
end
|
data/lib/worker_army/queue.rb
CHANGED
@@ -61,17 +61,28 @@ module WorkerArmy
|
|
61
61
|
Queue.redis_instance.lpush 'jobs', job_id
|
62
62
|
if callback_url
|
63
63
|
data.delete("callback_url")
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
64
|
+
deliver_callback(job_id, callback_url, data)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def deliver_callback(job_id, callback_url, data, retry_count = 0)
|
70
|
+
begin
|
71
|
+
response = RestClient.post callback_url.split("?callback_url=").last,
|
72
|
+
data.to_json, :content_type => :json, :accept => :json
|
73
|
+
if response.code == 404 or response.code == 500
|
74
|
+
@log.error("Response from callback url: #{response.code}")
|
75
|
+
add_failed_callback_job(job_id)
|
76
|
+
end
|
77
|
+
rescue => e
|
78
|
+
@log.error(e)
|
79
|
+
retry_count += 1
|
80
|
+
if retry_count < callback_retry_count(@config)
|
81
|
+
@log.debug("Delivering external callback failed! Retrying (#{retry_count})...")
|
82
|
+
sleep (retry_count * 2)
|
83
|
+
deliver_callback(job_id, callback_url, data, retry_count)
|
84
|
+
else
|
85
|
+
add_failed_callback_job(job_id)
|
75
86
|
end
|
76
87
|
end
|
77
88
|
end
|
data/lib/worker_army/web.rb
CHANGED
data/lib/worker_army/worker.rb
CHANGED
@@ -42,23 +42,27 @@ module WorkerArmy
|
|
42
42
|
callback_url = data['callback_url']
|
43
43
|
if @job and @job.class.name == data['job_class']
|
44
44
|
@queue.add_current_job(job_id)
|
45
|
+
started_at = Time.now.utc.to_i
|
45
46
|
response_data = @job.perform(data)
|
46
47
|
response_data = {} unless response_data
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
if callback_url and not callback_url.empty?
|
49
|
+
response_data.merge!(callback_url: callback_url)
|
50
|
+
end
|
51
|
+
response_data.merge!(job_id: job_id, started_at: started_at,
|
52
|
+
finished_at: Time.now.utc.to_i, host_name: @host_name,
|
53
|
+
worker_pid: Process.pid)
|
50
54
|
if @worker_name
|
51
55
|
response_data.merge!(worker_name: @worker_name)
|
52
56
|
end
|
57
|
+
@processed += 1
|
53
58
|
end
|
54
59
|
@queue.remove_current_job(job_id)
|
55
|
-
response_data
|
56
60
|
rescue => e
|
57
61
|
@queue.remove_current_job(job_id)
|
58
62
|
@log.error(e)
|
59
63
|
retry_count += 1
|
60
64
|
if retry_count < worker_retry_count(@config)
|
61
|
-
@log.debug("
|
65
|
+
@log.debug("Job execution failed! Retrying (#{retry_count})...")
|
62
66
|
sleep (retry_count * 2)
|
63
67
|
execute_job(list, element, retry_count)
|
64
68
|
else
|
@@ -66,22 +70,24 @@ module WorkerArmy
|
|
66
70
|
@queue.add_failed_job(job_id)
|
67
71
|
end
|
68
72
|
end
|
73
|
+
if callback_url and not callback_url.empty?
|
74
|
+
deliver_callback(data, response_data)
|
75
|
+
end
|
76
|
+
self.process_queue
|
77
|
+
end
|
78
|
+
|
79
|
+
def deliver_callback(data, response_data, retry_count = 0)
|
69
80
|
begin
|
70
81
|
response = RestClient.post data['callback_url'],
|
71
82
|
response_data.to_json, :content_type => :json, :accept => :json
|
72
83
|
rescue => e
|
73
84
|
@log.error(e)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
return ENV['worker_army_worker_retry_count'].to_i
|
81
|
-
elsif conf and conf['worker_retry_count']
|
82
|
-
return conf['worker_retry_count'].to_i
|
83
|
-
else
|
84
|
-
return 10
|
85
|
+
retry_count += 1
|
86
|
+
if retry_count < callback_retry_count(@config)
|
87
|
+
@log.debug("Delivering worker-army callback failed! Retrying (#{retry_count})...")
|
88
|
+
sleep (retry_count * 2)
|
89
|
+
deliver_callback(data, response_data, retry_count)
|
90
|
+
end
|
85
91
|
end
|
86
92
|
end
|
87
93
|
end
|
data/worker-army.gemspec
CHANGED
@@ -2,22 +2,22 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: worker-army 0.4.
|
5
|
+
# stub: worker-army 0.4.1 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "worker-army"
|
9
|
-
s.version = "0.4.
|
9
|
+
s.version = "0.4.1"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Oliver Kiessler"]
|
14
|
-
s.date = "2014-05-
|
14
|
+
s.date = "2014-05-30"
|
15
15
|
s.description = "Simple redis based worker queue with a HTTP/Rest interface"
|
16
16
|
s.email = "kiessler@inceedo.com"
|
17
17
|
s.executables = ["worker_army"]
|
18
18
|
s.extra_rdoc_files = [
|
19
19
|
"LICENSE.txt",
|
20
|
-
"README.
|
20
|
+
"README.md"
|
21
21
|
]
|
22
22
|
s.files = [
|
23
23
|
".document",
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Gemfile.lock",
|
27
27
|
"LICENSE.txt",
|
28
28
|
"Procfile",
|
29
|
-
"README.
|
29
|
+
"README.md",
|
30
30
|
"Rakefile",
|
31
31
|
"VERSION",
|
32
32
|
"bin/worker_army",
|
@@ -44,7 +44,7 @@ Gem::Specification.new do |s|
|
|
44
44
|
"test/test_worker-army.rb",
|
45
45
|
"unicorn.rb",
|
46
46
|
"worker-army.gemspec",
|
47
|
-
"
|
47
|
+
"worker_army.yml.sample"
|
48
48
|
]
|
49
49
|
s.homepage = "http://github.com/okiess/worker-army"
|
50
50
|
s.licenses = ["MIT"]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: worker-army
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oliver Kiessler
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -157,7 +157,7 @@ executables:
|
|
157
157
|
extensions: []
|
158
158
|
extra_rdoc_files:
|
159
159
|
- LICENSE.txt
|
160
|
-
- README.
|
160
|
+
- README.md
|
161
161
|
files:
|
162
162
|
- ".document"
|
163
163
|
- ".rvmrc"
|
@@ -165,7 +165,7 @@ files:
|
|
165
165
|
- Gemfile.lock
|
166
166
|
- LICENSE.txt
|
167
167
|
- Procfile
|
168
|
-
- README.
|
168
|
+
- README.md
|
169
169
|
- Rakefile
|
170
170
|
- VERSION
|
171
171
|
- bin/worker_army
|
@@ -183,7 +183,7 @@ files:
|
|
183
183
|
- test/test_worker-army.rb
|
184
184
|
- unicorn.rb
|
185
185
|
- worker-army.gemspec
|
186
|
-
-
|
186
|
+
- worker_army.yml.sample
|
187
187
|
homepage: http://github.com/okiess/worker-army
|
188
188
|
licenses:
|
189
189
|
- MIT
|
data/README.rdoc
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
= worker-army
|
2
|
-
|
3
|
-
Simple redis based worker queue with a HTTP/Rest interface.
|
4
|
-
|
5
|
-
== Contributing to worker-army
|
6
|
-
|
7
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
-
* Fork the project.
|
10
|
-
* Start a feature/bugfix branch.
|
11
|
-
* Commit and push until you are happy with your contribution.
|
12
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
-
|
15
|
-
== Copyright
|
16
|
-
|
17
|
-
Copyright (c) 2013-2014 Oliver Kiessler. See LICENSE.txt for
|
18
|
-
further details.
|