resque_sqs 1.25.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/HISTORY.md +467 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +866 -0
  5. data/Rakefile +70 -0
  6. data/bin/resque-sqs +81 -0
  7. data/bin/resque-sqs-web +27 -0
  8. data/lib/resque_sqs/errors.rb +13 -0
  9. data/lib/resque_sqs/failure/airbrake.rb +33 -0
  10. data/lib/resque_sqs/failure/base.rb +73 -0
  11. data/lib/resque_sqs/failure/multiple.rb +59 -0
  12. data/lib/resque_sqs/failure/redis.rb +108 -0
  13. data/lib/resque_sqs/failure/redis_multi_queue.rb +89 -0
  14. data/lib/resque_sqs/failure.rb +113 -0
  15. data/lib/resque_sqs/helpers.rb +107 -0
  16. data/lib/resque_sqs/job.rb +346 -0
  17. data/lib/resque_sqs/log_formatters/quiet_formatter.rb +7 -0
  18. data/lib/resque_sqs/log_formatters/verbose_formatter.rb +7 -0
  19. data/lib/resque_sqs/log_formatters/very_verbose_formatter.rb +8 -0
  20. data/lib/resque_sqs/logging.rb +18 -0
  21. data/lib/resque_sqs/plugin.rb +66 -0
  22. data/lib/resque_sqs/server/helpers.rb +52 -0
  23. data/lib/resque_sqs/server/public/favicon.ico +0 -0
  24. data/lib/resque_sqs/server/public/idle.png +0 -0
  25. data/lib/resque_sqs/server/public/jquery-1.3.2.min.js +19 -0
  26. data/lib/resque_sqs/server/public/jquery.relatize_date.js +95 -0
  27. data/lib/resque_sqs/server/public/poll.png +0 -0
  28. data/lib/resque_sqs/server/public/ranger.js +78 -0
  29. data/lib/resque_sqs/server/public/reset.css +44 -0
  30. data/lib/resque_sqs/server/public/style.css +91 -0
  31. data/lib/resque_sqs/server/public/working.png +0 -0
  32. data/lib/resque_sqs/server/test_helper.rb +19 -0
  33. data/lib/resque_sqs/server/views/error.erb +1 -0
  34. data/lib/resque_sqs/server/views/failed.erb +29 -0
  35. data/lib/resque_sqs/server/views/failed_job.erb +50 -0
  36. data/lib/resque_sqs/server/views/failed_queues_overview.erb +24 -0
  37. data/lib/resque_sqs/server/views/key_sets.erb +19 -0
  38. data/lib/resque_sqs/server/views/key_string.erb +11 -0
  39. data/lib/resque_sqs/server/views/layout.erb +44 -0
  40. data/lib/resque_sqs/server/views/next_more.erb +22 -0
  41. data/lib/resque_sqs/server/views/overview.erb +4 -0
  42. data/lib/resque_sqs/server/views/queues.erb +58 -0
  43. data/lib/resque_sqs/server/views/stats.erb +62 -0
  44. data/lib/resque_sqs/server/views/workers.erb +109 -0
  45. data/lib/resque_sqs/server/views/working.erb +72 -0
  46. data/lib/resque_sqs/server.rb +271 -0
  47. data/lib/resque_sqs/stat.rb +57 -0
  48. data/lib/resque_sqs/tasks.rb +83 -0
  49. data/lib/resque_sqs/vendor/utf8_util/utf8_util_18.rb +91 -0
  50. data/lib/resque_sqs/vendor/utf8_util/utf8_util_19.rb +5 -0
  51. data/lib/resque_sqs/vendor/utf8_util.rb +20 -0
  52. data/lib/resque_sqs/version.rb +3 -0
  53. data/lib/resque_sqs/worker.rb +779 -0
  54. data/lib/resque_sqs.rb +479 -0
  55. data/lib/tasks/redis_sqs.rake +161 -0
  56. data/lib/tasks/resque_sqs.rake +2 -0
  57. data/test/airbrake_test.rb +27 -0
  58. data/test/failure_base_test.rb +15 -0
  59. data/test/job_hooks_test.rb +465 -0
  60. data/test/job_plugins_test.rb +230 -0
  61. data/test/logging_test.rb +24 -0
  62. data/test/plugin_test.rb +116 -0
  63. data/test/redis-test-cluster.conf +115 -0
  64. data/test/redis-test.conf +115 -0
  65. data/test/resque-web_test.rb +59 -0
  66. data/test/resque_failure_redis_test.rb +19 -0
  67. data/test/resque_hook_test.rb +165 -0
  68. data/test/resque_test.rb +278 -0
  69. data/test/stdout +42 -0
  70. data/test/test_helper.rb +228 -0
  71. data/test/worker_test.rb +1080 -0
  72. metadata +202 -0
data/lib/resque_sqs.rb ADDED
@@ -0,0 +1,479 @@
1
+ require 'mono_logger'
2
+ require 'redis/namespace'
3
+ require 'forwardable'
4
+
5
+ require 'resque_sqs/version'
6
+
7
+ require 'resque_sqs/errors'
8
+
9
+ require 'resque_sqs/failure'
10
+ require 'resque_sqs/failure/base'
11
+
12
+ require 'resque_sqs/helpers'
13
+ require 'resque_sqs/stat'
14
+ require 'resque_sqs/logging'
15
+ require 'resque_sqs/log_formatters/quiet_formatter'
16
+ require 'resque_sqs/log_formatters/verbose_formatter'
17
+ require 'resque_sqs/log_formatters/very_verbose_formatter'
18
+ require 'resque_sqs/job'
19
+ require 'resque_sqs/worker'
20
+ require 'resque_sqs/plugin'
21
+
22
+ require 'resque_sqs/vendor/utf8_util'
23
+
24
+ module ResqueSqs
25
+ extend self
26
+
27
+ # Given a Ruby object, returns a string suitable for storage in a
28
+ # queue.
29
+ def encode(object)
30
+ if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
31
+ MultiJson.dump object
32
+ else
33
+ MultiJson.encode object
34
+ end
35
+ end
36
+
37
+ # Given a string, returns a Ruby object.
38
+ def decode(object)
39
+ return unless object
40
+
41
+ begin
42
+ if MultiJson.respond_to?(:dump) && MultiJson.respond_to?(:load)
43
+ MultiJson.load object
44
+ else
45
+ MultiJson.decode object
46
+ end
47
+ rescue ::MultiJson::DecodeError => e
48
+ raise Helpers::DecodeException, e.message, e.backtrace
49
+ end
50
+ end
51
+
52
+ extend ::Forwardable
53
+
54
+ def self.config=(options = {})
55
+ @config = Config.new(options)
56
+ end
57
+
58
+ def self.config
59
+ @config ||= Config.new
60
+ end
61
+
62
+ def self.configure
63
+ yield config
64
+ end
65
+
66
+ # Accepts:
67
+ # 1. A 'hostname:port' String
68
+ # 2. A 'hostname:port:db' String (to select the Redis db)
69
+ # 3. A 'hostname:port/namespace' String (to set the Redis namespace)
70
+ # 4. A Redis URL String 'redis://host:port'
71
+ # 5. An instance of `Redis`, `Redis::Client`, `Redis::DistRedis`,
72
+ # or `Redis::Namespace`.
73
+ # 6. An Hash of a redis connection {:host => 'localhost', :port => 6379, :db => 0}
74
+ def redis=(server)
75
+ case server
76
+ when String
77
+ if server =~ /redis\:\/\//
78
+ redis = Redis.connect(:url => server, :thread_safe => true)
79
+ else
80
+ server, namespace = server.split('/', 2)
81
+ host, port, db = server.split(':')
82
+ redis = Redis.new(:host => host, :port => port,
83
+ :thread_safe => true, :db => db)
84
+ end
85
+ namespace ||= :resque
86
+
87
+ @redis = Redis::Namespace.new(namespace, :redis => redis)
88
+ when Redis::Namespace
89
+ @redis = server
90
+ when Hash
91
+ @redis = Redis::Namespace.new(:resque, :redis => Redis.new(server))
92
+ else
93
+ @redis = Redis::Namespace.new(:resque, :redis => server)
94
+ end
95
+ end
96
+
97
+ # Returns the current Redis connection. If none has been created, will
98
+ # create a new one.
99
+ def redis
100
+ return @redis if @redis
101
+ self.redis = Redis.respond_to?(:connect) ? Redis.connect : "localhost:6379"
102
+ self.redis
103
+ end
104
+
105
+ def redis_id
106
+ # support 1.x versions of redis-rb
107
+ if redis.respond_to?(:server)
108
+ redis.server
109
+ elsif redis.respond_to?(:nodes) # distributed
110
+ redis.nodes.map { |n| n.id }.join(', ')
111
+ else
112
+ redis.client.id
113
+ end
114
+ end
115
+
116
+ # Set or retrieve the current logger object
117
+ attr_accessor :logger
118
+
119
+ # The `before_first_fork` hook will be run in the **parent** process
120
+ # only once, before forking to run the first job. Be careful- any
121
+ # changes you make will be permanent for the lifespan of the
122
+ # worker.
123
+ #
124
+ # Call with a block to register a hook.
125
+ # Call with no arguments to return all registered hooks.
126
+ def before_first_fork(&block)
127
+ block ? register_hook(:before_first_fork, block) : hooks(:before_first_fork)
128
+ end
129
+
130
+ # Register a before_first_fork proc.
131
+ def before_first_fork=(block)
132
+ register_hook(:before_first_fork, block)
133
+ end
134
+
135
+ # The `before_fork` hook will be run in the **parent** process
136
+ # before every job, so be careful- any changes you make will be
137
+ # permanent for the lifespan of the worker.
138
+ #
139
+ # Call with a block to register a hook.
140
+ # Call with no arguments to return all registered hooks.
141
+ def before_fork(&block)
142
+ block ? register_hook(:before_fork, block) : hooks(:before_fork)
143
+ end
144
+
145
+ # Register a before_fork proc.
146
+ def before_fork=(block)
147
+ register_hook(:before_fork, block)
148
+ end
149
+
150
+ # The `after_fork` hook will be run in the child process and is passed
151
+ # the current job. Any changes you make, therefore, will only live as
152
+ # long as the job currently being processed.
153
+ #
154
+ # Call with a block to register a hook.
155
+ # Call with no arguments to return all registered hooks.
156
+ def after_fork(&block)
157
+ block ? register_hook(:after_fork, block) : hooks(:after_fork)
158
+ end
159
+
160
+ # Register an after_fork proc.
161
+ def after_fork=(block)
162
+ register_hook(:after_fork, block)
163
+ end
164
+
165
+ # The `before_pause` hook will be run in the parent process before the
166
+ # worker has paused processing (via #pause_processing or SIGUSR2).
167
+ def before_pause(&block)
168
+ block ? register_hook(:before_pause, block) : hooks(:before_pause)
169
+ end
170
+
171
+ # Set the after_pause proc.
172
+ attr_writer :before_pause
173
+
174
+ # The `after_pause` hook will be run in the parent process after the
175
+ # worker has paused (via SIGCONT).
176
+ def after_pause(&block)
177
+ block ? register_hook(:after_pause, block) : hooks(:after_pause)
178
+ end
179
+
180
+ # Set the after_continue proc.
181
+ attr_writer :after_pause
182
+
183
+ def to_s
184
+ "Resque Client connected to #{redis_id}"
185
+ end
186
+
187
+ attr_accessor :inline
188
+
189
+ # If 'inline' is true Resque will call #perform method inline
190
+ # without queuing it into Redis and without any Resque callbacks.
191
+ # The 'inline' is false Resque jobs will be put in queue regularly.
192
+ alias :inline? :inline
193
+
194
+ #
195
+ # queue manipulation
196
+ #
197
+
198
+ # Pushes a job onto a queue. Queue name should be a string and the
199
+ # item should be any JSON-able Ruby object.
200
+ #
201
+ # Resque works generally expect the `item` to be a hash with the following
202
+ # keys:
203
+ #
204
+ # class - The String name of the job to run.
205
+ # args - An Array of arguments to pass the job. Usually passed
206
+ # via `class.to_class.perform(*args)`.
207
+ #
208
+ # Example
209
+ #
210
+ # ResqueSqs.push('archive', :class => 'Archive', :args => [ 35, 'tar' ])
211
+ #
212
+ # Returns nothing
213
+ def push(queue, item)
214
+ redis.pipelined do
215
+ watch_queue(queue)
216
+ redis.rpush "queue:#{queue}", encode(item)
217
+ end
218
+ end
219
+
220
+ # Pops a job off a queue. Queue name should be a string.
221
+ #
222
+ # Returns a Ruby object.
223
+ def pop(queue)
224
+ decode redis.lpop("queue:#{queue}")
225
+ end
226
+
227
+ # Returns an integer representing the size of a queue.
228
+ # Queue name should be a string.
229
+ def size(queue)
230
+ redis.llen("queue:#{queue}").to_i
231
+ end
232
+
233
+ # Returns an array of items currently queued. Queue name should be
234
+ # a string.
235
+ #
236
+ # start and count should be integer and can be used for pagination.
237
+ # start is the item to begin, count is how many items to return.
238
+ #
239
+ # To get the 3rd page of a 30 item, paginatied list one would use:
240
+ # ResqueSqs.peek('my_list', 59, 30)
241
+ def peek(queue, start = 0, count = 1)
242
+ list_range("queue:#{queue}", start, count)
243
+ end
244
+
245
+ # Does the dirty work of fetching a range of items from a Redis list
246
+ # and converting them into Ruby objects.
247
+ def list_range(key, start = 0, count = 1)
248
+ if count == 1
249
+ decode redis.lindex(key, start)
250
+ else
251
+ Array(redis.lrange(key, start, start+count-1)).map do |item|
252
+ decode item
253
+ end
254
+ end
255
+ end
256
+
257
+ # Returns an array of all known Resque queues as strings.
258
+ def queues
259
+ Array(redis.smembers(:queues))
260
+ end
261
+
262
+ # Given a queue name, completely deletes the queue.
263
+ def remove_queue(queue)
264
+ redis.pipelined do
265
+ redis.srem(:queues, queue.to_s)
266
+ redis.del("queue:#{queue}")
267
+ end
268
+ end
269
+
270
+ # Used internally to keep track of which queues we've created.
271
+ # Don't call this directly.
272
+ def watch_queue(queue)
273
+ redis.sadd(:queues, queue.to_s)
274
+ end
275
+
276
+
277
+ #
278
+ # job shortcuts
279
+ #
280
+
281
+ # This method can be used to conveniently add a job to a queue.
282
+ # It assumes the class you're passing it is a real Ruby class (not
283
+ # a string or reference) which either:
284
+ #
285
+ # a) has a @queue ivar set
286
+ # b) responds to `queue`
287
+ #
288
+ # If either of those conditions are met, it will use the value obtained
289
+ # from performing one of the above operations to determine the queue.
290
+ #
291
+ # If no queue can be inferred this method will raise a `ResqueSqs::NoQueueError`
292
+ #
293
+ # Returns true if the job was queued, nil if the job was rejected by a
294
+ # before_enqueue hook.
295
+ #
296
+ # This method is considered part of the `stable` API.
297
+ def enqueue(klass, *args)
298
+ enqueue_to(queue_from_class(klass), klass, *args)
299
+ end
300
+
301
+ # Just like `enqueue` but allows you to specify the queue you want to
302
+ # use. Runs hooks.
303
+ #
304
+ # `queue` should be the String name of the queue you're targeting.
305
+ #
306
+ # Returns true if the job was queued, nil if the job was rejected by a
307
+ # before_enqueue hook.
308
+ #
309
+ # This method is considered part of the `stable` API.
310
+ def enqueue_to(queue, klass, *args)
311
+ # Perform before_enqueue hooks. Don't perform enqueue if any hook returns false
312
+ before_hooks = Plugin.before_enqueue_hooks(klass).collect do |hook|
313
+ klass.send(hook, *args)
314
+ end
315
+ return nil if before_hooks.any? { |result| result == false }
316
+
317
+ Job.create(queue, klass, *args)
318
+
319
+ Plugin.after_enqueue_hooks(klass).each do |hook|
320
+ klass.send(hook, *args)
321
+ end
322
+
323
+ return true
324
+ end
325
+
326
+ # This method can be used to conveniently remove a job from a queue.
327
+ # It assumes the class you're passing it is a real Ruby class (not
328
+ # a string or reference) which either:
329
+ #
330
+ # a) has a @queue ivar set
331
+ # b) responds to `queue`
332
+ #
333
+ # If either of those conditions are met, it will use the value obtained
334
+ # from performing one of the above operations to determine the queue.
335
+ #
336
+ # If no queue can be inferred this method will raise a `ResqueSqs::NoQueueError`
337
+ #
338
+ # If no args are given, this method will dequeue *all* jobs matching
339
+ # the provided class. See `ResqueSqs::Job.destroy` for more
340
+ # information.
341
+ #
342
+ # Returns the number of jobs destroyed.
343
+ #
344
+ # Example:
345
+ #
346
+ # # Removes all jobs of class `UpdateNetworkGraph`
347
+ # ResqueSqs.dequeue(GitHub::Jobs::UpdateNetworkGraph)
348
+ #
349
+ # # Removes all jobs of class `UpdateNetworkGraph` with matching args.
350
+ # ResqueSqs.dequeue(GitHub::Jobs::UpdateNetworkGraph, 'repo:135325')
351
+ #
352
+ # This method is considered part of the `stable` API.
353
+ def dequeue(klass, *args)
354
+ # Perform before_dequeue hooks. Don't perform dequeue if any hook returns false
355
+ before_hooks = Plugin.before_dequeue_hooks(klass).collect do |hook|
356
+ klass.send(hook, *args)
357
+ end
358
+ return if before_hooks.any? { |result| result == false }
359
+
360
+ destroyed = Job.destroy(queue_from_class(klass), klass, *args)
361
+
362
+ Plugin.after_dequeue_hooks(klass).each do |hook|
363
+ klass.send(hook, *args)
364
+ end
365
+
366
+ destroyed
367
+ end
368
+
369
+ # Given a class, try to extrapolate an appropriate queue based on a
370
+ # class instance variable or `queue` method.
371
+ def queue_from_class(klass)
372
+ klass.instance_variable_get(:@queue) ||
373
+ (klass.respond_to?(:queue) and klass.queue)
374
+ end
375
+
376
+ # This method will return a `ResqueSqs::Job` object or a non-true value
377
+ # depending on whether a job can be obtained. You should pass it the
378
+ # precise name of a queue: case matters.
379
+ #
380
+ # This method is considered part of the `stable` API.
381
+ def reserve(queue)
382
+ Job.reserve(queue)
383
+ end
384
+
385
+ # Validates if the given klass could be a valid Resque job
386
+ #
387
+ # If no queue can be inferred this method will raise a `ResqueSqs::NoQueueError`
388
+ #
389
+ # If given klass is nil this method will raise a `ResqueSqs::NoClassError`
390
+ def validate(klass, queue = nil)
391
+ queue ||= queue_from_class(klass)
392
+
393
+ if !queue
394
+ raise NoQueueError.new("Jobs must be placed onto a queue.")
395
+ end
396
+
397
+ if klass.to_s.empty?
398
+ raise NoClassError.new("Jobs must be given a class.")
399
+ end
400
+ end
401
+
402
+
403
+ #
404
+ # worker shortcuts
405
+ #
406
+
407
+ # A shortcut to Worker.all
408
+ def workers
409
+ Worker.all
410
+ end
411
+
412
+ # A shortcut to Worker.working
413
+ def working
414
+ Worker.working
415
+ end
416
+
417
+ # A shortcut to unregister_worker
418
+ # useful for command line tool
419
+ def remove_worker(worker_id)
420
+ worker = ResqueSqs::Worker.find(worker_id)
421
+ worker.unregister_worker
422
+ end
423
+
424
+ #
425
+ # stats
426
+ #
427
+
428
+ # Returns a hash, similar to redis-rb's #info, of interesting stats.
429
+ def info
430
+ return {
431
+ :pending => queues.inject(0) { |m,k| m + size(k) },
432
+ :processed => Stat[:processed],
433
+ :queues => queues.size,
434
+ :workers => workers.size.to_i,
435
+ :working => working.size,
436
+ :failed => ResqueSqs.redis.llen(:failed).to_i,
437
+ :servers => [redis_id],
438
+ :environment => ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
439
+ }
440
+ end
441
+
442
+ # Returns an array of all known Resque keys in Redis. Redis' KEYS operation
443
+ # is O(N) for the keyspace, so be careful - this can be slow for big databases.
444
+ def keys
445
+ redis.keys("*").map do |key|
446
+ key.sub("#{redis.namespace}:", '')
447
+ end
448
+ end
449
+
450
+ private
451
+
452
+ # Register a new proc as a hook. If the block is nil this is the
453
+ # equivalent of removing all hooks of the given name.
454
+ #
455
+ # `name` is the hook that the block should be registered with.
456
+ def register_hook(name, block)
457
+ return clear_hooks(name) if block.nil?
458
+
459
+ @hooks ||= {}
460
+ @hooks[name] ||= []
461
+
462
+ block = Array(block)
463
+ @hooks[name].concat(block)
464
+ end
465
+
466
+ # Clear all hooks given a hook name.
467
+ def clear_hooks(name)
468
+ @hooks && @hooks[name] = []
469
+ end
470
+
471
+ # Retrieve all hooks of a given name.
472
+ def hooks(name)
473
+ (@hooks && @hooks[name]) || []
474
+ end
475
+ end
476
+
477
+ # Log to STDOUT by default
478
+ ResqueSqs.logger = MonoLogger.new(STDOUT)
479
+ ResqueSqs.logger.formatter = ResqueSqs::QuietFormatter.new
@@ -0,0 +1,161 @@
1
+ # Inspired by rabbitmq.rake the Redbox project at http://github.com/rick/redbox/tree/master
2
+ require 'fileutils'
3
+ require 'open-uri'
4
+ require 'pathname'
5
+
6
+ class RedisSqsRunner
7
+ def self.redis_dir
8
+ @redis_dir ||= if ENV['PREFIX']
9
+ Pathname.new(ENV['PREFIX'])
10
+ else
11
+ Pathname.new(`which redis-server`) + '..' + '..'
12
+ end
13
+ end
14
+
15
+ def self.bin_dir
16
+ redis_dir + 'bin'
17
+ end
18
+
19
+ def self.config
20
+ @config ||= if File.exists?(redis_dir + 'etc/redis.conf')
21
+ redis_dir + 'etc/redis.conf'
22
+ else
23
+ redis_dir + '../etc/redis.conf'
24
+ end
25
+ end
26
+
27
+ def self.dtach_socket
28
+ '/tmp/redis.dtach'
29
+ end
30
+
31
+ # Just check for existance of dtach socket
32
+ def self.running?
33
+ File.exists? dtach_socket
34
+ end
35
+
36
+ def self.start
37
+ puts 'Detach with Ctrl+\ Re-attach with rake redis_sqs:attach'
38
+ sleep 1
39
+ command = "#{bin_dir}/dtach -A #{dtach_socket} #{bin_dir}/redis-server #{config}"
40
+ sh command
41
+ end
42
+
43
+ def self.attach
44
+ exec "#{bin_dir}/dtach -a #{dtach_socket}"
45
+ end
46
+
47
+ def self.stop
48
+ sh 'echo "SHUTDOWN" | nc localhost 6379'
49
+ end
50
+ end
51
+
52
+ INSTALL_DIR = ENV['INSTALL_DIR'] || '/tmp/redis'
53
+
54
+ namespace :sqs_redis do
55
+ desc 'About redis'
56
+ task :about do
57
+ puts "\nSee http://code.google.com/p/redis/ for information about redis.\n\n"
58
+ end
59
+
60
+ desc 'Start redis'
61
+ task :start do
62
+ RedisSqsRunner.start
63
+ end
64
+
65
+ desc 'Stop redis'
66
+ task :stop do
67
+ RedisSqsRunner.stop
68
+ end
69
+
70
+ desc 'Restart redis'
71
+ task :restart do
72
+ RedisSqsRunner.stop
73
+ RedisSqsRunner.start
74
+ end
75
+
76
+ desc 'Attach to redis dtach socket'
77
+ task :attach do
78
+ RedisSqsRunner.attach
79
+ end
80
+
81
+ desc <<-DOC
82
+ Install the latest verison of Redis from Github (requires git, duh).
83
+ Use INSTALL_DIR env var like "rake redis_sqs:install INSTALL_DIR=~/tmp"
84
+ in order to get an alternate location for your install files.
85
+ DOC
86
+
87
+ task :install => [:about, :download, :make] do
88
+ bin_dir = '/usr/bin'
89
+ conf_dir = '/etc'
90
+
91
+ if ENV['PREFIX']
92
+ bin_dir = "#{ENV['PREFIX']}/bin"
93
+ sh "mkdir -p #{bin_dir}" unless File.exists?("#{bin_dir}")
94
+
95
+ conf_dir = "#{ENV['PREFIX']}/etc"
96
+ sh "mkdir -p #{conf_dir}" unless File.exists?("#{conf_dir}")
97
+ end
98
+
99
+ %w(redis-benchmark redis-cli redis-server).each do |bin|
100
+ sh "cp #{INSTALL_DIR}/src/#{bin} #{bin_dir}"
101
+ end
102
+
103
+ puts "Installed redis-benchmark, redis-cli and redis-server to #{bin_dir}"
104
+
105
+ unless File.exists?("#{conf_dir}/redis.conf")
106
+ sh "cp #{INSTALL_DIR}/redis.conf #{conf_dir}/redis.conf"
107
+ puts "Installed redis.conf to #{conf_dir} \n You should look at this file!"
108
+ end
109
+ end
110
+
111
+ task :make do
112
+ sh "cd #{INSTALL_DIR}/src && make clean"
113
+ sh "cd #{INSTALL_DIR}/src && make"
114
+ end
115
+
116
+ desc "Download package"
117
+ task :download do
118
+ sh "rm -rf #{INSTALL_DIR}/" if File.exists?("#{INSTALL_DIR}/.svn")
119
+ sh "git clone git://github.com/antirez/redis.git #{INSTALL_DIR}" unless File.exists?(INSTALL_DIR)
120
+ sh "cd #{INSTALL_DIR} && git pull" if File.exists?("#{INSTALL_DIR}/.git")
121
+ end
122
+ end
123
+
124
+ namespace :dtach_sqs do
125
+ desc 'About dtach'
126
+ task :about do
127
+ puts "\nSee http://dtach.sourceforge.net/ for information about dtach.\n\n"
128
+ end
129
+
130
+ desc 'Install dtach 0.8 from source'
131
+ task :install => [:about, :download, :make] do
132
+
133
+ bin_dir = "/usr/bin"
134
+
135
+
136
+ if ENV['PREFIX']
137
+ bin_dir = "#{ENV['PREFIX']}/bin"
138
+ sh "mkdir -p #{bin_dir}" unless File.exists?("#{bin_dir}")
139
+ end
140
+
141
+ sh "cp #{INSTALL_DIR}/dtach-0.8/dtach #{bin_dir}"
142
+ end
143
+
144
+ task :make do
145
+ sh "cd #{INSTALL_DIR}/dtach-0.8/ && ./configure && make"
146
+ end
147
+
148
+ desc "Download package"
149
+ task :download do
150
+ unless File.exists?("#{INSTALL_DIR}/dtach-0.8.tar.gz")
151
+ require 'net/http'
152
+
153
+ url = 'http://downloads.sourceforge.net/project/dtach/dtach/0.8/dtach-0.8.tar.gz'
154
+ open("#{INSTALL_DIR}/dtach-0.8.tar.gz", 'wb') do |file| file.write(open(url).read) end
155
+ end
156
+
157
+ unless File.directory?("#{INSTALL_DIR}/dtach-0.8")
158
+ sh "cd #{INSTALL_DIR} && tar xzf dtach-0.8.tar.gz"
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/../../lib'
2
+ require 'resque_sqs/tasks'
@@ -0,0 +1,27 @@
1
+
2
+ require 'test_helper'
3
+
4
+ begin
5
+ require 'airbrake'
6
+ rescue LoadError
7
+ warn "Install airbrake gem to run Airbrake tests."
8
+ end
9
+
10
+ if defined? Airbrake
11
+ require 'resque_sqs/failure/airbrake'
12
+ context "Airbrake" do
13
+ test "should be notified of an error" do
14
+ exception = StandardError.new("BOOM")
15
+ worker = ResqueSqs::Worker.new(:test)
16
+ queue = "test"
17
+ payload = {'class' => Object, 'args' => 66}
18
+
19
+ Airbrake.expects(:notify_or_ignore).with(
20
+ exception,
21
+ :parameters => {:payload_class => 'Object', :payload_args => '66'})
22
+
23
+ backend = ResqueSqs::Failure::Airbrake.new(exception, worker, queue, payload)
24
+ backend.save
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,15 @@
1
+ require 'test_helper'
2
+ require 'minitest/mock'
3
+
4
+ require 'resque_sqs/failure/base'
5
+
6
+ class TestFailure < ResqueSqs::Failure::Base
7
+ end
8
+
9
+ describe "Base failure class" do
10
+ it "allows calling all without throwing" do
11
+ with_failure_backend TestFailure do
12
+ assert_empty ResqueSqs::Failure.all
13
+ end
14
+ end
15
+ end