jerefrer-resque 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.kick +26 -0
  2. data/HISTORY.md +10 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +703 -0
  5. data/Rakefile +61 -0
  6. data/bin/resque +69 -0
  7. data/bin/resque-web +47 -0
  8. data/config.ru +8 -0
  9. data/deps.rip +5 -0
  10. data/examples/async_helper.rb +31 -0
  11. data/examples/demo/README.markdown +71 -0
  12. data/examples/demo/Rakefile +3 -0
  13. data/examples/demo/app.rb +27 -0
  14. data/examples/demo/config.ru +19 -0
  15. data/examples/demo/job.rb +12 -0
  16. data/examples/god/resque.god +52 -0
  17. data/examples/god/stale.god +26 -0
  18. data/examples/instance.rb +11 -0
  19. data/examples/simple.rb +30 -0
  20. data/init.rb +1 -0
  21. data/lib/resque/errors.rb +7 -0
  22. data/lib/resque/failure/base.rb +58 -0
  23. data/lib/resque/failure/hoptoad.rb +88 -0
  24. data/lib/resque/failure/redis.rb +33 -0
  25. data/lib/resque/failure.rb +63 -0
  26. data/lib/resque/helpers.rb +57 -0
  27. data/lib/resque/job.rb +91 -0
  28. data/lib/resque/server/public/idle.png +0 -0
  29. data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
  30. data/lib/resque/server/public/jquery.relatize_date.js +95 -0
  31. data/lib/resque/server/public/poll.png +0 -0
  32. data/lib/resque/server/public/ranger.js +21 -0
  33. data/lib/resque/server/public/reset.css +48 -0
  34. data/lib/resque/server/public/style.css +75 -0
  35. data/lib/resque/server/public/working.png +0 -0
  36. data/lib/resque/server/views/error.erb +1 -0
  37. data/lib/resque/server/views/failed.erb +35 -0
  38. data/lib/resque/server/views/key.erb +17 -0
  39. data/lib/resque/server/views/layout.erb +41 -0
  40. data/lib/resque/server/views/next_more.erb +10 -0
  41. data/lib/resque/server/views/overview.erb +4 -0
  42. data/lib/resque/server/views/queues.erb +46 -0
  43. data/lib/resque/server/views/stats.erb +62 -0
  44. data/lib/resque/server/views/workers.erb +78 -0
  45. data/lib/resque/server/views/working.erb +67 -0
  46. data/lib/resque/server.rb +174 -0
  47. data/lib/resque/stat.rb +53 -0
  48. data/lib/resque/tasks.rb +24 -0
  49. data/lib/resque/version.rb +3 -0
  50. data/lib/resque/worker.rb +406 -0
  51. data/lib/resque.rb +184 -0
  52. data/tasks/redis.rake +125 -0
  53. data/tasks/resque.rake +2 -0
  54. data/test/redis-test.conf +132 -0
  55. data/test/resque_test.rb +160 -0
  56. data/test/test_helper.rb +90 -0
  57. data/test/worker_test.rb +220 -0
  58. metadata +121 -0
@@ -0,0 +1,132 @@
1
+ # Redis configuration file example
2
+
3
+ # By default Redis does not run as a daemon. Use 'yes' if you need it.
4
+ # Note that Redis will write a pid file in /var/run/redis.pid when daemonized.
5
+ daemonize yes
6
+
7
+ # When run as a daemon, Redis write a pid file in /var/run/redis.pid by default.
8
+ # You can specify a custom pid file location here.
9
+ pidfile ./test/redis-test.pid
10
+
11
+ # Accept connections on the specified port, default is 6379
12
+ port 9736
13
+
14
+ # If you want you can bind a single interface, if the bind option is not
15
+ # specified all the interfaces will listen for connections.
16
+ #
17
+ # bind 127.0.0.1
18
+
19
+ # Close the connection after a client is idle for N seconds (0 to disable)
20
+ timeout 300
21
+
22
+ # Save the DB on disk:
23
+ #
24
+ # save <seconds> <changes>
25
+ #
26
+ # Will save the DB if both the given number of seconds and the given
27
+ # number of write operations against the DB occurred.
28
+ #
29
+ # In the example below the behaviour will be to save:
30
+ # after 900 sec (15 min) if at least 1 key changed
31
+ # after 300 sec (5 min) if at least 10 keys changed
32
+ # after 60 sec if at least 10000 keys changed
33
+ save 900 1
34
+ save 300 10
35
+ save 60 10000
36
+
37
+ # The filename where to dump the DB
38
+ dbfilename dump.rdb
39
+
40
+ # For default save/load DB in/from the working directory
41
+ # Note that you must specify a directory not a file name.
42
+ dir ./test/
43
+
44
+ # Set server verbosity to 'debug'
45
+ # it can be one of:
46
+ # debug (a lot of information, useful for development/testing)
47
+ # notice (moderately verbose, what you want in production probably)
48
+ # warning (only very important / critical messages are logged)
49
+ loglevel debug
50
+
51
+ # Specify the log file name. Also 'stdout' can be used to force
52
+ # the demon to log on the standard output. Note that if you use standard
53
+ # output for logging but daemonize, logs will be sent to /dev/null
54
+ logfile stdout
55
+
56
+ # Set the number of databases. The default database is DB 0, you can select
57
+ # a different one on a per-connection basis using SELECT <dbid> where
58
+ # dbid is a number between 0 and 'databases'-1
59
+ databases 16
60
+
61
+ ################################# REPLICATION #################################
62
+
63
+ # Master-Slave replication. Use slaveof to make a Redis instance a copy of
64
+ # another Redis server. Note that the configuration is local to the slave
65
+ # so for example it is possible to configure the slave to save the DB with a
66
+ # different interval, or to listen to another port, and so on.
67
+
68
+ # slaveof <masterip> <masterport>
69
+
70
+ ################################## SECURITY ###################################
71
+
72
+ # Require clients to issue AUTH <PASSWORD> before processing any other
73
+ # commands. This might be useful in environments in which you do not trust
74
+ # others with access to the host running redis-server.
75
+ #
76
+ # This should stay commented out for backward compatibility and because most
77
+ # people do not need auth (e.g. they run their own servers).
78
+
79
+ # requirepass foobared
80
+
81
+ ################################### LIMITS ####################################
82
+
83
+ # Set the max number of connected clients at the same time. By default there
84
+ # is no limit, and it's up to the number of file descriptors the Redis process
85
+ # is able to open. The special value '0' means no limts.
86
+ # Once the limit is reached Redis will close all the new connections sending
87
+ # an error 'max number of clients reached'.
88
+
89
+ # maxclients 128
90
+
91
+ # Don't use more memory than the specified amount of bytes.
92
+ # When the memory limit is reached Redis will try to remove keys with an
93
+ # EXPIRE set. It will try to start freeing keys that are going to expire
94
+ # in little time and preserve keys with a longer time to live.
95
+ # Redis will also try to remove objects from free lists if possible.
96
+ #
97
+ # If all this fails, Redis will start to reply with errors to commands
98
+ # that will use more memory, like SET, LPUSH, and so on, and will continue
99
+ # to reply to most read-only commands like GET.
100
+ #
101
+ # WARNING: maxmemory can be a good idea mainly if you want to use Redis as a
102
+ # 'state' server or cache, not as a real DB. When Redis is used as a real
103
+ # database the memory usage will grow over the weeks, it will be obvious if
104
+ # it is going to use too much memory in the long run, and you'll have the time
105
+ # to upgrade. With maxmemory after the limit is reached you'll start to get
106
+ # errors for write operations, and this may even lead to DB inconsistency.
107
+
108
+ # maxmemory <bytes>
109
+
110
+ ############################### ADVANCED CONFIG ###############################
111
+
112
+ # Glue small output buffers together in order to send small replies in a
113
+ # single TCP packet. Uses a bit more CPU but most of the times it is a win
114
+ # in terms of number of queries per second. Use 'yes' if unsure.
115
+ glueoutputbuf yes
116
+
117
+ # Use object sharing. Can save a lot of memory if you have many common
118
+ # string in your dataset, but performs lookups against the shared objects
119
+ # pool so it uses more CPU and can be a bit slower. Usually it's a good
120
+ # idea.
121
+ #
122
+ # When object sharing is enabled (shareobjects yes) you can use
123
+ # shareobjectspoolsize to control the size of the pool used in order to try
124
+ # object sharing. A bigger pool size will lead to better sharing capabilities.
125
+ # In general you want this value to be at least the double of the number of
126
+ # very common strings you have in your dataset.
127
+ #
128
+ # WARNING: object sharing is experimental, don't enable this feature
129
+ # in production before of Redis 1.0-stable. Still please try this feature in
130
+ # your development environment so that we can test it better.
131
+ shareobjects no
132
+ shareobjectspoolsize 1024
@@ -0,0 +1,160 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Resque" do
4
+ setup do
5
+ Resque.redis.flush_all
6
+
7
+ Resque.push(:people, { 'name' => 'chris' })
8
+ Resque.push(:people, { 'name' => 'bob' })
9
+ Resque.push(:people, { 'name' => 'mark' })
10
+ end
11
+
12
+ test "can put jobs on a queue" do
13
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
14
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
15
+ end
16
+
17
+ test "can grab jobs off a queue" do
18
+ Resque::Job.create(:jobs, 'some-job', 20, '/tmp')
19
+
20
+ job = Resque.reserve(:jobs)
21
+
22
+ assert_kind_of Resque::Job, job
23
+ assert_equal SomeJob, job.payload_class
24
+ assert_equal 20, job.args[0]
25
+ assert_equal '/tmp', job.args[1]
26
+ end
27
+
28
+ test "can put jobs on a queue by way of an ivar" do
29
+ assert_equal 0, Resque.size(:ivar)
30
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
31
+ assert Resque.enqueue(SomeIvarJob, 20, '/tmp')
32
+
33
+ job = Resque.reserve(:ivar)
34
+
35
+ assert_kind_of Resque::Job, job
36
+ assert_equal SomeIvarJob, job.payload_class
37
+ assert_equal 20, job.args[0]
38
+ assert_equal '/tmp', job.args[1]
39
+
40
+ assert Resque.reserve(:ivar)
41
+ assert_equal nil, Resque.reserve(:ivar)
42
+ end
43
+
44
+ test "jobs have a nice #inspect" do
45
+ assert Resque::Job.create(:jobs, 'SomeJob', 20, '/tmp')
46
+ job = Resque.reserve(:jobs)
47
+ assert_equal '(Job{jobs} | SomeJob | [20, "/tmp"])', job.inspect
48
+ end
49
+
50
+ test "can put jobs on a queue by way of a method" do
51
+ assert_equal 0, Resque.size(:method)
52
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
53
+ assert Resque.enqueue(SomeMethodJob, 20, '/tmp')
54
+
55
+ job = Resque.reserve(:method)
56
+
57
+ assert_kind_of Resque::Job, job
58
+ assert_equal SomeMethodJob, job.payload_class
59
+ assert_equal 20, job.args[0]
60
+ assert_equal '/tmp', job.args[1]
61
+
62
+ assert Resque.reserve(:method)
63
+ assert_equal nil, Resque.reserve(:method)
64
+ end
65
+
66
+ test "needs to infer a queue with enqueue" do
67
+ assert_raises Resque::NoQueueError do
68
+ Resque.enqueue(SomeJob, 20, '/tmp')
69
+ end
70
+ end
71
+
72
+ test "can put items on a queue" do
73
+ assert Resque.push(:people, { 'name' => 'jon' })
74
+ end
75
+
76
+ test "can pull items off a queue" do
77
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
78
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
79
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
80
+ assert_equal nil, Resque.pop(:people)
81
+ end
82
+
83
+ test "knows how big a queue is" do
84
+ assert_equal 3, Resque.size(:people)
85
+
86
+ assert_equal({ 'name' => 'chris' }, Resque.pop(:people))
87
+ assert_equal 2, Resque.size(:people)
88
+
89
+ assert_equal({ 'name' => 'bob' }, Resque.pop(:people))
90
+ assert_equal({ 'name' => 'mark' }, Resque.pop(:people))
91
+ assert_equal 0, Resque.size(:people)
92
+ end
93
+
94
+ test "can peek at a queue" do
95
+ assert_equal({ 'name' => 'chris' }, Resque.peek(:people))
96
+ assert_equal 3, Resque.size(:people)
97
+ end
98
+
99
+ test "can peek multiple items on a queue" do
100
+ assert_equal({ 'name' => 'bob' }, Resque.peek(:people, 1, 1))
101
+
102
+ assert_equal([{ 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 1, 2))
103
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }], Resque.peek(:people, 0, 2))
104
+ assert_equal([{ 'name' => 'chris' }, { 'name' => 'bob' }, { 'name' => 'mark' }], Resque.peek(:people, 0, 3))
105
+ assert_equal({ 'name' => 'mark' }, Resque.peek(:people, 2, 1))
106
+ assert_equal nil, Resque.peek(:people, 3)
107
+ assert_equal [], Resque.peek(:people, 3, 2)
108
+ end
109
+
110
+ test "knows what queues it is managing" do
111
+ assert_equal %w( people ), Resque.queues
112
+ Resque.push(:cars, { 'make' => 'bmw' })
113
+ assert_equal %w( cars people ), Resque.queues
114
+ end
115
+
116
+ test "queues are always a list" do
117
+ Resque.redis.flush_all
118
+ assert_equal [], Resque.queues
119
+ end
120
+
121
+ test "keeps track of resque keys" do
122
+ assert_equal ["queue:people", "queues"], Resque.keys
123
+ end
124
+
125
+ test "badly wants a class name, too" do
126
+ assert_raises Resque::NoClassError do
127
+ Resque::Job.create(:jobs, nil)
128
+ end
129
+ end
130
+
131
+ test "keeps stats" do
132
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
133
+ Resque::Job.create(:jobs, BadJob)
134
+ Resque::Job.create(:jobs, GoodJob)
135
+
136
+ Resque::Job.create(:others, GoodJob)
137
+ Resque::Job.create(:others, GoodJob)
138
+
139
+ stats = Resque.info
140
+ assert_equal 8, stats[:pending]
141
+
142
+ @worker = Resque::Worker.new(:jobs)
143
+ @worker.register_worker
144
+ 2.times { @worker.process }
145
+ job = @worker.reserve
146
+ @worker.working_on job
147
+
148
+ stats = Resque.info
149
+ assert_equal 1, stats[:working]
150
+ assert_equal 1, stats[:workers]
151
+
152
+ @worker.done_working
153
+
154
+ stats = Resque.info
155
+ assert_equal 3, stats[:queues]
156
+ assert_equal 3, stats[:processed]
157
+ assert_equal 1, stats[:failed]
158
+ assert_equal ['localhost:9736'], stats[:servers]
159
+ end
160
+ end
@@ -0,0 +1,90 @@
1
+ dir = File.dirname(File.expand_path(__FILE__))
2
+ $LOAD_PATH.unshift dir + '/../lib'
3
+ $TESTING = true
4
+ require 'test/unit'
5
+ require 'rubygems'
6
+ require 'resque'
7
+
8
+
9
+ #
10
+ # make sure we can run redis
11
+ #
12
+
13
+ if `which redis-server`.chomp.empty?
14
+ puts '', "** can't find `redis-server` in your path"
15
+ puts "** try running `sudo rake install`"
16
+ abort ''
17
+ end
18
+
19
+
20
+ #
21
+ # start our own redis when the tests start,
22
+ # kill it when they end
23
+ #
24
+
25
+ at_exit do
26
+ unless $! || Test::Unit.run?
27
+ status = Test::Unit::AutoRunner.run
28
+ pid = `ps -e -o pid,command | grep [r]edis-test`.split(" ")[0]
29
+ puts "Killing test redis server..."
30
+ `rm -f #{dir}/dump.rdb`
31
+ Process.kill("KILL", pid.to_i)
32
+ exit status
33
+ end
34
+ end
35
+
36
+ puts "Starting redis for testing at localhost:9736..."
37
+ `redis-server #{dir}/redis-test.conf`
38
+ Resque.redis = 'localhost:9736'
39
+
40
+
41
+ ##
42
+ # test/spec/mini 2
43
+ # http://gist.github.com/25455
44
+ # chris@ozmm.org
45
+ #
46
+ def context(*args, &block)
47
+ return super unless (name = args.first) && block
48
+ require 'test/unit'
49
+ klass = Class.new(defined?(ActiveSupport::TestCase) ? ActiveSupport::TestCase : Test::Unit::TestCase) do
50
+ def self.test(name, &block)
51
+ define_method("test_#{name.gsub(/\W/,'_')}", &block) if block
52
+ end
53
+ def self.xtest(*args) end
54
+ def self.setup(&block) define_method(:setup, &block) end
55
+ def self.teardown(&block) define_method(:teardown, &block) end
56
+ end
57
+ klass.class_eval &block
58
+ end
59
+
60
+
61
+ #
62
+ # fixture classes
63
+ #
64
+
65
+ class SomeJob
66
+ def self.perform(repo_id, path)
67
+ end
68
+ end
69
+
70
+ class SomeIvarJob < SomeJob
71
+ @queue = :ivar
72
+ end
73
+
74
+ class SomeMethodJob < SomeJob
75
+ def self.queue
76
+ :method
77
+ end
78
+ end
79
+
80
+ class BadJob
81
+ def self.perform
82
+ raise "Bad job!"
83
+ end
84
+ end
85
+
86
+ class GoodJob
87
+ def self.perform(name)
88
+ "Good job, #{name}"
89
+ end
90
+ end
@@ -0,0 +1,220 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ context "Resque::Worker" do
4
+ setup do
5
+ Resque.redis.flush_all
6
+
7
+ @worker = Resque::Worker.new(:jobs)
8
+ Resque::Job.create(:jobs, SomeJob, 20, '/tmp')
9
+ end
10
+
11
+ test "can fail jobs" do
12
+ Resque::Job.create(:jobs, BadJob)
13
+ @worker.work(0)
14
+ assert_equal 1, Resque::Failure.count
15
+ end
16
+
17
+ test "can peek at failed jobs" do
18
+ 10.times { Resque::Job.create(:jobs, BadJob) }
19
+ @worker.work(0)
20
+ assert_equal 10, Resque::Failure.count
21
+
22
+ assert_equal 10, Resque::Failure.all(0, 20).size
23
+ end
24
+
25
+ test "can clear failed jobs" do
26
+ Resque::Job.create(:jobs, BadJob)
27
+ @worker.work(0)
28
+ assert_equal 1, Resque::Failure.count
29
+ Resque::Failure.clear
30
+ assert_equal 0, Resque::Failure.count
31
+ end
32
+
33
+ test "catches exceptional jobs" do
34
+ Resque::Job.create(:jobs, BadJob)
35
+ Resque::Job.create(:jobs, BadJob)
36
+ @worker.process
37
+ @worker.process
38
+ @worker.process
39
+ assert_equal 2, Resque::Failure.count
40
+ end
41
+
42
+ test "can work on multiple queues" do
43
+ Resque::Job.create(:high, GoodJob)
44
+ Resque::Job.create(:critical, GoodJob)
45
+
46
+ worker = Resque::Worker.new(:critical, :high)
47
+
48
+ worker.process
49
+ assert_equal 1, Resque.size(:high)
50
+ assert_equal 0, Resque.size(:critical)
51
+
52
+ worker.process
53
+ assert_equal 0, Resque.size(:high)
54
+ end
55
+
56
+ test "can work on all queues" do
57
+ Resque::Job.create(:high, GoodJob)
58
+ Resque::Job.create(:critical, GoodJob)
59
+ Resque::Job.create(:blahblah, GoodJob)
60
+
61
+ worker = Resque::Worker.new("*")
62
+
63
+ worker.work(0)
64
+ assert_equal 0, Resque.size(:high)
65
+ assert_equal 0, Resque.size(:critical)
66
+ assert_equal 0, Resque.size(:blahblah)
67
+ end
68
+
69
+ test "processes * queues in alphabetical order" do
70
+ Resque::Job.create(:high, GoodJob)
71
+ Resque::Job.create(:critical, GoodJob)
72
+ Resque::Job.create(:blahblah, GoodJob)
73
+
74
+ worker = Resque::Worker.new("*")
75
+ processed_queues = []
76
+
77
+ worker.work(0) do |job|
78
+ processed_queues << job.queue
79
+ end
80
+
81
+ assert_equal %w( jobs high critical blahblah ).sort, processed_queues
82
+ end
83
+
84
+ test "has a unique id" do
85
+ assert_equal "#{`hostname`.chomp}:#{$$}:jobs", @worker.to_s
86
+ end
87
+
88
+ test "complains if no queues are given" do
89
+ assert_raise Resque::NoQueueError do
90
+ Resque::Worker.new
91
+ end
92
+ end
93
+
94
+ test "inserts itself into the 'workers' list on startup" do
95
+ @worker.work(0) do
96
+ assert_equal @worker, Resque.workers[0]
97
+ end
98
+ end
99
+
100
+ test "removes itself from the 'workers' list on shutdown" do
101
+ @worker.work(0) do
102
+ assert_equal @worker, Resque.workers[0]
103
+ end
104
+
105
+ assert_equal [], Resque.workers
106
+ end
107
+
108
+ test "records what it is working on" do
109
+ @worker.work(0) do
110
+ task = @worker.job
111
+ assert_equal({"args"=>[20, "/tmp"], "class"=>"SomeJob"}, task['payload'])
112
+ assert task['run_at']
113
+ assert_equal 'jobs', task['queue']
114
+ end
115
+ end
116
+
117
+ test "clears its status when not working on anything" do
118
+ @worker.work(0)
119
+ assert_equal Hash.new, @worker.job
120
+ end
121
+
122
+ test "knows when it is working" do
123
+ @worker.work(0) do
124
+ assert @worker.working?
125
+ end
126
+ end
127
+
128
+ test "knows when it is idle" do
129
+ @worker.work(0)
130
+ assert @worker.idle?
131
+ end
132
+
133
+ test "knows who is working" do
134
+ @worker.work(0) do
135
+ assert_equal [@worker], Resque.working
136
+ end
137
+ end
138
+
139
+ test "keeps track of how many jobs it has processed" do
140
+ Resque::Job.create(:jobs, BadJob)
141
+ Resque::Job.create(:jobs, BadJob)
142
+
143
+ 3.times do
144
+ job = @worker.reserve
145
+ @worker.process job
146
+ end
147
+ assert_equal 3, @worker.processed
148
+ end
149
+
150
+ test "keeps track of how many failures it has seen" do
151
+ Resque::Job.create(:jobs, BadJob)
152
+ Resque::Job.create(:jobs, BadJob)
153
+
154
+ 3.times do
155
+ job = @worker.reserve
156
+ @worker.process job
157
+ end
158
+ assert_equal 2, @worker.failed
159
+ end
160
+
161
+ test "stats are erased when the worker goes away" do
162
+ @worker.work(0)
163
+ assert_equal 0, @worker.processed
164
+ assert_equal 0, @worker.failed
165
+ end
166
+
167
+ test "knows when it started" do
168
+ time = Time.now
169
+ @worker.work(0) do
170
+ assert_equal time.to_s, @worker.started.to_s
171
+ end
172
+ end
173
+
174
+ test "knows whether it exists or not" do
175
+ @worker.work(0) do
176
+ assert Resque::Worker.exists?(@worker)
177
+ assert !Resque::Worker.exists?('blah-blah')
178
+ end
179
+ end
180
+
181
+ test "sets $0 while working" do
182
+ @worker.work(0) do
183
+ assert_equal "resque: Processing jobs since #{Time.now.to_i}", $0
184
+ end
185
+ end
186
+
187
+ test "can be found" do
188
+ @worker.work(0) do
189
+ found = Resque::Worker.find(@worker.to_s)
190
+ assert_equal @worker.to_s, found.to_s
191
+ assert found.working?
192
+ assert_equal @worker.job, found.job
193
+ end
194
+ end
195
+
196
+ test "doesn't find fakes" do
197
+ @worker.work(0) do
198
+ found = Resque::Worker.find('blah-blah')
199
+ assert_equal nil, found
200
+ end
201
+ end
202
+
203
+ test "cleans up dead worker info on start (crash recovery)" do
204
+ # first we fake out two dead workers
205
+ workerA = Resque::Worker.new(:jobs)
206
+ workerA.instance_variable_set(:@to_s, "#{`hostname`.chomp}:1:jobs")
207
+ workerA.register_worker
208
+
209
+ workerB = Resque::Worker.new(:high, :low)
210
+ workerB.instance_variable_set(:@to_s, "#{`hostname`.chomp}:2:high,low")
211
+ workerB.register_worker
212
+
213
+ assert_equal 2, Resque.workers.size
214
+
215
+ # then we prune them
216
+ @worker.work(0) do
217
+ assert_equal 1, Resque.workers.size
218
+ end
219
+ end
220
+ end