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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 356fda8449bf808280461964fd361d5960d4098f
4
- data.tar.gz: 2bc6419214d9b6498bc132ff8cb5db842b0ebb43
3
+ metadata.gz: 927bd98e49089fff441dad39d22b1415e72846e3
4
+ data.tar.gz: 543b233b40f905bac71fc9378767412de284cfe8
5
5
  SHA512:
6
- metadata.gz: 3b62516a6387cf9e5ab8350bf823f63812fa9b90197cb746bc26e98a2bab4d3ba1a38b4e282d83c3f55480f1b01db7d15ded35cbbbe94869102fd5b4c889bdb4
7
- data.tar.gz: 0104f1aa27d28a0f3b2d18455dff4dde4f23c4bc23295ab989a06d540cbb89b98489e2791a463b8c769fcb96c64a4a0f951fd5c930d3628e6a116018060f2405
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.0
1
+ 0.4.1
@@ -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
@@ -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: true)
35
+ hash.merge('success' => true)
36
36
  else
37
- { success: false }
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
@@ -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
- begin
65
- response = RestClient.post callback_url.split("?callback_url=").last,
66
- data.to_json, :content_type => :json, :accept => :json
67
- if response.code == 404 or response.code == 500
68
- @log.error("Response from callback url: #{response.code}")
69
- add_failed_callback_job(job_id)
70
- end
71
- rescue => e
72
- @log.error(e)
73
- add_failed_callback_job(job_id)
74
- end
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
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  get '/jobs/:job_id' do
38
38
  data = queue.job_data(params[:job_id])
39
- json JSON.parse(data)
39
+ json data ? JSON.parse(data): {}
40
40
  end
41
41
 
42
42
  post '/callback' do
@@ -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
- response_data.merge!(job_id: job_id, callback_url: callback_url,
48
- finished_at: Time.now.utc.to_i, host_name: @host_name)
49
- @processed += 1
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("Failed! Retrying (#{retry_count})...")
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
- end
75
- self.process_queue
76
- end
77
-
78
- def worker_retry_count(conf = nil)
79
- if ENV['worker_army_worker_retry_count']
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.0 ruby lib
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.0"
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-29"
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.rdoc"
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.rdoc",
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
- "worker-army.yml.sample"
47
+ "worker_army.yml.sample"
48
48
  ]
49
49
  s.homepage = "http://github.com/okiess/worker-army"
50
50
  s.licenses = ["MIT"]
@@ -4,3 +4,4 @@ redis_port: 6379
4
4
  redis_auth: "YOUR_PASS"
5
5
  client_retry_count: 10
6
6
  worker_retry_count: 10
7
+ callback_retry_count: 5
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.0
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-29 00:00:00.000000000 Z
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.rdoc
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.rdoc
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
- - worker-army.yml.sample
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.