sweatshop 1.5.2 → 1.6.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.
@@ -1,5 +1,5 @@
1
1
  ---
2
- :build:
3
- :minor: 5
4
- :patch: 2
2
+ :patch: 0
5
3
  :major: 1
4
+ :build:
5
+ :minor: 6
@@ -8,5 +8,6 @@ module MessageQueue
8
8
  def delete(queue); end
9
9
  def client; end
10
10
  def stop; end
11
+ def flush_all(queue); end
11
12
  end
12
13
  end
@@ -7,44 +7,38 @@ module MessageQueue
7
7
  end
8
8
 
9
9
  def delete(queue)
10
- send_command do
11
- client.queue(queue).delete
12
- end
10
+ cmd(queue, :delete)
13
11
  end
14
12
 
15
13
  def queue_size(queue)
16
- send_command do
17
- client.queue(queue).message_count
18
- end
14
+ cmd(queue, :message_count)
19
15
  end
20
16
 
21
17
  def enqueue(queue, data)
22
- send_command do
23
- client.queue(queue, :durable => true).publish(Marshal.dump(data), :persistent => true)
24
- end
18
+ cmd(queue, :publish, Marshal.dump(data), :persistent => true)
25
19
  end
26
20
 
27
21
  def dequeue(queue)
28
- send_command do
29
- task = client.queue(queue).pop(:ack => true)
30
- return unless task
31
- Marshal.load(task)
32
- end
22
+ task = cmd(queue, :pop, :ack => true)
23
+ return unless task
24
+ Marshal.load(task)
33
25
  end
34
26
 
35
27
  def confirm(queue)
36
- send_command do
37
- client.queue(queue).ack
38
- end
28
+ cmd(queue, :ack)
29
+ end
30
+
31
+ def flush_all(queue)
32
+ cmd(queue, :purge)
39
33
  end
40
34
 
41
- def send_command(&block)
35
+ def cmd(queue, command, *args)
42
36
  retried = false
43
37
  begin
44
- block.call
38
+ client.queue(queue, :durable => true).send(command, *args)
45
39
  rescue Carrot::AMQP::Server::ServerDown => e
46
40
  if not retried
47
- puts "Error #{e.message}. Retrying..."
41
+ Sweatshop.log "Error #{e.message}. Retrying..."
48
42
  @client = nil
49
43
  retried = true
50
44
  retry
@@ -44,6 +44,7 @@ module Sweatshop
44
44
  worker.stop
45
45
  end
46
46
  queue.stop
47
+ @stop.call if @stop.kind_of?(Proc)
47
48
  exit
48
49
  end
49
50
  sleep 1 if wait
@@ -87,8 +88,12 @@ module Sweatshop
87
88
  @daemon = true
88
89
  end
89
90
 
90
- def stop
91
- @stop = true
91
+ def stop(&block)
92
+ if block_given?
93
+ @stop = block
94
+ else
95
+ @stop = true
96
+ end
92
97
  end
93
98
 
94
99
  def stop?
@@ -125,6 +130,12 @@ module Sweatshop
125
130
  @queue_groups ||= (workers.collect{|w| w.queue_group.to_s} << 'default').uniq
126
131
  end
127
132
 
133
+ def flush_all_queues
134
+ workers.each do |worker|
135
+ worker.flush_queue
136
+ end
137
+ end
138
+
128
139
  def pp_sizes
129
140
  max_width = workers.collect{|w| w.to_s.size}.max
130
141
  puts '-' * (max_width + 10)
@@ -155,6 +166,10 @@ module Sweatshop
155
166
  nil
156
167
  end
157
168
 
169
+ def enabled?
170
+ !!config['enable']
171
+ end
172
+
158
173
  def log(msg)
159
174
  return if logger == :silent
160
175
  logger ? logger.debug(msg) : puts(msg)
@@ -174,5 +189,5 @@ module Sweatshop
174
189
  end
175
190
 
176
191
  if defined?(RAILS_ROOT)
177
- Dir.glob(RAILS_ROOT + '/app/workers/*.rb').each{|worker| require worker }
192
+ Dir.glob(RAILS_ROOT + '/app/workers/*.rb').each{|worker| require_or_load worker }
178
193
  end
@@ -49,10 +49,6 @@ module Daemoned
49
49
  options[:ontop] = true
50
50
  end
51
51
 
52
- opt.on('--instances=NUM', 'Allow multiple instances to run simultaneously? 0 for infinite. default: 1') do |value|
53
- self.instances = value.to_i
54
- end
55
-
56
52
  opt.on('--log-file=LOGFILE', 'Logfile to log to') do |value|
57
53
  options[:log_file] = File.expand_path(value)
58
54
  end
@@ -3,3 +3,9 @@ def meta_eval(&blk); metaclass.instance_eval(&blk); end
3
3
  def meta_def(name, &blk)
4
4
  meta_eval { define_method name, &blk }
5
5
  end
6
+
7
+ def check_arity!(method, args)
8
+ arity = method.arity
9
+ valid = arity < 0 ? args.size >= arity.abs - 1 : args.size == arity
10
+ raise ArgumentError.new("#{method.name} expects #{arity} arguments") unless valid
11
+ end
@@ -34,10 +34,8 @@ module Sweatshop
34
34
  end
35
35
 
36
36
  sig(:hup) do
37
- begin
38
- puts "Received HUP"
39
- Sweatshop.stop
40
- ensure
37
+ puts "Received HUP"
38
+ Sweatshop.stop do
41
39
  remove_pid!
42
40
  puts "Restarting sweatd with #{start_cmd}..."
43
41
  `#{start_cmd}`
@@ -8,12 +8,10 @@ module Sweatshop
8
8
 
9
9
  def self.method_missing(method, *args, &block)
10
10
  if method.to_s =~ /^async_(.*)/
11
- method = $1
12
- expected_args = instance.method(method).arity
13
- if expected_args != args.size
14
- raise ArgumentError.new("#{method} expects #{expected_args} arguments")
15
- end
16
- return instance.send(method, *args) unless config['enable']
11
+ method = $1
12
+ check_arity!(instance.method(method), args)
13
+
14
+ return instance.send(method, *args) unless async?
17
15
 
18
16
  uid = ::Digest::MD5.hexdigest("#{name}:#{method}:#{args}:#{Time.now.to_f}")
19
17
  task = {:args => args, :method => method, :uid => uid, :queued_at => Time.now.to_i}
@@ -29,6 +27,10 @@ module Sweatshop
29
27
  end
30
28
  end
31
29
 
30
+ def self.async?
31
+ Sweatshop.enabled?
32
+ end
33
+
32
34
  def self.instance
33
35
  @instance ||= new
34
36
  end
@@ -41,6 +43,10 @@ module Sweatshop
41
43
  @queue_name ||= self.to_s
42
44
  end
43
45
 
46
+ def self.flush_queue
47
+ queue.flush_all(queue_name)
48
+ end
49
+
44
50
  def self.delete_queue
45
51
  queue.delete(queue_name)
46
52
  end
@@ -82,6 +88,16 @@ module Sweatshop
82
88
  rescue Exception => e
83
89
  log("Caught Exception: #{e.message}, \n#{e.backtrace.join("\n")}")
84
90
  call_exception_handler(e)
91
+
92
+ # the only way to re-queue messages with rabbitmq is to close and reopen the connection
93
+ # putting a 'sleep 2' in here to give the administrator to fix peristent problems, otherwise
94
+ # we'll hit an infinite loop
95
+ #
96
+ # THIS CODE IS PROBLEMATIC --- we need to put these tasks into a 'failed' queue so we don't run into infinite loops
97
+ # will just 'confirm' for now
98
+ #queue.stop
99
+ #sleep 2
100
+ confirm
85
101
  end
86
102
  end
87
103
 
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/../lib/sweatshop'
1
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sweatshop')
2
2
  class HelloWorker < Sweatshop::Worker
3
3
  TEST_FILE = File.dirname(__FILE__) + '/test.txt' unless defined?(TEST_FILE)
4
4
 
@@ -1,6 +1,6 @@
1
- require File.dirname(__FILE__) + '/../lib/sweatshop'
2
- require File.dirname(__FILE__) + '/test_helper'
3
- require File.dirname(__FILE__) + '/hello_worker'
1
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sweatshop')
2
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper' )
3
+ require File.expand_path(File.dirname(__FILE__) + '/hello_worker' )
4
4
 
5
5
  class WorkerTest < Test::Unit::TestCase
6
6
 
@@ -15,10 +15,7 @@ class WorkerTest < Test::Unit::TestCase
15
15
  end
16
16
 
17
17
  should "daemonize" do
18
- begin
19
- Sweatshop.config['enable'] = true
20
- Sweatshop.logger = :silent
21
-
18
+ enable_server do
22
19
  HelloWorker.async_hello('Amos')
23
20
 
24
21
  worker = File.expand_path(File.dirname(__FILE__) + '/hello_worker')
@@ -29,26 +26,19 @@ class WorkerTest < Test::Unit::TestCase
29
26
 
30
27
  File.delete('sweatd.log') if File.exist?('sweatd.log')
31
28
  assert_equal 'Hi, Amos', File.read(HelloWorker::TEST_FILE)
32
-
33
- rescue Exception => e
34
- puts e.message
35
- puts e.backtrace.join("\n")
36
- fail "\n\n*** Functional test failed, is the rabbit server running on localhost? ***\n"
37
29
  end
38
30
  end
39
31
 
40
32
  should "connect to fallback servers if the default one is down" do
41
- begin
42
- Sweatshop.logger = :silent
43
- Sweatshop.config['enable'] = true
33
+ enable_server do
44
34
  Sweatshop.config['default']['cluster'] =
45
35
  [
46
36
  'localhost:5671', # invalid
47
37
  'localhost:5672' # valid
48
38
  ]
49
39
  HelloWorker.async_hello('Amos')
50
-
51
- assert_equal 'Amos', HelloWorker.dequeue[:args].first
40
+ task = HelloWorker.dequeue
41
+ assert_equal 'Amos', task[:args].first
52
42
 
53
43
  HelloWorker.queue.client = nil
54
44
 
@@ -61,12 +51,29 @@ class WorkerTest < Test::Unit::TestCase
61
51
 
62
52
  HelloWorker.async_hello('Amos')
63
53
  assert_equal 'Amos', HelloWorker.dequeue[:args].first
64
-
54
+ end
55
+ end
56
+
57
+ should "exception handler" do
58
+ exception = nil
59
+ HelloWorker.on_exception do |e|
60
+ exception = e
61
+ end
62
+
63
+ HelloWorker.do_task(nil)
64
+ assert_equal NoMethodError, exception.class
65
+ end
66
+
67
+
68
+ def enable_server
69
+ Sweatshop.config['enable'] = true
70
+ Sweatshop.logger = :silent
71
+ begin
72
+ yield
65
73
  rescue Exception => e
66
74
  puts e.message
67
75
  puts e.backtrace.join("\n")
68
76
  fail "\n\n*** Functional test failed, is the rabbit server running on localhost? ***\n"
69
77
  end
70
78
  end
71
-
72
79
  end
@@ -1,5 +1,5 @@
1
- require File.dirname(__FILE__) + '/test_helper'
2
- require File.dirname(__FILE__) + '/../lib/sweatshop'
1
+ require File.expand_path(File.dirname(__FILE__) + '/test_helper' )
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sweatshop')
3
3
 
4
4
  class SweatshopTest < Test::Unit::TestCase
5
5
  Sweatshop.workers = []
@@ -25,13 +25,6 @@ class SweatshopTest < Test::Unit::TestCase
25
25
  assert_equal "Hi, Amos", worker.hello('Amos')
26
26
  end
27
27
 
28
- should "assign a uid" do
29
- Sweatshop.logger = :silent
30
- Sweatshop.config['enable'] = false
31
- uid = HelloWorker.async_hello('Amos')
32
- assert_not_nil uid
33
- end
34
-
35
28
  should "have before task" do
36
29
  HelloWorker.before_task do
37
30
  "hello"
@@ -46,18 +39,6 @@ class SweatshopTest < Test::Unit::TestCase
46
39
  assert_equal "goodbye", HelloWorker.after_task.call
47
40
  end
48
41
 
49
- should "exception handler" do
50
- Sweatshop.logger = :silent
51
-
52
- exception = nil
53
- HelloWorker.on_exception do |e|
54
- exception = e
55
- end
56
-
57
- HelloWorker.do_task(nil)
58
- assert_equal NoMethodError, exception.class
59
- end
60
-
61
42
  should "chain before tasks" do
62
43
  MESSAGES = []
63
44
  class BaseWorker < Sweatshop::Worker
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sweatshop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.2
4
+ hash: 15
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 6
9
+ - 0
10
+ version: 1.6.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Amos Elliston
@@ -9,19 +15,25 @@ autorequire:
9
15
  bindir: bin
10
16
  cert_chain: []
11
17
 
12
- date: 2010-01-03 00:00:00 -08:00
18
+ date: 2011-04-05 00:00:00 -07:00
13
19
  default_executable: sweatd
14
20
  dependencies:
15
21
  - !ruby/object:Gem::Dependency
16
22
  name: carrot
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
20
26
  requirements:
21
27
  - - "="
22
28
  - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ - 7
33
+ - 0
23
34
  version: 0.7.0
24
- version:
35
+ type: :runtime
36
+ version_requirements: *id001
25
37
  description: See summary
26
38
  email: amos@geni.com
27
39
  executables:
@@ -56,31 +68,38 @@ files:
56
68
  - test/test_functional_worker.rb
57
69
  - test/test_helper.rb
58
70
  - test/test_sweatshop.rb
71
+ - bin/sweatd
59
72
  has_rdoc: true
60
73
  homepage: http://github.com/famoseagle/sweatshop
61
74
  licenses: []
62
75
 
63
76
  post_install_message:
64
- rdoc_options:
65
- - --charset=UTF-8
77
+ rdoc_options: []
78
+
66
79
  require_paths:
67
80
  - lib
68
81
  required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
69
83
  requirements:
70
84
  - - ">="
71
85
  - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
72
89
  version: "0"
73
- version:
74
90
  required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
75
92
  requirements:
76
93
  - - ">="
77
94
  - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
78
98
  version: "0"
79
- version:
80
99
  requirements: []
81
100
 
82
101
  rubyforge_project:
83
- rubygems_version: 1.3.5
102
+ rubygems_version: 1.3.7
84
103
  signing_key:
85
104
  specification_version: 3
86
105
  summary: Sweatshop is a simple asynchronous worker queue build on top of rabbitmq/ampq