resque-delayed 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .rvmrc
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 1.0.0 (2011-09-07)
2
+
3
+ * initial release.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) Justin Giancola
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ # Resque::Delayed
2
+
3
+ Delayed job queueing for Resque.
4
+
5
+ Enqueue jobs that will only appear for processing after a specified delay or at a particular time in the future.
6
+
7
+ ## About
8
+
9
+ Useful for jobs that would be awkward to run in crons. For example:
10
+
11
+ * expiring stale orders to free up reserved inventory
12
+ * retrying failed webhook deliveries with progressively increasing delays
13
+
14
+ Also useful for jobs that are typically run in crons. For example:
15
+
16
+ * sending call-to-action reminder emails a few days after each signup
17
+ * checking whether pending payments have cleared
18
+
19
+ Fine-grained job scheduling avoids the need for monolithic crons that are often slow, resource intensive and single-process. Instead of needing to stagger crons to avoid overlap or parallelize crons that are too slow, jobs can be spread throughout the entire day and amongst multiple worker processes.
20
+
21
+ ## Usage
22
+
23
+ Resque::Delayed is very simple. Call `Resque.enqueue_in` or `Resque.enqueue_at` instead of `Resque.enqueue`
24
+ For example:
25
+
26
+ ```ruby
27
+ class User
28
+ after_create :send_call_to_action_email
29
+
30
+ private
31
+ def send_call_to_action_email
32
+ Resque.enqueue_in 3.days, CallToActionEmailJob, self.id
33
+ end
34
+ end
35
+ ```
36
+
37
+ **or**
38
+
39
+ ```ruby
40
+ class RecurringInvoice
41
+ def generate_invoice
42
+ # snip...
43
+
44
+ Resque.enqueue_at self.next_billing_date, RecurringInvoiceJob, self.id
45
+ end
46
+ end
47
+ ```
48
+
49
+ **or**
50
+
51
+ ```ruby
52
+ class Webhook
53
+ MAX_RETRIES = 15
54
+
55
+ def deliver
56
+ unless Webhook.post(payload).success?
57
+ return if retries == Webhook::MAX_RETRIES
58
+
59
+ update_attribute :retries, retries + 1
60
+
61
+ Resque.enqueue_in (2**retries).minutes, WebhookDeliveryJob, self.id
62
+ end
63
+ end
64
+ end
65
+ ```
66
+
67
+ ## Setup
68
+
69
+ `$ gem install resque-delayed`
70
+
71
+ or add
72
+
73
+ `gem 'resque-delayed'`
74
+
75
+ to your Gemfile and run
76
+
77
+ `$ bundle install`
78
+
79
+ Resque::Delayed piggybacks on your existing Resque setup so it will use whatever Redis instance Resque has been configured to use.
80
+
81
+ The above will provide `Resque.enqueue_in` and `Resque.enqueue_at` to your application but you will also need to run a Resque::Dealyed worker process. The worker is responsible for harvesting future-queued jobs and pushing them onto the appropriate Resque queues at the right time.
82
+
83
+ `Resque::Delayed::Worker` is a stripped-down version of `Resque::Worker` so you can use the same configuration options like `INTERVAL`, `PIDFILE`, `LOGGING`, `VERBOSE` and `VVERBOSE`
84
+
85
+ Like Resque, Resque::Delayed provides a rake task to run workers. Add `require 'resque-delayed/tasks'` to your `Rakefile` and run
86
+
87
+ $ cd app_root
88
+ $ LOGGING=1 INTERVAL=10 rake resque_delayed:work
89
+
90
+ **NOTE: Resque::Delayed workers only take future-queued jobs and push them onto Resque queues when they need to be run. They do *not* actually process jobs so any setup using Resque::Delayed also needs one or more regular Resque workers.**
91
+
92
+ ## Deployment Considerations
93
+
94
+ Resque::Delayed workers are very lean as they do not need to load either your application or your Resque job classes. Even so you will probably want to monitor them in production using something like monit, god, or bluepill. Also, because they are not actually performing any of the job processing work it is unlikely you will need to run more than one.<sup>1</sup>
95
+
96
+ <sup>1</sup> a single Resque::Delayed worker on a laptop with unexciting hardware can push a few thousand jobs per second into Resque while new delayed jobs are simultaneously being added.
97
+
98
+ ## Contributing
99
+
100
+ 1. [fork](http://help.github.com/fork-a-repo/) this repo
101
+ 1. create a topic branch (`$ git checkout -b my_branch`)
102
+ 1. make your changes along with specs
103
+ 1. push to your branch (`$ git push origin my_branch`)
104
+ 1. send me a [pull request](http://help.github.com/send-pull-requests/)
105
+
106
+ ## Thanks
107
+
108
+ Thanks to [defunkt](https://github.com/defunkt) and all Resque contributors. Resque is a pleasure to use and adapts well to new challenges. Also some code in this project, `Resque::Delayed::Worker` in particular, borrows heavily from the Resque implementation.
109
+
110
+ ## Copyright
111
+
112
+ Copyright (c) Justin Giancola. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env rake
2
+
3
+ $:.unshift File.dirname(__FILE__)
4
+ require "bundler/gem_tasks"
5
+ require "lib/resque-delayed/tasks"
@@ -0,0 +1,6 @@
1
+ require 'resque'
2
+ require 'uuidtools'
3
+
4
+ %w(resque-delayed resque worker).each do |component|
5
+ require File.join(File.dirname(__FILE__), 'resque-delayed', component)
6
+ end
@@ -0,0 +1,69 @@
1
+ module Resque
2
+ module Delayed
3
+ class << self
4
+ @queue = "Resque::Delayed:internal"
5
+
6
+ def random_uuid
7
+ UUIDTools::UUID.random_create.to_s.gsub('-', '')
8
+ end
9
+
10
+ def clear
11
+ Resque.redis.del @queue
12
+ end
13
+
14
+ def count
15
+ Resque.redis.zcard @queue
16
+ end
17
+
18
+ def create_at(time, *args)
19
+ klass, *args = args
20
+ queue = Resque.queue_from_class klass
21
+ # validate here so that the Resque::Delayed worker doesn't have
22
+ # to worry about it before enqueueing
23
+ Resque.validate(klass, queue)
24
+ Resque.redis.zadd @queue, time.to_i, encode(queue, klass, *args)
25
+ end
26
+
27
+ def create_in(offset, *args)
28
+ create_at Time.now + offset, *args
29
+ end
30
+
31
+ def encode(queue, klass, *args)
32
+ "#{random_uuid}|#{Resque.encode([queue, klass.to_s, *args])}"
33
+ end
34
+
35
+ def decode(encoded_job)
36
+ Resque.decode encoded_job.split('|', 2).last
37
+ end
38
+
39
+ def next
40
+ next_at Time.now
41
+ end
42
+
43
+ def next_at(time)
44
+ job = peek_at_serialized(time)
45
+
46
+ # it is possible that another process will pull this job out of the
47
+ # queue before this process has a chance. if that happens, return nil
48
+ # so that we don't end up duplicating the job.
49
+ return unless job and Resque.redis.zrem(@queue, job)
50
+
51
+ Resque::Delayed.decode job
52
+ end
53
+
54
+ def peek
55
+ peek_at Time.now
56
+ end
57
+
58
+ def peek_at(time)
59
+ job = peek_at_serialized(time)
60
+ job and Resque::Delayed.decode(job)
61
+ end
62
+
63
+ def peek_at_serialized(time)
64
+ Resque.redis.
65
+ zrangebyscore(@queue, '-inf', time.to_i, :limit => [0, 1]).first
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ module Resque
2
+ class << self
3
+ def enqueue_at(time, *args)
4
+ Resque::Delayed.create_at time, *args
5
+ end
6
+
7
+ def enqueue_in(offset, *args)
8
+ Resque::Delayed.create_in offset, *args
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,22 @@
1
+ # require 'resque-delayed/tasks'
2
+ namespace :resque_delayed do
3
+
4
+ desc "Start a Resque::Delayed worker"
5
+ task :work do
6
+ require 'resque-delayed'
7
+
8
+ begin
9
+ worker = Resque::Delayed::Worker.new
10
+ worker.verbose = ENV['LOGGING'] || ENV['VERBOSE']
11
+ worker.very_verbose = ENV['VVERBOSE']
12
+ end
13
+
14
+ if ENV['PIDFILE']
15
+ File.open(ENV['PIDFILE'], 'w') { |f| f << worker.pid }
16
+ end
17
+
18
+ worker.log "Starting Resque::Delayed worker #{worker}"
19
+
20
+ worker.work(ENV['INTERVAL'] || 5) # interval, will block
21
+ end
22
+ end
@@ -0,0 +1,5 @@
1
+ module Resque
2
+ module Delayed
3
+ VERSION = "1.0.0"
4
+ end
5
+ end
@@ -0,0 +1,120 @@
1
+ module Resque::Delayed
2
+ # a worker that harvests delayed jobs and queues them
3
+ #
4
+ # note: this is a modified version of
5
+ # https://github.com/defunkt/resque/blob/e01bece0ccfd561909333d51b28813d59777183d/lib/resque/worker.rb
6
+ # with nearly everything stripped out of it
7
+ class Worker
8
+ # Whether the worker should log basic info to STDOUT
9
+ attr_accessor :verbose
10
+
11
+ # Whether the worker should log lots of info to STDOUT
12
+ attr_accessor :very_verbose
13
+
14
+ attr_writer :to_s
15
+
16
+ # Can be passed a float representing the polling frequency.
17
+ # The default is 5 seconds, but for a semi-active site you may
18
+ # want to use a smaller value.
19
+ def work(interval = 5.0)
20
+ interval = Float(interval)
21
+ $0 = "resque-delayed: harvesting"
22
+ startup
23
+
24
+ loop do
25
+ break if shutdown?
26
+
27
+ # harvest delayed jobs while they are available
28
+ while job = Resque::Delayed.next do
29
+ log "got: #{job.inspect}"
30
+ queue, klass, *args = job
31
+ Resque::Job.create(queue, klass, *args)
32
+ end
33
+
34
+ break if interval.zero?
35
+ log! "Sleeping for #{interval} seconds"
36
+ sleep interval
37
+ end
38
+ end
39
+
40
+ # Runs all the methods needed when a worker begins its lifecycle.
41
+ def startup
42
+ register_signal_handlers
43
+
44
+ # Fix buffering so we can `rake resque-delayed:work > resque-delayed.log` and
45
+ # get output from the worker
46
+ $stdout.sync = true
47
+ end
48
+
49
+ # Registers the various signal handlers a worker responds to.
50
+ #
51
+ # TERM: Shutdown immediately, stop processing jobs.
52
+ # INT: Shutdown immediately, stop processing jobs.
53
+ # QUIT: Shutdown after the current job has finished processing.
54
+ def register_signal_handlers
55
+ trap('TERM') { shutdown! }
56
+ trap('INT') { shutdown! }
57
+
58
+ begin
59
+ trap('QUIT') { shutdown }
60
+ rescue ArgumentError
61
+ warn "Signals TERM and/or QUIT not supported."
62
+ end
63
+
64
+ log! "Registered signals"
65
+ end
66
+
67
+ # Schedule this worker for shutdown. Will finish processing the
68
+ # current job.
69
+ def shutdown
70
+ log 'Exiting...'
71
+ @shutdown = true
72
+ end
73
+
74
+ # Kill the child and shutdown immediately.
75
+ def shutdown!
76
+ shutdown
77
+ end
78
+
79
+ # Should this worker shutdown as soon as current job is finished?
80
+ def shutdown?
81
+ @shutdown
82
+ end
83
+
84
+ def inspect
85
+ "#<Resque::Delayed worker #{to_s}>"
86
+ end
87
+
88
+ # The string representation is the same as the id for this worker
89
+ # instance. Can be used with `Worker.find`.
90
+ def to_s
91
+ @to_s ||= "#{hostname}:#{Process.pid}:resque-delayed"
92
+ end
93
+ alias_method :id, :to_s
94
+
95
+ # chomp'd hostname of this machine
96
+ def hostname
97
+ @hostname ||= `hostname`.chomp
98
+ end
99
+
100
+ # Returns Integer PID of running worker
101
+ def pid
102
+ @pid ||= Process.pid
103
+ end
104
+
105
+ # Log a message to STDOUT if we are verbose or very_verbose.
106
+ def log(message)
107
+ if verbose
108
+ puts "*** #{message}"
109
+ elsif very_verbose
110
+ time = Time.now.strftime('%H:%M:%S %Y-%m-%d')
111
+ puts "** [#{time}] #$$: #{message}"
112
+ end
113
+ end
114
+
115
+ # Logs a very verbose message to STDOUT.
116
+ def log!(message)
117
+ log message if very_verbose
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path('../lib/resque-delayed/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.authors = ["Justin Giancola"]
5
+ gem.email = ["justin.giancola@gmail.com"]
6
+ gem.summary = %q{Delayed job queueing for Resque}
7
+ gem.description = %q{Enqueue jobs that will only appear for processing after a specified delay or at a particular time in the future}
8
+ gem.homepage = "https://github.com/elucid/resque-delayed"
9
+
10
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
11
+ gem.files = `git ls-files`.split("\n")
12
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
13
+ gem.name = "resque-delayed"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = Resque::Delayed::VERSION
16
+
17
+ gem.add_development_dependency "bundler", [">= 1.0.2", "< 1.2.0"]
18
+ gem.add_development_dependency "rspec", "~> 2.6.0"
19
+ gem.add_development_dependency "rake", [">= 0.8.7", "< 1.0"]
20
+
21
+ gem.add_dependency "redis", "~> 2.2.0"
22
+ gem.add_dependency "resque", [">= 1.18.0", "< 1.20.0"]
23
+ gem.add_dependency "uuidtools", "~> 2.1.2"
24
+ end
@@ -0,0 +1,8 @@
1
+ daemonize yes
2
+ pidfile ./spec/redis-test.pid
3
+ port 9736
4
+ timeout 10
5
+ loglevel warning
6
+ logfile /dev/null
7
+ databases 1
8
+ glueoutputbuf yes
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque::Delayed do
4
+ describe 'simple create' do
5
+ before :each do
6
+ Resque::Delayed.clear
7
+ end
8
+
9
+ it "should start with zero delayed jobs queued" do
10
+ Resque::Delayed.count.should be_zero
11
+ end
12
+
13
+ it "should allow queueing at a specified time" do
14
+ Resque::Delayed.create_at(Time.now + 1.day, SomeJob, 'foo', 'bar', 1234)
15
+ Resque::Delayed.count.should == 1
16
+ end
17
+
18
+ it "should allow queuing after a specified delay" do
19
+ Resque::Delayed.create_in(1.day, SomeJob, 'foo', 'bar', 1234)
20
+ Resque::Delayed.count.should == 1
21
+ end
22
+ end
23
+
24
+ describe :availability do
25
+ before :each do
26
+ Resque::Delayed.clear
27
+ @one_day_from_now = Time.now + 1.day
28
+ Resque::Delayed.create_at(@one_day_from_now, SomeJob, 'foo', 'bar', 1234)
29
+ end
30
+
31
+ it "should not make items available before create time" do
32
+ Resque::Delayed.next.should be_nil
33
+ Resque::Delayed.next_at(Time.now).should be_nil
34
+ end
35
+
36
+ it "should make items available at create time" do
37
+ Resque::Delayed.next_at(@one_day_from_now).should_not be_nil
38
+ end
39
+
40
+ it "should make items available after create time" do
41
+ Resque::Delayed.next_at(@one_day_from_now + 1.minute).should_not be_nil
42
+ end
43
+ end
44
+
45
+ describe :dequeueing do
46
+ before do
47
+ Resque::Delayed.clear
48
+ @one_hour_ago = Time.now - 1.hour
49
+ Resque::Delayed.create_at(@one_hour_ago, SomeJob, 'foo', 'bar', 1234)
50
+ end
51
+
52
+ it "should deserialize properly" do
53
+ job = Resque::Delayed.next
54
+ job.should == ["jobs", "SomeJob", "foo", "bar", 1234]
55
+ Resque::Delayed.count.should be_zero
56
+ end
57
+ end
58
+
59
+ describe :updates do
60
+ before :each do
61
+ Resque::Delayed.clear
62
+ @one_hour_ago = Time.now - 1.hour
63
+ Resque::Delayed.create_at(@one_hour_ago, SomeJob, 'first')
64
+ Resque::Delayed.create_at(@one_hour_ago + 2.minutes, SomeJob, 'third')
65
+ Resque::Delayed.create_at(@one_hour_ago + 1.minute, SomeJob, 'second')
66
+ end
67
+
68
+ it "should be setup properly" do
69
+ Resque::Delayed.peek.should == ["jobs", "SomeJob", "first"]
70
+ Resque::Delayed.count.should == 3
71
+ end
72
+
73
+ it "should dequeue in the correct order regardless of instert order" do
74
+ %w(first second third).each do |arg|
75
+ Resque::Delayed.next.last.should == arg
76
+ end
77
+ end
78
+
79
+ it "should allow queueing multiple instances of the same job" do
80
+ Resque::Delayed.create_at(@one_hour_ago + 3.minutes, SomeJob, 'first')
81
+ Resque::Delayed.count.should == 4
82
+ end
83
+
84
+ it "should not alter position of existing jobs on second instance queue" do
85
+ Resque::Delayed.create_at(@one_hour_ago + 3.minutes, SomeJob, 'first')
86
+ Resque::Delayed.peek.should == ["jobs", "SomeJob", "first"]
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque do
4
+ describe 'simple create' do
5
+ before :each do
6
+ Resque::Delayed.clear
7
+ end
8
+
9
+ it "should start with zero delayed jobs queued" do
10
+ Resque::Delayed.count.should be_zero
11
+ end
12
+
13
+ it "should allow queueing at a specified time" do
14
+ Resque.enqueue_at(Time.now + 1.day, SomeJob, 'foo', 'bar', 1234)
15
+ Resque::Delayed.count.should == 1
16
+ end
17
+
18
+ it "should allow queuing after a specified delay" do
19
+ Resque.enqueue_in(1.day, SomeJob, 'foo', 'bar', 1234)
20
+ Resque::Delayed.count.should == 1
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ # based on https://github.com/defunkt/resque/blob/e01bece0ccfd561909333d51b28813d59777183d/test/test_helper.rb
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.setup
6
+ Bundler.require
7
+
8
+ # this is necessary because of
9
+ # https://github.com/carlhuda/bundler/issues/1096
10
+ require 'resque'
11
+
12
+ # make sure we can run redis
13
+ if !system("which redis-server")
14
+ puts '', "** can't find `redis-server` in your path"
15
+ abort ''
16
+ end
17
+
18
+ dir = File.dirname(File.expand_path(__FILE__))
19
+
20
+ # start our own redis when the tests start,
21
+ # kill it when they end
22
+ at_exit do
23
+ pid = File.read("#{dir}/redis-test.pid").chomp
24
+ puts "Killing test redis server..."
25
+ Process.kill("KILL", pid.to_i)
26
+ File.unlink "#{dir}/redis-test.pid"
27
+ end
28
+
29
+ puts "Starting redis for testing at localhost:9736..."
30
+ `redis-server #{dir}/redis-test.conf`
31
+ Resque.redis = 'localhost:9736'
32
+
33
+ require "#{dir}/support/extensions.rb"
34
+
35
+ class SomeJob
36
+ @queue = :jobs
37
+ end
38
+
39
+ class SomeOtherJob
40
+ @queue = :other_jobs
41
+ end
@@ -0,0 +1,21 @@
1
+ class Fixnum
2
+ def seconds
3
+ to_i
4
+ end
5
+ alias :second :seconds
6
+
7
+ def minutes
8
+ seconds * 60
9
+ end
10
+ alias :minute :minutes
11
+
12
+ def hours
13
+ minutes * 60
14
+ end
15
+ alias :hour :hours
16
+
17
+ def days
18
+ hours * 24
19
+ end
20
+ alias :day :days
21
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque::Delayed::Worker do
4
+ describe "harvest timing" do
5
+ before :each do
6
+ Resque::Delayed.clear
7
+ @worker = Resque::Delayed::Worker.new
8
+ end
9
+
10
+ after :each do
11
+ @worker.shutdown!
12
+ end
13
+
14
+ it "should not harvest future jobs" do
15
+ Resque.enqueue_in(1.hour, SomeJob, 'future')
16
+ @worker.work(0)
17
+ Resque::Delayed.count.should == 1
18
+ end
19
+
20
+ it "should harvest past jobs" do
21
+ Resque.enqueue_at(Time.now - 1.hour, SomeJob, 'past')
22
+ @worker.work(0)
23
+ Resque::Delayed.count.should == 0
24
+ end
25
+ end
26
+
27
+ describe "Resque interface" do
28
+ before do
29
+ Resque::Delayed.clear
30
+ @worker = Resque::Delayed::Worker.new
31
+ Resque.enqueue_at(Time.now - 1.hour, SomeJob, 'past')
32
+ Resque.enqueue_at(Time.now - 1.hour, SomeOtherJob, 'past')
33
+ end
34
+
35
+ after do
36
+ @worker.shutdown!
37
+ end
38
+
39
+ it "should queue delayed jobs in appropriate Resque queues after harvest" do
40
+ Resque::Job.should_receive(:create).with('jobs', 'SomeJob', 'past')
41
+ Resque::Job.should_receive(:create).with('other_jobs', 'SomeOtherJob', 'past')
42
+ @worker.work(0)
43
+ end
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-delayed
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 1.0.0
6
+ platform: ruby
7
+ authors:
8
+ - Justin Giancola
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-09-07 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.2
23
+ - - <
24
+ - !ruby/object:Gem::Version
25
+ version: 1.2.0
26
+ type: :development
27
+ prerelease: false
28
+ version_requirements: *id001
29
+ - !ruby/object:Gem::Dependency
30
+ name: rspec
31
+ requirement: &id002 !ruby/object:Gem::Requirement
32
+ none: false
33
+ requirements:
34
+ - - ~>
35
+ - !ruby/object:Gem::Version
36
+ version: 2.6.0
37
+ type: :development
38
+ prerelease: false
39
+ version_requirements: *id002
40
+ - !ruby/object:Gem::Dependency
41
+ name: rake
42
+ requirement: &id003 !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.7
48
+ - - <
49
+ - !ruby/object:Gem::Version
50
+ version: "1.0"
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: *id003
54
+ - !ruby/object:Gem::Dependency
55
+ name: redis
56
+ requirement: &id004 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: *id004
65
+ - !ruby/object:Gem::Dependency
66
+ name: resque
67
+ requirement: &id005 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: 1.18.0
73
+ - - <
74
+ - !ruby/object:Gem::Version
75
+ version: 1.20.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: *id005
79
+ - !ruby/object:Gem::Dependency
80
+ name: uuidtools
81
+ requirement: &id006 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: 2.1.2
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: *id006
90
+ description: Enqueue jobs that will only appear for processing after a specified delay or at a particular time in the future
91
+ email:
92
+ - justin.giancola@gmail.com
93
+ executables: []
94
+
95
+ extensions: []
96
+
97
+ extra_rdoc_files: []
98
+
99
+ files:
100
+ - .gitignore
101
+ - CHANGELOG.md
102
+ - Gemfile
103
+ - LICENSE
104
+ - README.md
105
+ - Rakefile
106
+ - lib/resque-delayed.rb
107
+ - lib/resque-delayed/resque-delayed.rb
108
+ - lib/resque-delayed/resque.rb
109
+ - lib/resque-delayed/tasks.rb
110
+ - lib/resque-delayed/version.rb
111
+ - lib/resque-delayed/worker.rb
112
+ - resque-delayed.gemspec
113
+ - spec/redis-test.conf
114
+ - spec/resque_delayed_spec.rb
115
+ - spec/resque_spec.rb
116
+ - spec/spec_helper.rb
117
+ - spec/support/extensions.rb
118
+ - spec/worker_spec.rb
119
+ homepage: https://github.com/elucid/resque-delayed
120
+ licenses: []
121
+
122
+ post_install_message:
123
+ rdoc_options: []
124
+
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ">="
131
+ - !ruby/object:Gem::Version
132
+ hash: -4057691847375928239
133
+ segments:
134
+ - 0
135
+ version: "0"
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ hash: -4057691847375928239
142
+ segments:
143
+ - 0
144
+ version: "0"
145
+ requirements: []
146
+
147
+ rubyforge_project:
148
+ rubygems_version: 1.8.8
149
+ signing_key:
150
+ specification_version: 3
151
+ summary: Delayed job queueing for Resque
152
+ test_files:
153
+ - spec/redis-test.conf
154
+ - spec/resque_delayed_spec.rb
155
+ - spec/resque_spec.rb
156
+ - spec/spec_helper.rb
157
+ - spec/support/extensions.rb
158
+ - spec/worker_spec.rb