roqua-support 0.1.26 → 0.1.27
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +3 -0
- data/README.md +29 -0
- data/lib/roqua-support.rb +10 -0
- data/lib/roqua-support/railtie.rb +16 -0
- data/lib/roqua-support/version.rb +1 -1
- data/lib/roqua/probes/scheduling_probe.rb +15 -0
- data/lib/roqua/scheduling/cron_job.rb +3 -0
- data/lib/roqua/scheduling/cron_job_table.rb +12 -0
- data/lib/roqua/scheduling/schedule.rb +34 -0
- data/lib/roqua/scheduling/scheduler.rb +47 -0
- data/lib/roqua/scheduling/task.rb +23 -0
- data/roqua-support.gemspec +4 -3
- data/spec/roqua/scheduling/scheduler_spec.rb +106 -0
- data/spec/spec_helper.rb +6 -4
- metadata +53 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bda6e60469417b289cc6b362240df7943ef3a32
|
4
|
+
data.tar.gz: 8b5a13cfbeddc4eb24f7d1cca3fe5c828df019c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dbd51457aa872e2684042494741aadc952814266fde183c09a7bf48f8a6d969df495fe3f708c39aa5d6fb3d4ecbcf6ad716037177b69fe65b3da5b205ec60e2
|
7
|
+
data.tar.gz: 7f39013acd584c9faead2d9475c0f8ed8fc74b455b4eb621a0596a2fef41482f0b59b7e5fa41c7bb0b8757ed2f1c44bd24875f6bfcc0b02b9084bdca23851779
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -12,6 +12,7 @@ PATH
|
|
12
12
|
active_interaction (~> 3.0)
|
13
13
|
activesupport (>= 3.2, < 6)
|
14
14
|
naught (~> 1.0)
|
15
|
+
with_advisory_lock (~> 3.2)
|
15
16
|
|
16
17
|
GEM
|
17
18
|
remote: https://rubygems.org/
|
@@ -168,6 +169,8 @@ GEM
|
|
168
169
|
tzinfo (1.2.2)
|
169
170
|
thread_safe (~> 0.1)
|
170
171
|
unicode-display_width (1.3.0)
|
172
|
+
with_advisory_lock (3.2.0)
|
173
|
+
activerecord (>= 3.2)
|
171
174
|
|
172
175
|
PLATFORMS
|
173
176
|
ruby
|
data/README.md
CHANGED
@@ -110,6 +110,35 @@ Enable it in a project by calling:
|
|
110
110
|
Roqua::Probes::DelayedJobProbe.enable
|
111
111
|
```
|
112
112
|
|
113
|
+
# Scheduling
|
114
|
+
|
115
|
+
For running code in a recurring fashion (for example hourly or daily) a scheduling mechanism is included in roqua-support.
|
116
|
+
|
117
|
+
To configure the jobs that need to run you need to create the file `config/schedule.rb` in the Rails project that you want
|
118
|
+
to schedule jobs for. An example configuration:
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
122
|
+
cron.add_task 'hourly', run_at: Roqua::Scheduling::Schedule::BEGINNING_OF_EVERY_HOUR do
|
123
|
+
# Put code here that you want to run at the first minute of every hour
|
124
|
+
end
|
125
|
+
|
126
|
+
cron.add_task 'daily', run_at: Roqua::Scheduling::Schedule::BEGINNING_OF_EVERY_DAY do
|
127
|
+
# Put code here that you want to run every day at 0:00
|
128
|
+
end
|
129
|
+
|
130
|
+
cron.add_task 'every_10_minutes', run_at: proc { 10.minutes.from_now } do
|
131
|
+
# Put code here that you want to approximately run every 10 minutes. Because the run_at is calculated after a job
|
132
|
+
# is finished the time between jobs will be 10 minutes plus the time the job itself takes.
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
Normally the RoQua infrastructure should be prepared so the jobs automatically are run if the application is correctly
|
138
|
+
deployed. An AppSignal probe can be used as a fallback for job triggering. It can be enabled by placing the following
|
139
|
+
code in a Rails initializer:
|
140
|
+
`Roqua::Probes::SchedulingProbe.enable`
|
141
|
+
|
113
142
|
### ActiveInteraction extensions
|
114
143
|
|
115
144
|
```
|
data/lib/roqua-support.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
require "roqua-support/version"
|
2
|
+
require "roqua-support/railtie" if defined?(Rails)
|
2
3
|
require "roqua/support"
|
3
4
|
|
4
5
|
module Roqua
|
5
6
|
module Probes
|
6
7
|
autoload :DelayedJobProbe, 'roqua/probes/delayed_job_probe'
|
8
|
+
autoload :SchedulingProbe, 'roqua/probes/scheduling_probe'
|
7
9
|
end
|
8
10
|
|
9
11
|
module Responders
|
10
12
|
autoload :ApiErrorsResponder, 'roqua/responders/api_errors_responder'
|
11
13
|
autoload :ActiveInteractionAwareResponder, 'roqua/responders/active_interaction_aware_responder'
|
12
14
|
end
|
15
|
+
|
16
|
+
module Scheduling
|
17
|
+
autoload :CronJob, 'roqua/scheduling/cron_job'
|
18
|
+
autoload :CronJobTable, 'roqua/scheduling/cron_job_table'
|
19
|
+
autoload :Scheduler, 'roqua/scheduling/scheduler'
|
20
|
+
autoload :Schedule, 'roqua/scheduling/schedule'
|
21
|
+
autoload :Task, 'roqua/scheduling/task'
|
22
|
+
end
|
13
23
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Roqua
|
2
|
+
# Include global rake tasks
|
3
|
+
class Railtie < Rails::Railtie
|
4
|
+
rake_tasks do
|
5
|
+
namespace :roqua do
|
6
|
+
desc 'Check if cron needs to run on this instance of the application'
|
7
|
+
task :cron_ping do
|
8
|
+
ActiveRecord::Base.establish_connection
|
9
|
+
require_relative Rails.root.join('config', 'schedule.rb')
|
10
|
+
Roqua::Scheduling::Scheduler.new.ping
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'base_probe'
|
2
|
+
|
3
|
+
module Roqua
|
4
|
+
module Probes
|
5
|
+
class SchedulingProbe
|
6
|
+
extend BaseProbe
|
7
|
+
|
8
|
+
def call
|
9
|
+
ActiveRecord::Base.establish_connection
|
10
|
+
require_relative Rails.root.join('config', 'schedule.rb')
|
11
|
+
Roqua::Scheduling::Scheduler.new.ping
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Roqua::Scheduling::CronJobTable
|
2
|
+
def self.create_cron_jobs_table(schema)
|
3
|
+
schema.create_table :roqua_scheduling_cron_jobs, force: true do |t|
|
4
|
+
t.string :name, null: false
|
5
|
+
t.datetime :next_run_at, null: false
|
6
|
+
t.datetime :completed_at
|
7
|
+
t.timestamps null: false
|
8
|
+
end
|
9
|
+
|
10
|
+
schema.add_index :roqua_scheduling_cron_jobs, :name, unique: true
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Roqua::Scheduling::Schedule
|
2
|
+
attr_reader :tasks
|
3
|
+
|
4
|
+
BEGINNING_OF_EVERY_DAY = proc { Time.now.beginning_of_day + 1.day }
|
5
|
+
BEGINNING_OF_EVERY_HOUR = proc { Time.now.beginning_of_hour + 1.hour }
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@tasks = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_task(name, options, &block)
|
12
|
+
@tasks[name] = Roqua::Scheduling::Task.new(name, options, block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.setup
|
16
|
+
@schedule = Roqua::Scheduling::Schedule.new.tap do |new_schedule|
|
17
|
+
yield(new_schedule)
|
18
|
+
new_schedule.initialize_cronjob_table
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.current_schedule
|
23
|
+
@schedule ||= Roqua::Scheduling::Schedule.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize_cronjob_table
|
27
|
+
Roqua::Scheduling::CronJob.where('name NOT IN (?)', tasks.values.map(&:name)).delete_all
|
28
|
+
|
29
|
+
tasks.each_value do |task|
|
30
|
+
cron_job = Roqua::Scheduling::CronJob.find_or_initialize_by(name: task.name)
|
31
|
+
cron_job.update next_run_at: task.next_run_at unless cron_job.persisted?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'with_advisory_lock'
|
2
|
+
|
3
|
+
class Roqua::Scheduling::Scheduler
|
4
|
+
def ping
|
5
|
+
with_advisory_lock do
|
6
|
+
jobs_to_run.each do |cron_job|
|
7
|
+
begin
|
8
|
+
run_task cron_job
|
9
|
+
rescue Exception => ex
|
10
|
+
Roqua::Support::Errors.report(ex)
|
11
|
+
raise ex if Rails.env.test?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def jobs_to_run
|
18
|
+
Roqua::Scheduling::CronJob.where('next_run_at <= ?', Time.now)
|
19
|
+
end
|
20
|
+
|
21
|
+
def tasks
|
22
|
+
schedule.tasks
|
23
|
+
end
|
24
|
+
|
25
|
+
def schedule
|
26
|
+
Roqua::Scheduling::Schedule.current_schedule
|
27
|
+
end
|
28
|
+
|
29
|
+
def advisory_lock_name
|
30
|
+
"#{ActiveRecord::Base.connection_config[:database]}_cron_lock"
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def with_advisory_lock
|
36
|
+
ActiveRecord::Base.with_advisory_lock(advisory_lock_name, timeout_seconds: 0) do
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run_task(cron_job)
|
42
|
+
task = schedule.tasks[cron_job.name]
|
43
|
+
task.run
|
44
|
+
|
45
|
+
cron_job.update completed_at: Time.now, next_run_at: task.next_run_at
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Roqua::Scheduling
|
2
|
+
class Task
|
3
|
+
attr_reader :name, :options
|
4
|
+
|
5
|
+
def initialize(name, options, callback)
|
6
|
+
@name = name
|
7
|
+
@options = options
|
8
|
+
@callback = callback
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_at
|
12
|
+
options[:run_at]
|
13
|
+
end
|
14
|
+
|
15
|
+
def next_run_at
|
16
|
+
run_at.call
|
17
|
+
end
|
18
|
+
|
19
|
+
def run
|
20
|
+
@callback.call
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/roqua-support.gemspec
CHANGED
@@ -18,15 +18,16 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
|
21
|
+
gem.add_dependency 'active_interaction', '~> 3.0'
|
21
22
|
gem.add_dependency 'activesupport', '>= 3.2', '< 6'
|
22
23
|
gem.add_dependency 'naught', '~> 1.0'
|
23
|
-
gem.add_dependency '
|
24
|
+
gem.add_dependency 'with_advisory_lock', '~> 3.2'
|
24
25
|
|
26
|
+
gem.add_development_dependency 'appsignal', '>= 2.3.1'
|
25
27
|
gem.add_development_dependency 'bundler', '~> 1.0'
|
28
|
+
gem.add_development_dependency 'delayed_job_active_record'
|
26
29
|
gem.add_development_dependency 'rake'
|
27
30
|
gem.add_development_dependency 'rspec', '>= 2.12.0', '< 4.0'
|
28
|
-
gem.add_development_dependency 'appsignal', '>= 2.3.1'
|
29
|
-
gem.add_development_dependency 'delayed_job_active_record'
|
30
31
|
gem.add_development_dependency 'sqlite3'
|
31
32
|
gem.add_development_dependency 'timecop'
|
32
33
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'timecop'
|
3
|
+
|
4
|
+
describe Roqua::Scheduling::Scheduler do
|
5
|
+
before do
|
6
|
+
Timecop.freeze
|
7
|
+
Roqua::Scheduling::CronJob.delete_all
|
8
|
+
end
|
9
|
+
|
10
|
+
after { Timecop.return }
|
11
|
+
|
12
|
+
subject { described_class.new }
|
13
|
+
|
14
|
+
def setup_daily_and_hourly_schedule
|
15
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
16
|
+
cron.add_task 'hourly', run_at: Roqua::Scheduling::Schedule::BEGINNING_OF_EVERY_HOUR do
|
17
|
+
end
|
18
|
+
|
19
|
+
cron.add_task 'daily', run_at: Roqua::Scheduling::Schedule::BEGINNING_OF_EVERY_DAY do
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def setup_hourly_schedule
|
25
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
26
|
+
cron.add_task 'hourly', run_at: Roqua::Scheduling::Schedule::BEGINNING_OF_EVERY_HOUR do
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'creates the correct table rows' do
|
32
|
+
expect { setup_daily_and_hourly_schedule }
|
33
|
+
.to change { Roqua::Scheduling::CronJob.all.pluck(:name, :next_run_at, :completed_at) }
|
34
|
+
.from(
|
35
|
+
[]
|
36
|
+
)
|
37
|
+
.to(
|
38
|
+
[
|
39
|
+
['hourly', Time.now.beginning_of_hour + 1.hour, nil],
|
40
|
+
['daily', Time.now.beginning_of_day + 1.day, nil]
|
41
|
+
]
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'removes unused table rows' do
|
46
|
+
setup_daily_and_hourly_schedule
|
47
|
+
|
48
|
+
expect { setup_hourly_schedule }
|
49
|
+
.to change { Roqua::Scheduling::CronJob.all.pluck(:name).sort }
|
50
|
+
.from(['daily', 'hourly']).to(['hourly'])
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'generates a database specific advisory lock name' do
|
54
|
+
expect(ActiveRecord::Base.connection_config[:database]).to eql(':memory:')
|
55
|
+
expect(subject.advisory_lock_name).to eql ':memory:_cron_lock'
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'with a run_at in the future' do
|
59
|
+
before do
|
60
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
61
|
+
cron.add_task 'hourly', run_at: proc { 1.minute.from_now } do
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'the task will not be run' do
|
67
|
+
expect(subject.schedule.tasks['hourly']).to_not receive(:run)
|
68
|
+
subject.ping
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'callbacks' do
|
73
|
+
let(:callback_spy) { spy(:callback) }
|
74
|
+
|
75
|
+
it 'get executed' do
|
76
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
77
|
+
cron.add_task 'hourly', run_at: proc { 1.minute.ago } do
|
78
|
+
callback_spy.execute
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
expect(callback_spy).to receive(:execute)
|
83
|
+
subject.ping
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'when running multiple times' do
|
88
|
+
before do
|
89
|
+
Timecop.freeze(60.seconds.ago)
|
90
|
+
|
91
|
+
Roqua::Scheduling::Schedule.setup do |cron|
|
92
|
+
cron.add_task 'task', run_at: proc { 30.seconds.from_now } do
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
let(:schedule) { Roqua::Scheduling::Schedule.current_schedule }
|
98
|
+
|
99
|
+
it 'the task is only called once' do
|
100
|
+
expect(schedule.tasks['task']).to receive(:run).once
|
101
|
+
|
102
|
+
Timecop.return
|
103
|
+
3.times { Roqua::Scheduling::Scheduler.new.ping }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -19,9 +19,9 @@ ActiveRecord::Base.logger = Delayed::Worker.logger
|
|
19
19
|
ActiveRecord::Migration.verbose = false
|
20
20
|
|
21
21
|
ActiveRecord::Schema.define do
|
22
|
-
create_table :delayed_jobs, :
|
23
|
-
t.integer :priority, :
|
24
|
-
t.integer :attempts, :
|
22
|
+
create_table :delayed_jobs, force: true do |t|
|
23
|
+
t.integer :priority, default: 0
|
24
|
+
t.integer :attempts, default: 0
|
25
25
|
t.text :handler
|
26
26
|
t.text :last_error
|
27
27
|
t.datetime :run_at
|
@@ -33,5 +33,7 @@ ActiveRecord::Schema.define do
|
|
33
33
|
t.timestamps null: false
|
34
34
|
end
|
35
35
|
|
36
|
-
add_index :delayed_jobs, [:priority, :run_at], :
|
36
|
+
add_index :delayed_jobs, [:priority, :run_at], name: 'delayed_jobs_priority'
|
37
|
+
|
38
|
+
Roqua::Scheduling::CronJobTable.create_cron_jobs_table(self)
|
37
39
|
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roqua-support
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.27
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marten Veldthuis
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: active_interaction
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: activesupport
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -45,95 +59,95 @@ dependencies:
|
|
45
59
|
- !ruby/object:Gem::Version
|
46
60
|
version: '1.0'
|
47
61
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
62
|
+
name: with_advisory_lock
|
49
63
|
requirement: !ruby/object:Gem::Requirement
|
50
64
|
requirements:
|
51
65
|
- - "~>"
|
52
66
|
- !ruby/object:Gem::Version
|
53
|
-
version: '3.
|
67
|
+
version: '3.2'
|
54
68
|
type: :runtime
|
55
69
|
prerelease: false
|
56
70
|
version_requirements: !ruby/object:Gem::Requirement
|
57
71
|
requirements:
|
58
72
|
- - "~>"
|
59
73
|
- !ruby/object:Gem::Version
|
60
|
-
version: '3.
|
74
|
+
version: '3.2'
|
61
75
|
- !ruby/object:Gem::Dependency
|
62
|
-
name:
|
76
|
+
name: appsignal
|
63
77
|
requirement: !ruby/object:Gem::Requirement
|
64
78
|
requirements:
|
65
|
-
- - "
|
79
|
+
- - ">="
|
66
80
|
- !ruby/object:Gem::Version
|
67
|
-
version:
|
81
|
+
version: 2.3.1
|
68
82
|
type: :development
|
69
83
|
prerelease: false
|
70
84
|
version_requirements: !ruby/object:Gem::Requirement
|
71
85
|
requirements:
|
72
|
-
- - "
|
86
|
+
- - ">="
|
73
87
|
- !ruby/object:Gem::Version
|
74
|
-
version:
|
88
|
+
version: 2.3.1
|
75
89
|
- !ruby/object:Gem::Dependency
|
76
|
-
name:
|
90
|
+
name: bundler
|
77
91
|
requirement: !ruby/object:Gem::Requirement
|
78
92
|
requirements:
|
79
|
-
- - "
|
93
|
+
- - "~>"
|
80
94
|
- !ruby/object:Gem::Version
|
81
|
-
version: '0'
|
95
|
+
version: '1.0'
|
82
96
|
type: :development
|
83
97
|
prerelease: false
|
84
98
|
version_requirements: !ruby/object:Gem::Requirement
|
85
99
|
requirements:
|
86
|
-
- - "
|
100
|
+
- - "~>"
|
87
101
|
- !ruby/object:Gem::Version
|
88
|
-
version: '0'
|
102
|
+
version: '1.0'
|
89
103
|
- !ruby/object:Gem::Dependency
|
90
|
-
name:
|
104
|
+
name: delayed_job_active_record
|
91
105
|
requirement: !ruby/object:Gem::Requirement
|
92
106
|
requirements:
|
93
107
|
- - ">="
|
94
108
|
- !ruby/object:Gem::Version
|
95
|
-
version:
|
96
|
-
- - "<"
|
97
|
-
- !ruby/object:Gem::Version
|
98
|
-
version: '4.0'
|
109
|
+
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
112
|
version_requirements: !ruby/object:Gem::Requirement
|
102
113
|
requirements:
|
103
114
|
- - ">="
|
104
115
|
- !ruby/object:Gem::Version
|
105
|
-
version:
|
106
|
-
- - "<"
|
107
|
-
- !ruby/object:Gem::Version
|
108
|
-
version: '4.0'
|
116
|
+
version: '0'
|
109
117
|
- !ruby/object:Gem::Dependency
|
110
|
-
name:
|
118
|
+
name: rake
|
111
119
|
requirement: !ruby/object:Gem::Requirement
|
112
120
|
requirements:
|
113
121
|
- - ">="
|
114
122
|
- !ruby/object:Gem::Version
|
115
|
-
version:
|
123
|
+
version: '0'
|
116
124
|
type: :development
|
117
125
|
prerelease: false
|
118
126
|
version_requirements: !ruby/object:Gem::Requirement
|
119
127
|
requirements:
|
120
128
|
- - ">="
|
121
129
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
130
|
+
version: '0'
|
123
131
|
- !ruby/object:Gem::Dependency
|
124
|
-
name:
|
132
|
+
name: rspec
|
125
133
|
requirement: !ruby/object:Gem::Requirement
|
126
134
|
requirements:
|
127
135
|
- - ">="
|
128
136
|
- !ruby/object:Gem::Version
|
129
|
-
version:
|
137
|
+
version: 2.12.0
|
138
|
+
- - "<"
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '4.0'
|
130
141
|
type: :development
|
131
142
|
prerelease: false
|
132
143
|
version_requirements: !ruby/object:Gem::Requirement
|
133
144
|
requirements:
|
134
145
|
- - ">="
|
135
146
|
- !ruby/object:Gem::Version
|
136
|
-
version:
|
147
|
+
version: 2.12.0
|
148
|
+
- - "<"
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '4.0'
|
137
151
|
- !ruby/object:Gem::Dependency
|
138
152
|
name: sqlite3
|
139
153
|
requirement: !ruby/object:Gem::Requirement
|
@@ -186,6 +200,7 @@ files:
|
|
186
200
|
- gemfiles/rails42.gemfile
|
187
201
|
- gemfiles/rails50.gemfile
|
188
202
|
- lib/roqua-support.rb
|
203
|
+
- lib/roqua-support/railtie.rb
|
189
204
|
- lib/roqua-support/version.rb
|
190
205
|
- lib/roqua/core_ext/active_interaction/filters/date_time_as_unix_extension.rb
|
191
206
|
- lib/roqua/core_ext/active_interaction/filters/duration_filter.rb
|
@@ -197,8 +212,14 @@ files:
|
|
197
212
|
- lib/roqua/core_ext/fixnum/clamp.rb
|
198
213
|
- lib/roqua/probes/base_probe.rb
|
199
214
|
- lib/roqua/probes/delayed_job_probe.rb
|
215
|
+
- lib/roqua/probes/scheduling_probe.rb
|
200
216
|
- lib/roqua/responders/active_interaction_aware_responder.rb
|
201
217
|
- lib/roqua/responders/api_errors_responder.rb
|
218
|
+
- lib/roqua/scheduling/cron_job.rb
|
219
|
+
- lib/roqua/scheduling/cron_job_table.rb
|
220
|
+
- lib/roqua/scheduling/schedule.rb
|
221
|
+
- lib/roqua/scheduling/scheduler.rb
|
222
|
+
- lib/roqua/scheduling/task.rb
|
202
223
|
- lib/roqua/support.rb
|
203
224
|
- lib/roqua/support/command_runner.rb
|
204
225
|
- lib/roqua/support/errors.rb
|
@@ -220,6 +241,7 @@ files:
|
|
220
241
|
- spec/roqua/probes/delayed_job_probe_spec.rb
|
221
242
|
- spec/roqua/responders/active_interaction_aware_responder_spec.rb
|
222
243
|
- spec/roqua/responders/api_errors_responder_spec.rb
|
244
|
+
- spec/roqua/scheduling/scheduler_spec.rb
|
223
245
|
- spec/roqua/support/errors_spec.rb
|
224
246
|
- spec/roqua/support/helpers_spec.rb
|
225
247
|
- spec/roqua/support/logwrapper_spec.rb
|
@@ -265,6 +287,7 @@ test_files:
|
|
265
287
|
- spec/roqua/probes/delayed_job_probe_spec.rb
|
266
288
|
- spec/roqua/responders/active_interaction_aware_responder_spec.rb
|
267
289
|
- spec/roqua/responders/api_errors_responder_spec.rb
|
290
|
+
- spec/roqua/scheduling/scheduler_spec.rb
|
268
291
|
- spec/roqua/support/errors_spec.rb
|
269
292
|
- spec/roqua/support/helpers_spec.rb
|
270
293
|
- spec/roqua/support/logwrapper_spec.rb
|