scheduled_job 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.ruby-version +1 -0
- data/.travis.yml +4 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +149 -0
- data/Rakefile +6 -0
- data/lib/scheduled_job.rb +91 -0
- data/lib/scheduled_job/version.rb +3 -0
- data/pry.rb +6 -0
- data/scheduled_job.gemspec +29 -0
- data/scheduled_job.rconf +9 -0
- data/spec/lib/scheduled_job_spec.rb +137 -0
- data/spec/spec_helper.rb +16 -0
- metadata +168 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4e5e1e7a35d0f3d68c2428b653941ccef7161544
|
4
|
+
data.tar.gz: cc91a8c1b338f203665d2c9e4022fcdf421bb761
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bc188dc562bc3871f5bb1da987c834c7e040ef57a57532b1e129f442a1d65b6a46ffe54f0abe4897e92a3d4b1d2ea3299a752a7e1e77ed8406ee8b4dc00aeb2e
|
7
|
+
data.tar.gz: 613e68e70fd21d1d05b27ef8154deea6322bc4d7c60da50452bb793a1dbaada71305b5f35223840de2abf2271ef4f168834c2eb9d41e212721c116d177baa296
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.1
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 RightScale
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
# ScheduledJob
|
2
|
+
|
3
|
+
Scheduled job looks to build on top of the [delayed_job](https://github.com/collectiveidea/delayed_job) project by adding support for jobs that need to recur. Whilst investigating other options we decided that we wanted a very light weight framework that would simply allow us to define worker tasks that need to happen on a regular basis.
|
4
|
+
|
5
|
+
In order to achieve this we created the following interface which allows the developer to consisly define what the job is to do as well as when it is to run. This helps keep all the logic in one place which is a huge plus.
|
6
|
+
|
7
|
+
In terms of implementation there are only a couple of things we need to do.
|
8
|
+
|
9
|
+
Firstly if there are any before or success callbacks you need to define you can do this via the configure block. This passes the instance of DelayedJob that run your job as well as the job itself.
|
10
|
+
|
11
|
+
We can also take this opportunity to set up any logging. By default we use the ruby logger but if you are using rails for example you can do something like the following:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
ScheduledJob.configure do |config|
|
15
|
+
config.before_callback = -> (job, scheduled_job) do
|
16
|
+
JobRunLogger.update_attributes!(job_name: scheduled_job.class.name, started_at: Time.now.utc)
|
17
|
+
end
|
18
|
+
|
19
|
+
config.success_callback = -> (job, _) do
|
20
|
+
ScheduledJob.logger.info("Hurrah my job #{job.id} has completed")
|
21
|
+
end
|
22
|
+
|
23
|
+
config.logger = Rails.logger
|
24
|
+
end
|
25
|
+
```
|
26
|
+
|
27
|
+
With this in place we can go on to define a job that we want to run regularly. To do this just mix in the scheduled job module in your class, define a perform method and define a time to recur.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class WeeklyMetricJob
|
31
|
+
include ::ScheduledJob
|
32
|
+
|
33
|
+
def perform
|
34
|
+
ScheduledJob.logger.info('I need to do something over and over')
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.time_to_recur(last_run_at)
|
38
|
+
last_run_at.end_of_week + 3.hours
|
39
|
+
end
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
This allows you so specify what logic you need to run along side how often it needs to run. The time to recur is passed the completion time of the last successful run so you can use whatever logic you like in here to define when the job needs to run again.
|
44
|
+
|
45
|
+
Finally you need to kick off the job the first time. Once it has run successfully it will look after itself but to start the cycle you need to run schedule_job on your job. Continuing on the example above:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
WeeklyMetricJob.schedule_job
|
49
|
+
```
|
50
|
+
|
51
|
+
Note currently this implementation is dependant upon using the [delayed_job_active_record](https://github.com/collectiveidea/delayed_job_active_record) backend. This is something that we may be looking to remove in future.
|
52
|
+
|
53
|
+
## Running the specs
|
54
|
+
|
55
|
+
This is the default rake task so you can run the specs in any of the following ways:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
bundle exec rake
|
59
|
+
bundle exec rake spec
|
60
|
+
bundle exec rspec
|
61
|
+
```
|
62
|
+
|
63
|
+
## Getting a console
|
64
|
+
|
65
|
+
The project is currently using pry. In order to get a console in the context of the project just run the pry.rb file in ruby.
|
66
|
+
|
67
|
+
```bash
|
68
|
+
bundle exec ruby pry.rb
|
69
|
+
```
|
70
|
+
|
71
|
+
## Installation
|
72
|
+
|
73
|
+
Add this line to your application's Gemfile:
|
74
|
+
|
75
|
+
gem 'scheduled_job'
|
76
|
+
|
77
|
+
And then execute:
|
78
|
+
|
79
|
+
$ bundle
|
80
|
+
|
81
|
+
Or install it yourself as:
|
82
|
+
|
83
|
+
$ gem install scheduled_job
|
84
|
+
|
85
|
+
## Usage
|
86
|
+
|
87
|
+
First you must include the scheduled job module in any DelayedJob that needs to run on a regular basis.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
include ::ScheduledJob
|
91
|
+
```
|
92
|
+
|
93
|
+
Then you need to say what the job is acutally to do. This is done by implementing the permform method.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
def perform
|
97
|
+
puts 'I do work!'
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
Finaly we need to write the logic for when we want the job to run. This is done by implementing the time_to_recur method which is passed the time the job last completed as its parameter.
|
102
|
+
|
103
|
+
```ruby
|
104
|
+
def self.time_to_recur(last_run_at)
|
105
|
+
last_run_at + 3.hours
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
There are also callbacks that are available using ScheduledJob. These allow you to hook into the scheduling life cycle. Also note that as this uses DelayedJob under the hood all of the delayed job callbacks are still available for use.
|
110
|
+
|
111
|
+
These can be defined when configuring the gem for you application on the configure block:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
ScheduledJob.configure do |config|
|
115
|
+
# configuration code in here
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
The before_callback is executed before the perform method is called on the scheduled job. This is passed the delayed job object and the scheduled job instance.
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
config.before_callback = -> (job, scheduled_job) do
|
123
|
+
JobRunLogger.update_attributes!(job_name: scheduled_job.class.name, started_at: Time.now.utc)
|
124
|
+
end
|
125
|
+
```
|
126
|
+
|
127
|
+
The success_callback is called on sucessful completion of the job and is also passed the delayed job object and the scheduled job instance.
|
128
|
+
|
129
|
+
```ruby
|
130
|
+
config.success_callback = -> (job, _) do
|
131
|
+
ScheduledJob.logger.info("Hurrah my job #{job.id} has completed")
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
Then there is the fast mode. This is checked prior to scheduling another run of your job e.g. after a job has completed. This allows you to override the scheduling logic and ask the job to run immediatly. This is passed the scheduled job class. This means you can have state stored elsewhere to change the scheduling without having to modify the code. This could be getting an array from a database for example:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
config.fast_mode = -> (job) do
|
139
|
+
Database.get_value('fast_mode_jobs').include?(job.name)
|
140
|
+
end
|
141
|
+
```
|
142
|
+
|
143
|
+
## Contributing
|
144
|
+
|
145
|
+
1. Fork it ( http://github.com/rightscale/scheduled_job/fork )
|
146
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
147
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
148
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
149
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require "scheduled_job/version"
|
2
|
+
require 'logger'
|
3
|
+
require 'delayed_job'
|
4
|
+
require 'delayed_job_active_record'
|
5
|
+
|
6
|
+
module ScheduledJob
|
7
|
+
class << self
|
8
|
+
attr_accessor :config
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.logger
|
12
|
+
self.config.logger
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure
|
16
|
+
self.config ||= Config.new
|
17
|
+
yield(config)
|
18
|
+
end
|
19
|
+
|
20
|
+
class Config
|
21
|
+
attr_accessor :logger, :before_callback, :success_callback, :fast_mode
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
@logger = Logger.new(STDOUT)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.extend ScheduledJobClassMethods
|
30
|
+
end
|
31
|
+
|
32
|
+
def before(job)
|
33
|
+
callback = ScheduledJob.config.before_callback
|
34
|
+
callback.call(job, self) if callback
|
35
|
+
end
|
36
|
+
|
37
|
+
def success(job)
|
38
|
+
callback = ScheduledJob.config.success_callback
|
39
|
+
callback.call(job, self) if callback
|
40
|
+
GC.start
|
41
|
+
self.class.schedule_job(job)
|
42
|
+
end
|
43
|
+
|
44
|
+
def failure(job)
|
45
|
+
ScheduledJob.logger.error("DelayedJob failed: processing job in queue #{self.class.queue_name} failed")
|
46
|
+
job.update_attributes!(:failed_at => Time.now)
|
47
|
+
self.class.schedule_job
|
48
|
+
end
|
49
|
+
|
50
|
+
def error(job, exception)
|
51
|
+
ScheduledJob.logger.warn("DelayedJob error: Job: #{job.id}, in queue #{self.class.queue_name}, exception: #{exception}")
|
52
|
+
self.class.schedule_job
|
53
|
+
end
|
54
|
+
|
55
|
+
module ScheduledJobClassMethods
|
56
|
+
# This method should be called when scheduling a recurring job as it checks to ensure no
|
57
|
+
# other instances of the job are already running.
|
58
|
+
def schedule_job(job = nil)
|
59
|
+
unless job_exists?(job)
|
60
|
+
callback = ScheduledJob.config.fast_mode
|
61
|
+
in_fast_mode = callback ? callback.call(self) : false
|
62
|
+
|
63
|
+
run_at = in_fast_mode ? Time.now.utc : time_to_recur(Time.now.utc)
|
64
|
+
|
65
|
+
Delayed::Job.enqueue(new, :run_at => run_at, :queue => queue_name)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def queue_name
|
70
|
+
"Default"
|
71
|
+
end
|
72
|
+
|
73
|
+
def random_minutes(base, random_delta)
|
74
|
+
random_delta *= -1 if random_delta < 0
|
75
|
+
(base + Random.new.rand((-1 * random_delta)..random_delta)).minutes
|
76
|
+
end
|
77
|
+
|
78
|
+
def job_exists?(job = nil)
|
79
|
+
conditions = ['handler like ? AND failed_at IS NULL', "%#{self.name}%"]
|
80
|
+
unless job.blank?
|
81
|
+
conditions[0] << " AND id != ?"
|
82
|
+
conditions << job.id
|
83
|
+
end
|
84
|
+
Delayed::Job.exists?(conditions)
|
85
|
+
end
|
86
|
+
|
87
|
+
def run_duration_threshold
|
88
|
+
self.const_defined?(:RUN_DURATION_THRESHOLD) ? self::RUN_DURATION_THRESHOLD : nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/pry.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'scheduled_job/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "scheduled_job"
|
8
|
+
spec.version = ScheduledJob::VERSION
|
9
|
+
spec.authors = ["CallumD", "aliscott", "smcgivern", "alikhajeh1"]
|
10
|
+
spec.email = ["callum.dryden@rightscale.com", "alistair@rightscale.com", "sean.mcgivern@rightscale.com", "ali@rightscale.com"]
|
11
|
+
spec.summary = %q{Adding support for jobs that need to reccur}
|
12
|
+
spec.description = %q{By including the scheduled job module in a delayed job you can specify when you would like the job to run again. Currently this is intented to be used with the active record back end this may change in future.}
|
13
|
+
spec.homepage = "https://github.com/rightscale/scheduled_job"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "delayed_job", "3.0.5"
|
22
|
+
spec.add_runtime_dependency "delayed_job_active_record", "0.4.4"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
25
|
+
spec.add_development_dependency "rake", "~> 0.9"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
spec.add_development_dependency "pry"
|
28
|
+
spec.add_development_dependency "simplecov"
|
29
|
+
end
|
data/scheduled_job.rconf
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
class UnderTest
|
5
|
+
include ScheduledJob
|
6
|
+
|
7
|
+
def self.queue_name
|
8
|
+
"TESTING"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.time_to_recur(last_run_time)
|
12
|
+
"time to recur"
|
13
|
+
end
|
14
|
+
|
15
|
+
def perform
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ScheduledJob do
|
20
|
+
|
21
|
+
let(:under_test) { UnderTest.new }
|
22
|
+
|
23
|
+
describe 'fast mode' do
|
24
|
+
before { expect(Delayed::Job).to receive(:exists?).and_return(false) }
|
25
|
+
|
26
|
+
context 'when the job is not in run fast mode' do
|
27
|
+
it 'uses the value from time to recur' do
|
28
|
+
Delayed::Job.should_receive(:enqueue).with(anything, {
|
29
|
+
:run_at => UnderTest.time_to_recur(nil),
|
30
|
+
:queue => UnderTest.queue_name
|
31
|
+
})
|
32
|
+
UnderTest.schedule_job
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when the job is in run fast mode' do
|
37
|
+
before do
|
38
|
+
ScheduledJob.configure do |config|
|
39
|
+
config.fast_mode = -> (_) do
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
it 'uses the current time' do
|
45
|
+
time = Time.now.utc
|
46
|
+
Time.stub_chain(:now, :utc) { time }
|
47
|
+
|
48
|
+
Delayed::Job.should_receive(:enqueue).with(anything, {
|
49
|
+
:run_at => time,
|
50
|
+
:queue => UnderTest.queue_name
|
51
|
+
})
|
52
|
+
UnderTest.schedule_job
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "implements the required interface" do
|
58
|
+
expect(UnderTest).to respond_to :queue_name
|
59
|
+
expect(under_test).to respond_to :perform
|
60
|
+
expect(UnderTest).to respond_to :time_to_recur
|
61
|
+
expect(UnderTest).to respond_to :random_minutes
|
62
|
+
end
|
63
|
+
|
64
|
+
it "adds success to the class" do
|
65
|
+
expect(under_test).to respond_to :success
|
66
|
+
end
|
67
|
+
|
68
|
+
it "schedules a new job on success" do
|
69
|
+
expect(UnderTest).to receive(:schedule_job)
|
70
|
+
Delayed::Job.stub(:enqueue)
|
71
|
+
underTestJob = double("UnderTestJob");
|
72
|
+
underTestJob.stub(:run_at) { DateTime.now.utc }
|
73
|
+
underTestJob.stub(:id) { 1 }
|
74
|
+
under_test.before underTestJob
|
75
|
+
under_test.success underTestJob
|
76
|
+
end
|
77
|
+
|
78
|
+
it "adds failure to the class" do
|
79
|
+
expect(under_test).to respond_to :failure
|
80
|
+
end
|
81
|
+
|
82
|
+
it "logs the error and schedules a job on failure" do
|
83
|
+
dummy_job = double("job")
|
84
|
+
dummy_job.stub(:id)
|
85
|
+
expect(dummy_job).to receive(:update_attributes!)
|
86
|
+
expect(ScheduledJob.logger).to receive(:error)
|
87
|
+
expect(UnderTest).to receive(:schedule_job)
|
88
|
+
Delayed::Job.stub(:enqueue)
|
89
|
+
under_test.failure(dummy_job)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "adds error to the class" do
|
93
|
+
expect(under_test).to respond_to :error
|
94
|
+
end
|
95
|
+
|
96
|
+
it "logs on error" do
|
97
|
+
job = double("job")
|
98
|
+
job.stub(:id) { 4 }
|
99
|
+
expect(ScheduledJob.logger).to receive(:warn)
|
100
|
+
UnderTest.stub(:schedule_job)
|
101
|
+
under_test.error job, nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "wraps delayed job with scheduled_job" do
|
105
|
+
job = double("job")
|
106
|
+
job.stub(:id) { 4 }
|
107
|
+
instance = double("instance")
|
108
|
+
UnderTest.stub(:new) { instance }
|
109
|
+
expect(Delayed::Job).to receive(:exists?).and_return(false)
|
110
|
+
expect(Delayed::Job).to receive(:enqueue).with(instance, run_at: "time to recur", queue: "TESTING")
|
111
|
+
UnderTest.schedule_job job
|
112
|
+
end
|
113
|
+
|
114
|
+
it "scheduled a job even if there is total failure and an existing job" do
|
115
|
+
dummy_job = double("job")
|
116
|
+
dummy_job.stub(:id)
|
117
|
+
expect(dummy_job).to receive(:update_attributes!)
|
118
|
+
expect(Delayed::Job).to receive(:exists?).twice.and_return(false)
|
119
|
+
expect(Delayed::Job).to receive(:enqueue).exactly(2).times
|
120
|
+
UnderTest.schedule_job
|
121
|
+
under_test.failure(dummy_job)
|
122
|
+
end
|
123
|
+
|
124
|
+
describe '#random_minutes' do
|
125
|
+
it 'returns a random number with a base and delta' do
|
126
|
+
expect(UnderTest.random_minutes(60, 10)).to be_within(10 * 60).of(60 * 60)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'returns a random number when called with a negative delta' do
|
130
|
+
expect(UnderTest.random_minutes(10, -2)).to be_within(2 * 60).of(10 * 60)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'returns base when called with delta of 0' do
|
134
|
+
expect(UnderTest.random_minutes(5, 0)).to be_within(0).of(5 * 60)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
Bundler.setup
|
6
|
+
|
7
|
+
require 'scheduled_job' # and any other gems you need
|
8
|
+
require 'logger'
|
9
|
+
|
10
|
+
ScheduledJob.configure do |config|
|
11
|
+
config.logger = Logger.new(nil)
|
12
|
+
end
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
# some (optional) config here
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scheduled_job
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- CallumD
|
8
|
+
- aliscott
|
9
|
+
- smcgivern
|
10
|
+
- alikhajeh1
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2014-07-18 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: delayed_job
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - '='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - '='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.0.5
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: delayed_job_active_record
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - '='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 0.4.4
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - '='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.4.4
|
44
|
+
- !ruby/object:Gem::Dependency
|
45
|
+
name: bundler
|
46
|
+
requirement: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - "~>"
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '1.5'
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.5'
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rake
|
60
|
+
requirement: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - "~>"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0.9'
|
65
|
+
type: :development
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0.9'
|
72
|
+
- !ruby/object:Gem::Dependency
|
73
|
+
name: rspec
|
74
|
+
requirement: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :development
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
- !ruby/object:Gem::Dependency
|
87
|
+
name: pry
|
88
|
+
requirement: !ruby/object:Gem::Requirement
|
89
|
+
requirements:
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '0'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '0'
|
100
|
+
- !ruby/object:Gem::Dependency
|
101
|
+
name: simplecov
|
102
|
+
requirement: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - ">="
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
description: By including the scheduled job module in a delayed job you can specify
|
115
|
+
when you would like the job to run again. Currently this is intented to be used
|
116
|
+
with the active record back end this may change in future.
|
117
|
+
email:
|
118
|
+
- callum.dryden@rightscale.com
|
119
|
+
- alistair@rightscale.com
|
120
|
+
- sean.mcgivern@rightscale.com
|
121
|
+
- ali@rightscale.com
|
122
|
+
executables: []
|
123
|
+
extensions: []
|
124
|
+
extra_rdoc_files: []
|
125
|
+
files:
|
126
|
+
- ".gitignore"
|
127
|
+
- ".ruby-version"
|
128
|
+
- ".travis.yml"
|
129
|
+
- CHANGELOG.md
|
130
|
+
- Gemfile
|
131
|
+
- LICENSE.txt
|
132
|
+
- README.md
|
133
|
+
- Rakefile
|
134
|
+
- lib/scheduled_job.rb
|
135
|
+
- lib/scheduled_job/version.rb
|
136
|
+
- pry.rb
|
137
|
+
- scheduled_job.gemspec
|
138
|
+
- scheduled_job.rconf
|
139
|
+
- spec/lib/scheduled_job_spec.rb
|
140
|
+
- spec/spec_helper.rb
|
141
|
+
homepage: https://github.com/rightscale/scheduled_job
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 2.2.2
|
162
|
+
signing_key:
|
163
|
+
specification_version: 4
|
164
|
+
summary: Adding support for jobs that need to reccur
|
165
|
+
test_files:
|
166
|
+
- spec/lib/scheduled_job_spec.rb
|
167
|
+
- spec/spec_helper.rb
|
168
|
+
has_rdoc:
|