scotttam-resque 0.0.1

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.
Files changed (61) hide show
  1. data/.gitignore +3 -0
  2. data/.kick +26 -0
  3. data/CONTRIBUTORS +23 -0
  4. data/HISTORY.md +80 -0
  5. data/LICENSE +20 -0
  6. data/README.markdown +767 -0
  7. data/Rakefile +66 -0
  8. data/bin/resque +57 -0
  9. data/bin/resque-web +18 -0
  10. data/config.ru +14 -0
  11. data/deps.rip +6 -0
  12. data/examples/async_helper.rb +31 -0
  13. data/examples/demo/README.markdown +71 -0
  14. data/examples/demo/Rakefile +3 -0
  15. data/examples/demo/app.rb +38 -0
  16. data/examples/demo/config.ru +19 -0
  17. data/examples/demo/job.rb +22 -0
  18. data/examples/god/resque.god +53 -0
  19. data/examples/god/stale.god +26 -0
  20. data/examples/instance.rb +11 -0
  21. data/examples/simple.rb +30 -0
  22. data/init.rb +1 -0
  23. data/lib/resque/errors.rb +7 -0
  24. data/lib/resque/failure/base.rb +58 -0
  25. data/lib/resque/failure/hoptoad.rb +121 -0
  26. data/lib/resque/failure/multiple.rb +44 -0
  27. data/lib/resque/failure/redis.rb +33 -0
  28. data/lib/resque/failure.rb +63 -0
  29. data/lib/resque/helpers.rb +57 -0
  30. data/lib/resque/job.rb +146 -0
  31. data/lib/resque/server/public/idle.png +0 -0
  32. data/lib/resque/server/public/jquery-1.3.2.min.js +19 -0
  33. data/lib/resque/server/public/jquery.relatize_date.js +95 -0
  34. data/lib/resque/server/public/poll.png +0 -0
  35. data/lib/resque/server/public/ranger.js +24 -0
  36. data/lib/resque/server/public/reset.css +48 -0
  37. data/lib/resque/server/public/style.css +76 -0
  38. data/lib/resque/server/public/working.png +0 -0
  39. data/lib/resque/server/views/error.erb +1 -0
  40. data/lib/resque/server/views/failed.erb +35 -0
  41. data/lib/resque/server/views/key.erb +17 -0
  42. data/lib/resque/server/views/layout.erb +38 -0
  43. data/lib/resque/server/views/next_more.erb +10 -0
  44. data/lib/resque/server/views/overview.erb +4 -0
  45. data/lib/resque/server/views/queues.erb +46 -0
  46. data/lib/resque/server/views/stats.erb +62 -0
  47. data/lib/resque/server/views/workers.erb +78 -0
  48. data/lib/resque/server/views/working.erb +69 -0
  49. data/lib/resque/server.rb +187 -0
  50. data/lib/resque/stat.rb +53 -0
  51. data/lib/resque/tasks.rb +39 -0
  52. data/lib/resque/version.rb +3 -0
  53. data/lib/resque/worker.rb +453 -0
  54. data/lib/resque.rb +246 -0
  55. data/tasks/redis.rake +135 -0
  56. data/tasks/resque.rake +2 -0
  57. data/test/redis-test.conf +132 -0
  58. data/test/resque_test.rb +220 -0
  59. data/test/test_helper.rb +96 -0
  60. data/test/worker_test.rb +260 -0
  61. metadata +172 -0
@@ -0,0 +1,187 @@
1
+ require 'sinatra/base'
2
+ require 'erb'
3
+ require 'resque'
4
+ require 'resque/version'
5
+
6
+ module Resque
7
+ class Server < Sinatra::Base
8
+ dir = File.dirname(File.expand_path(__FILE__))
9
+
10
+ set :views, "#{dir}/server/views"
11
+ set :public, "#{dir}/server/public"
12
+ set :static, true
13
+
14
+ helpers do
15
+ include Rack::Utils
16
+ alias_method :h, :escape_html
17
+
18
+ def current_section
19
+ url request.path_info.sub('/','').split('/')[0].downcase
20
+ end
21
+
22
+ def current_page
23
+ url request.path_info.sub('/','').downcase
24
+ end
25
+
26
+ def url(*path_parts)
27
+ [ path_prefix, path_parts ].join("/").squeeze('/')
28
+ end
29
+ alias_method :u, :url
30
+
31
+ def path_prefix
32
+ request.env['SCRIPT_NAME']
33
+ end
34
+
35
+ def class_if_current(path = '')
36
+ 'class="current"' if current_page.start_with?(path.to_s)
37
+ end
38
+
39
+ def tab(name)
40
+ dname = name.to_s.downcase
41
+ path = url(dname)
42
+ "<li #{class_if_current(path)}><a href='#{path}'>#{name}</a></li>"
43
+ end
44
+
45
+ def tabs
46
+ Resque::Server.tabs
47
+ end
48
+
49
+ def redis_get_size(key)
50
+ case Resque.redis.type(key)
51
+ when 'none'
52
+ []
53
+ when 'list'
54
+ Resque.redis.llen(key)
55
+ when 'set'
56
+ Resque.redis.scard(key)
57
+ when 'string'
58
+ Resque.redis.get(key).length
59
+ when 'zset'
60
+ Resque.redis.zcard(key)
61
+ end
62
+ end
63
+
64
+ def redis_get_value_as_array(key, start=0)
65
+ case Resque.redis.type(key)
66
+ when 'none'
67
+ []
68
+ when 'list'
69
+ Resque.redis.lrange(key, start, start + 20)
70
+ when 'set'
71
+ Resque.redis.smembers(key)[start..(start + 20)]
72
+ when 'string'
73
+ [Resque.redis.get(key)]
74
+ when 'zset'
75
+ Resque.redis.zrange(key, start, start + 20)
76
+ end
77
+ end
78
+
79
+ def show_args(args)
80
+ Array(args).map { |a| a.inspect }.join("\n")
81
+ end
82
+
83
+ def partial?
84
+ @partial
85
+ end
86
+
87
+ def partial(template, local_vars = {})
88
+ @partial = true
89
+ erb(template.to_sym, {:layout => false}, local_vars)
90
+ ensure
91
+ @partial = false
92
+ end
93
+
94
+ def poll
95
+ if @polling
96
+ text = "Last Updated: #{Time.now.strftime("%H:%M:%S")}"
97
+ else
98
+ text = "<a href='#{url(request.path_info)}.poll' rel='poll'>Live Poll</a>"
99
+ end
100
+ "<p class='poll'>#{text}</p>"
101
+ end
102
+
103
+ end
104
+
105
+ def show(page, layout = true)
106
+ begin
107
+ erb page.to_sym, {:layout => layout}, :resque => Resque
108
+ rescue Errno::ECONNREFUSED
109
+ erb :error, {:layout => false}, :error => "Can't connect to Redis! (#{Resque.redis.server})"
110
+ end
111
+ end
112
+
113
+ # to make things easier on ourselves
114
+ get "/?" do
115
+ redirect url(:overview)
116
+ end
117
+
118
+ %w( overview queues working workers key ).each do |page|
119
+ get "/#{page}" do
120
+ show page
121
+ end
122
+
123
+ get "/#{page}/:id" do
124
+ show page
125
+ end
126
+ end
127
+
128
+ %w( overview workers ).each do |page|
129
+ get "/#{page}.poll" do
130
+ content_type "text/plain"
131
+ @polling = true
132
+ show(page.to_sym, false).gsub(/\s{1,}/, ' ')
133
+ end
134
+ end
135
+
136
+ get "/failed" do
137
+ if Resque::Failure.url
138
+ redirect Resque::Failure.url
139
+ else
140
+ show :failed
141
+ end
142
+ end
143
+
144
+ post "/failed/clear" do
145
+ Resque::Failure.clear
146
+ redirect u('failed')
147
+ end
148
+
149
+ get "/stats" do
150
+ redirect url("/stats/resque")
151
+ end
152
+
153
+ get "/stats/:id" do
154
+ show :stats
155
+ end
156
+
157
+ get "/stats/keys/:key" do
158
+ show :stats
159
+ end
160
+
161
+ get "/stats.txt" do
162
+ info = Resque.info
163
+
164
+ stats = []
165
+ stats << "resque.pending=#{info[:pending]}"
166
+ stats << "resque.processed+=#{info[:processed]}"
167
+ stats << "resque.failed+=#{info[:failed]}"
168
+ stats << "resque.workers=#{info[:workers]}"
169
+ stats << "resque.working=#{info[:working]}"
170
+
171
+ Resque.queues.each do |queue|
172
+ stats << "queues.#{queue}=#{Resque.size(queue)}"
173
+ end
174
+
175
+ content_type 'text/plain'
176
+ stats.join "\n"
177
+ end
178
+
179
+ def resque
180
+ Resque
181
+ end
182
+
183
+ def self.tabs
184
+ @tabs ||= ["Overview", "Working", "Failed", "Queues", "Workers", "Stats"]
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,53 @@
1
+ module Resque
2
+ # The stat subsystem. Used to keep track of integer counts.
3
+ #
4
+ # Get a stat: Stat[name]
5
+ # Incr a stat: Stat.incr(name)
6
+ # Decr a stat: Stat.decr(name)
7
+ # Kill a stat: Stat.clear(name)
8
+ module Stat
9
+ extend self
10
+ extend Helpers
11
+
12
+ # Returns the int value of a stat, given a string stat name.
13
+ def get(stat)
14
+ redis.get("stat:#{stat}").to_i
15
+ end
16
+
17
+ # Alias of `get`
18
+ def [](stat)
19
+ get(stat)
20
+ end
21
+
22
+ # For a string stat name, increments the stat by one.
23
+ #
24
+ # Can optionally accept a second int parameter. The stat is then
25
+ # incremented by that amount.
26
+ def incr(stat, by = 1)
27
+ redis.incr("stat:#{stat}", by)
28
+ end
29
+
30
+ # Increments a stat by one.
31
+ def <<(stat)
32
+ incr stat
33
+ end
34
+
35
+ # For a string stat name, decrements the stat by one.
36
+ #
37
+ # Can optionally accept a second int parameter. The stat is then
38
+ # decremented by that amount.
39
+ def decr(stat, by = 1)
40
+ redis.decr("stat:#{stat}", by)
41
+ end
42
+
43
+ # Decrements a stat by one.
44
+ def >>(stat)
45
+ decr stat
46
+ end
47
+
48
+ # Removes a stat from Redis, effectively setting it to 0.
49
+ def clear(stat)
50
+ redis.del("stat:#{stat}")
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,39 @@
1
+ # require 'resque/tasks'
2
+ # will give you the resque tasks
3
+
4
+ namespace :resque do
5
+ task :setup
6
+
7
+ desc "Start a Resque worker"
8
+ task :work => :setup do
9
+ require 'resque'
10
+
11
+ worker = nil
12
+ queues = (ENV['QUEUES'] || ENV['QUEUE']).to_s.split(',')
13
+
14
+ begin
15
+ worker = Resque::Worker.new(*queues)
16
+ worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
17
+ worker.very_verbose = ENV['VVERBOSE']
18
+ rescue Resque::NoQueueError
19
+ abort "set QUEUE env var, e.g. $ QUEUE=critical,high rake resque:work"
20
+ end
21
+
22
+ puts "*** Starting worker #{worker}"
23
+
24
+ worker.work(ENV['INTERVAL'] || 5) # interval, will block
25
+ end
26
+
27
+ desc "Start multiple Resque workers. Should only be used in dev mode."
28
+ task :workers do
29
+ threads = []
30
+
31
+ ENV['COUNT'].to_i.times do
32
+ threads << Thread.new do
33
+ system "rake resque:work"
34
+ end
35
+ end
36
+
37
+ threads.each { |thread| thread.join }
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ module Resque
2
+ Version = '0.0.1'
3
+ end