crono 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Changes.md +5 -0
- data/Gemfile.lock +21 -1
- data/README.md +54 -21
- data/crono.gemspec +3 -0
- data/examples/crono_web_ui.png +0 -0
- data/examples/cronotab.rb +7 -7
- data/lib/crono/cli.rb +1 -2
- data/lib/crono/job.rb +33 -5
- data/lib/crono/period.rb +12 -2
- data/lib/crono/version.rb +1 -1
- data/lib/crono/web.rb +20 -0
- data/lib/generators/crono/install/templates/cronotab.rb.erb +10 -4
- data/lib/generators/crono/install/templates/migrations/create_crono_jobs.rb +1 -1
- data/spec/job_spec.rb +40 -7
- data/spec/period_spec.rb +12 -3
- data/spec/scheduler_spec.rb +4 -8
- data/spec/spec_helper.rb +2 -1
- data/tmp/.gitkeep +0 -0
- data/web/assets/custom.css +20 -0
- data/web/views/dashboard.haml +17 -0
- data/web/views/job.haml +8 -0
- data/web/views/layout.haml +25 -0
- metadata +51 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88e53a7c4eee894469cb7980928acb90726d65c9
|
4
|
+
data.tar.gz: b0cf49ee7f5edfb936271d5ba4cb7f71319e156e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 283289e7b9ef4cb6840d55513cbbce57b3c4773e816957e3e5394646c2920f2c50954abd240302c0d0c8dff2f623bc576d12ef682d6c3624e74f6486a7de8842
|
7
|
+
data.tar.gz: 5c59231c15eb083f7ca341fdf1d0637cb50cd4ceec8cd05f17661ead5aa68507c664a217598cb1ae858b2ff784058b0fae3db760ffd10ab01fa106916460ea23
|
data/.gitignore
CHANGED
data/Changes.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
crono (0.
|
4
|
+
crono (0.7.0)
|
5
5
|
activejob (~> 4.0)
|
6
6
|
activerecord (~> 4.0)
|
7
7
|
activesupport (~> 4.0)
|
@@ -27,12 +27,23 @@ GEM
|
|
27
27
|
tzinfo (~> 1.1)
|
28
28
|
arel (6.0.0)
|
29
29
|
builder (3.2.2)
|
30
|
+
byebug (3.5.1)
|
31
|
+
columnize (~> 0.8)
|
32
|
+
debugger-linecache (~> 1.2)
|
33
|
+
slop (~> 3.6)
|
34
|
+
columnize (0.9.0)
|
35
|
+
debugger-linecache (1.2.0)
|
30
36
|
diff-lcs (1.2.5)
|
31
37
|
globalid (0.3.3)
|
32
38
|
activesupport (>= 4.1.0)
|
39
|
+
haml (4.0.6)
|
40
|
+
tilt
|
33
41
|
i18n (0.7.0)
|
34
42
|
json (1.8.2)
|
35
43
|
minitest (5.5.1)
|
44
|
+
rack (1.6.0)
|
45
|
+
rack-protection (1.5.3)
|
46
|
+
rack
|
36
47
|
rake (10.4.2)
|
37
48
|
rspec (3.2.0)
|
38
49
|
rspec-core (~> 3.2.0)
|
@@ -47,8 +58,14 @@ GEM
|
|
47
58
|
diff-lcs (>= 1.2.0, < 2.0)
|
48
59
|
rspec-support (~> 3.2.0)
|
49
60
|
rspec-support (3.2.2)
|
61
|
+
sinatra (1.4.5)
|
62
|
+
rack (~> 1.4)
|
63
|
+
rack-protection (~> 1.4)
|
64
|
+
tilt (~> 1.3, >= 1.3.4)
|
65
|
+
slop (3.6.0)
|
50
66
|
sqlite3 (1.3.10)
|
51
67
|
thread_safe (0.3.4)
|
68
|
+
tilt (1.4.1)
|
52
69
|
timecop (0.7.3)
|
53
70
|
tzinfo (1.2.2)
|
54
71
|
thread_safe (~> 0.1)
|
@@ -58,8 +75,11 @@ PLATFORMS
|
|
58
75
|
|
59
76
|
DEPENDENCIES
|
60
77
|
bundler (>= 1.0.0)
|
78
|
+
byebug
|
61
79
|
crono!
|
80
|
+
haml
|
62
81
|
rake (~> 10.0)
|
63
82
|
rspec (~> 3.0)
|
83
|
+
sinatra
|
64
84
|
sqlite3
|
65
85
|
timecop (~> 0.7)
|
data/README.md
CHANGED
@@ -13,6 +13,7 @@ Crono is a time-based background job scheduler daemon (just like Cron) for Ruby
|
|
13
13
|
|
14
14
|
Currently there is no such thing as Cron in Ruby for Rails. Well, there's [Whenever](https://github.com/javan/whenever) but it works on top of Unix Cron, so you have no total control of it from Ruby. Crono is pure Ruby. It doesn't use Unix Cron and other platform-dependent things. So you can use it on all platforms supported by Ruby. It persists job state to your database using Active Record. You have full control of jobs performing process. You have Ruby code, so you can understand and modify it to fit your needs.
|
15
15
|
|
16
|
+
![Web UI](https://github.com/plashchynski/crono/raw/master/examples/crono_web_ui.png)
|
16
17
|
|
17
18
|
## Requirements
|
18
19
|
|
@@ -24,7 +25,9 @@ Other versions are untested but might work fine.
|
|
24
25
|
|
25
26
|
Add the following line to your application's Gemfile:
|
26
27
|
|
27
|
-
|
28
|
+
```ruby
|
29
|
+
gem 'crono'
|
30
|
+
```
|
28
31
|
|
29
32
|
Run the `bundle` command to install it.
|
30
33
|
After you install Crono, you can run the generator:
|
@@ -47,40 +50,48 @@ Crono can use Active Job jobs from `app/jobs/`. The only requirements is that th
|
|
47
50
|
|
48
51
|
Here's an example of a test job:
|
49
52
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
```ruby
|
54
|
+
# app/jobs/test_job.rb
|
55
|
+
class TestJob < ActiveJob::Base
|
56
|
+
def perform
|
57
|
+
# put you scheduled code here
|
58
|
+
# Comments.deleted.clean_up...
|
59
|
+
end
|
60
|
+
end
|
61
|
+
```
|
57
62
|
|
58
63
|
The ActiveJob jobs is convenient because you can use one job in both periodic and enqueued ways. But Active Job is not required. Any class can be used as a crono job if it implements a method `perform` without arguments:
|
59
64
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
65
|
+
```ruby
|
66
|
+
class TestJob # This is not an Active Job job, but pretty legal Crono job.
|
67
|
+
def perform
|
68
|
+
# put you scheduled code here
|
69
|
+
# Comments.deleted.clean_up...
|
70
|
+
end
|
71
|
+
end
|
72
|
+
```
|
67
73
|
|
68
74
|
#### Job Schedule
|
69
75
|
|
70
76
|
The schedule described in the configuration file `config/cronotab.rb`, that created using `crono:install` or manually. The semantic is pretty straightforward:
|
71
77
|
|
72
|
-
|
73
|
-
|
78
|
+
```ruby
|
79
|
+
# config/cronotab.rb
|
80
|
+
Crono.perform(TestJob).every 2.days, at: "15:30"
|
81
|
+
```
|
74
82
|
|
75
83
|
You can schedule one job a few times, if you want a job to be performed a few times a day:
|
76
84
|
|
77
|
-
|
78
|
-
|
85
|
+
```ruby
|
86
|
+
Crono.perform(TestJob).every 1.day, at: "00:00"
|
87
|
+
Crono.perform(TestJob).every 1.day, at: "12:00"
|
88
|
+
```
|
79
89
|
|
80
90
|
The `at` can be a Hash:
|
81
91
|
|
82
|
-
|
83
|
-
|
92
|
+
```ruby
|
93
|
+
Crono.perform(TestJob).every 1.day, at: {hour: 12, min: 15}
|
94
|
+
```
|
84
95
|
|
85
96
|
#### Run daemon
|
86
97
|
|
@@ -98,6 +109,28 @@ Usage: crono [options]
|
|
98
109
|
-e, --environment ENV Application environment (Default: development)
|
99
110
|
```
|
100
111
|
|
112
|
+
## Web UI
|
113
|
+
|
114
|
+
Crono comes with a Sinatra application that can display the current state of Crono jobs.
|
115
|
+
Add `sinatra` and `haml` to your Gemfile
|
116
|
+
|
117
|
+
```ruby
|
118
|
+
gam 'haml'
|
119
|
+
gem 'sinatra', require: nil
|
120
|
+
```
|
121
|
+
|
122
|
+
Add the following to your `config/routes.rb`:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
require 'crono/web'
|
126
|
+
|
127
|
+
Rails.application.routes.draw do
|
128
|
+
mount Crono::Web, at: '/crono'
|
129
|
+
...
|
130
|
+
```
|
131
|
+
|
132
|
+
Access management and other questions described in the [wiki](https://github.com/plashchynski/crono/wiki/Web-UI).
|
133
|
+
|
101
134
|
## Capistrano
|
102
135
|
|
103
136
|
Use the `capistrano-crono` gem ([github](https://github.com/plashchynski/capistrano-crono/)).
|
data/crono.gemspec
CHANGED
@@ -21,6 +21,9 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_development_dependency "rspec", "~> 3.0"
|
22
22
|
s.add_development_dependency "timecop", "~> 0.7"
|
23
23
|
s.add_development_dependency "sqlite3"
|
24
|
+
s.add_development_dependency "byebug"
|
25
|
+
s.add_development_dependency "sinatra"
|
26
|
+
s.add_development_dependency "haml"
|
24
27
|
|
25
28
|
s.files = `git ls-files`.split("\n")
|
26
29
|
s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
|
Binary file
|
data/examples/cronotab.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
|
-
# cronotab.rb — Crono configuration
|
1
|
+
# cronotab.rb — Crono configuration file
|
2
2
|
#
|
3
|
-
# Here you can specify periodic jobs and
|
4
|
-
# You can
|
5
|
-
#
|
6
|
-
#
|
3
|
+
# Here you can specify periodic jobs and schedule.
|
4
|
+
# You can use ActiveJob's jobs from `app/jobs/`
|
5
|
+
# You can use any class. The only requirement is that
|
6
|
+
# class should have a method `perform` without arguments.
|
7
7
|
#
|
8
|
-
|
9
8
|
class TestJob
|
10
9
|
def perform
|
11
10
|
puts "Test!"
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
15
|
-
Crono.perform(TestJob).every
|
14
|
+
Crono.perform(TestJob).every 2.days, at: "15:30"
|
15
|
+
|
data/lib/crono/cli.rb
CHANGED
@@ -56,7 +56,7 @@ module Crono
|
|
56
56
|
|
57
57
|
logger.info "Jobs:"
|
58
58
|
Crono.scheduler.jobs.each do |job|
|
59
|
-
logger.info job.description
|
59
|
+
logger.info %{"#{job.performer}" with rule "#{job.period.description}" next time will perform at #{job.next}}
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -75,7 +75,6 @@ module Crono
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def start_working_loop
|
78
|
-
Thread.abort_on_exception = true
|
79
78
|
while job = Crono.scheduler.next do
|
80
79
|
sleep(job.next - Time.now)
|
81
80
|
job.perform
|
data/lib/crono/job.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'logger'
|
3
|
+
|
1
4
|
module Crono
|
2
5
|
class Job
|
3
6
|
include Logging
|
@@ -5,9 +8,14 @@ module Crono
|
|
5
8
|
attr_accessor :performer
|
6
9
|
attr_accessor :period
|
7
10
|
attr_accessor :last_performed_at
|
11
|
+
attr_accessor :job_log
|
12
|
+
attr_accessor :job_logger
|
8
13
|
|
9
14
|
def initialize(performer, period)
|
10
15
|
self.performer, self.period = performer, period
|
16
|
+
self.job_log = StringIO.new
|
17
|
+
self.job_logger = Logger.new(job_log)
|
18
|
+
@semaphore = Mutex.new
|
11
19
|
end
|
12
20
|
|
13
21
|
def next
|
@@ -24,17 +32,30 @@ module Crono
|
|
24
32
|
end
|
25
33
|
|
26
34
|
def perform
|
27
|
-
|
35
|
+
log "Perform #{performer}"
|
28
36
|
self.last_performed_at = Time.now
|
29
|
-
|
37
|
+
|
30
38
|
Thread.new do
|
31
|
-
|
32
|
-
|
39
|
+
begin
|
40
|
+
performer.new.perform
|
41
|
+
rescue Exception => e
|
42
|
+
log "Finished #{performer} in %.2f seconds with error: #{e.message}" % (Time.now - last_performed_at)
|
43
|
+
log e.backtrace.join("\n")
|
44
|
+
else
|
45
|
+
log "Finished #{performer} in %.2f seconds" % (Time.now - last_performed_at)
|
46
|
+
ensure
|
47
|
+
save
|
48
|
+
end
|
33
49
|
end
|
34
50
|
end
|
35
51
|
|
36
52
|
def save
|
37
|
-
|
53
|
+
@semaphore.synchronize do
|
54
|
+
log = model.reload.log || ""
|
55
|
+
log << job_log.string
|
56
|
+
job_log.truncate(job_log.rewind)
|
57
|
+
model.update(last_performed_at: last_performed_at, log: log)
|
58
|
+
end
|
38
59
|
end
|
39
60
|
|
40
61
|
def load
|
@@ -42,6 +63,13 @@ module Crono
|
|
42
63
|
end
|
43
64
|
|
44
65
|
private
|
66
|
+
def log(message)
|
67
|
+
@semaphore.synchronize do
|
68
|
+
logger.info message
|
69
|
+
job_logger.info message
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
45
73
|
def model
|
46
74
|
@model ||= Crono::CronoJob.find_or_create_by(job_id: job_id)
|
47
75
|
end
|
data/lib/crono/period.rb
CHANGED
@@ -6,8 +6,13 @@ module Crono
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def next(since: nil)
|
9
|
-
since
|
10
|
-
|
9
|
+
if since.nil?
|
10
|
+
@next = Time.now.change(time_atts)
|
11
|
+
return @next if @next.future?
|
12
|
+
since = Time.now
|
13
|
+
end
|
14
|
+
|
15
|
+
@period.since(since).change(time_atts)
|
11
16
|
end
|
12
17
|
|
13
18
|
def description
|
@@ -27,5 +32,10 @@ module Crono
|
|
27
32
|
raise "Unknown 'at' format"
|
28
33
|
end
|
29
34
|
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def time_atts
|
38
|
+
{hour: @at_hour, min: @at_min}.compact
|
39
|
+
end
|
30
40
|
end
|
31
41
|
end
|
data/lib/crono/version.rb
CHANGED
data/lib/crono/web.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'haml'
|
2
|
+
require 'sinatra/base'
|
3
|
+
|
4
|
+
module Crono
|
5
|
+
class Web < Sinatra::Base
|
6
|
+
set :root, File.expand_path(File.dirname(__FILE__) + "/../../web")
|
7
|
+
set :public_folder, Proc.new { "#{root}/assets" }
|
8
|
+
set :views, Proc.new { "#{root}/views" }
|
9
|
+
|
10
|
+
get '/' do
|
11
|
+
@jobs = Crono::CronoJob.all
|
12
|
+
haml :dashboard, format: :html5
|
13
|
+
end
|
14
|
+
|
15
|
+
get '/jobs/:id' do
|
16
|
+
@job = Crono::CronoJob.find(params[:id])
|
17
|
+
haml :job
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,9 +1,15 @@
|
|
1
1
|
# cronotab.rb — Crono configuration file
|
2
2
|
#
|
3
|
-
# Here you can specify periodic jobs and
|
4
|
-
# You can
|
5
|
-
#
|
6
|
-
#
|
3
|
+
# Here you can specify periodic jobs and schedule.
|
4
|
+
# You can use ActiveJob's jobs from `app/jobs/`
|
5
|
+
# You can use any class. The only requirement is that
|
6
|
+
# class should have a method `perform` without arguments.
|
7
|
+
#
|
8
|
+
# class TestJob
|
9
|
+
# def perform
|
10
|
+
# puts "Test!"
|
11
|
+
# end
|
12
|
+
# end
|
7
13
|
#
|
8
14
|
# Crono.perform(TestJob).every 2.days, at: "15:30"
|
9
15
|
#
|
data/spec/job_spec.rb
CHANGED
@@ -4,9 +4,16 @@ class TestJob
|
|
4
4
|
def perform;end
|
5
5
|
end
|
6
6
|
|
7
|
+
class TestFailingJob
|
8
|
+
def perform
|
9
|
+
raise "Some error"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
describe Crono::Job do
|
8
14
|
let(:period) { Crono::Period.new(2.day) }
|
9
15
|
let(:job) { Crono::Job.new(TestJob, period) }
|
16
|
+
let(:failing_job) { Crono::Job.new(TestFailingJob, period) }
|
10
17
|
|
11
18
|
it "should contain performer and period" do
|
12
19
|
expect(job.performer).to be TestJob
|
@@ -15,14 +22,17 @@ describe Crono::Job do
|
|
15
22
|
|
16
23
|
describe "#perform" do
|
17
24
|
it "should run performer in separate thread" do
|
25
|
+
expect(job).to receive(:save)
|
18
26
|
thread = job.perform.join
|
19
27
|
expect(thread).to be_stop
|
28
|
+
job.send(:model).destroy
|
20
29
|
end
|
21
30
|
|
22
|
-
it "should
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
it "should save performin errors to log" do
|
32
|
+
thread = failing_job.perform.join
|
33
|
+
expect(thread).to be_stop
|
34
|
+
saved_log = Crono::CronoJob.find_by(job_id: failing_job.job_id).log
|
35
|
+
expect(saved_log).to include "Some error"
|
26
36
|
end
|
27
37
|
end
|
28
38
|
|
@@ -43,7 +53,15 @@ describe Crono::Job do
|
|
43
53
|
job.last_performed_at = Time.now
|
44
54
|
job.save
|
45
55
|
@crono_job = Crono::CronoJob.find_by(job_id: job.job_id)
|
46
|
-
expect(@crono_job.last_performed_at).to be_eql
|
56
|
+
expect(@crono_job.last_performed_at.utc.to_s).to be_eql job.last_performed_at.utc.to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should save and truncate job log" do
|
60
|
+
message = "test message"
|
61
|
+
job.send(:log, message)
|
62
|
+
job.save
|
63
|
+
expect(job.send(:model).reload.log).to include message
|
64
|
+
expect(job.job_log.string).to be_empty
|
47
65
|
end
|
48
66
|
end
|
49
67
|
|
@@ -53,10 +71,25 @@ describe Crono::Job do
|
|
53
71
|
job.save
|
54
72
|
end
|
55
73
|
|
56
|
-
it "should load
|
74
|
+
it "should load last_performed_at from DB" do
|
57
75
|
@job = Crono::Job.new(TestJob, period)
|
58
76
|
@job.load
|
59
|
-
expect(@job.last_performed_at).to be_eql @saved_last_performed_at
|
77
|
+
expect(@job.last_performed_at.utc.to_s).to be_eql @saved_last_performed_at.utc.to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#log" do
|
82
|
+
it "should write log messages to both common and job log" do
|
83
|
+
message = "Test message"
|
84
|
+
expect(job.logger).to receive(:info).with(message)
|
85
|
+
expect(job.job_logger).to receive(:info).with(message)
|
86
|
+
job.send(:log, message)
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should write job log to Job#job_log" do
|
90
|
+
message = "Test message"
|
91
|
+
job.send(:log, message)
|
92
|
+
expect(job.job_log.string).to include(message)
|
60
93
|
end
|
61
94
|
end
|
62
95
|
end
|
data/spec/period_spec.rb
CHANGED
@@ -22,12 +22,14 @@ describe Crono::Period do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should set time to 'at' time as a string" do
|
25
|
-
|
26
|
-
|
25
|
+
time = 10.minutes.ago
|
26
|
+
@period = Crono::Period.new(2.day, at: [time.hour, time.min].join(':'))
|
27
|
+
expect(@period.next).to be_eql(2.day.from_now.change(hour: time.hour, min: time.min))
|
27
28
|
end
|
28
29
|
|
29
30
|
it "should set time to 'at' time as a hash" do
|
30
|
-
|
31
|
+
time = 10.minutes.ago
|
32
|
+
at = {hour: time.hour, min: time.min}
|
31
33
|
@period = Crono::Period.new(2.day, at: at)
|
32
34
|
expect(@period.next).to be_eql(2.day.from_now.change(at))
|
33
35
|
end
|
@@ -42,6 +44,13 @@ describe Crono::Period do
|
|
42
44
|
@period = Crono::Period.new(2.day)
|
43
45
|
expect(@period.next(since: 1.day.ago)).to be_eql(1.day.from_now)
|
44
46
|
end
|
47
|
+
|
48
|
+
it "should return today time if it is first run and not too late" do
|
49
|
+
time = 10.minutes.from_now
|
50
|
+
at = {hour: time.hour, min: time.min}
|
51
|
+
@period = Crono::Period.new(2.day, at: at)
|
52
|
+
expect(@period.next).to be_eql(Time.now.change(at))
|
53
|
+
end
|
45
54
|
end
|
46
55
|
end
|
47
56
|
end
|
data/spec/scheduler_spec.rb
CHANGED
@@ -8,9 +8,9 @@ describe Crono::Scheduler do
|
|
8
8
|
before(:each) do
|
9
9
|
@scheduler = Crono::Scheduler.new
|
10
10
|
@jobs = [
|
11
|
-
Crono::Period.new(3.day, at: "
|
12
|
-
Crono::Period.new(1.day, at: "
|
13
|
-
Crono::Period.new(7.day, at: "
|
11
|
+
Crono::Period.new(3.day, at: 10.minutes.from_now.strftime("%H:%M")),
|
12
|
+
Crono::Period.new(1.day, at: 20.minutes.from_now.strftime("%H:%M")),
|
13
|
+
Crono::Period.new(7.day, at: 40.minutes.from_now.strftime("%H:%M"))
|
14
14
|
].map { |period| Crono::Job.new(TestJob, period) }
|
15
15
|
@scheduler.jobs = @jobs
|
16
16
|
end
|
@@ -25,11 +25,7 @@ describe Crono::Scheduler do
|
|
25
25
|
|
26
26
|
describe "#next" do
|
27
27
|
it "should return next job in schedule" do
|
28
|
-
expect(@scheduler.next).to be @jobs[
|
29
|
-
end
|
30
|
-
|
31
|
-
it "should return next based on last" do
|
32
|
-
expect(@scheduler.next)
|
28
|
+
expect(@scheduler.next).to be @jobs[0]
|
33
29
|
end
|
34
30
|
end
|
35
31
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,10 +2,11 @@ require 'bundler/setup'
|
|
2
2
|
Bundler.setup
|
3
3
|
|
4
4
|
require 'timecop'
|
5
|
+
require 'byebug'
|
5
6
|
require 'crono'
|
6
7
|
require 'generators/crono/install/templates/migrations/create_crono_jobs.rb'
|
7
8
|
|
8
|
-
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database:
|
9
|
+
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: "file::memory:?cache=shared")
|
9
10
|
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
10
11
|
CreateCronoJobs.up
|
11
12
|
|
data/tmp/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,20 @@
|
|
1
|
+
.container {
|
2
|
+
background-color: #CFD8DC;
|
3
|
+
}
|
4
|
+
|
5
|
+
body {
|
6
|
+
background-color: #455A64;
|
7
|
+
}
|
8
|
+
|
9
|
+
.page-header {
|
10
|
+
border-bottom: 1px solid #B6B6B6;
|
11
|
+
}
|
12
|
+
|
13
|
+
#job_list td,#job_list th {
|
14
|
+
border-top: 1px solid #B6B6B6;
|
15
|
+
color: #212121;
|
16
|
+
}
|
17
|
+
|
18
|
+
.breadcrumb {
|
19
|
+
background-color: #FFFFFF;
|
20
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
%ol.breadcrumb
|
2
|
+
%li.active Home
|
3
|
+
|
4
|
+
%h3 Running Jobs
|
5
|
+
%table.table#job_list
|
6
|
+
%tr
|
7
|
+
%th Job
|
8
|
+
%th Last performed at
|
9
|
+
%th
|
10
|
+
- for job in @jobs
|
11
|
+
%tr
|
12
|
+
%td= job.job_id
|
13
|
+
%td= job.last_performed_at || "—"
|
14
|
+
%td
|
15
|
+
%a{href: url("/jobs/#{job.id}")}
|
16
|
+
Log
|
17
|
+
%span.glyphicon.glyphicon-menu-right
|
data/web/views/job.haml
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
!!! 5
|
2
|
+
%html{lang: "en"}
|
3
|
+
%head
|
4
|
+
%meta{charset: "utf-8"}
|
5
|
+
%meta{"http-equiv" => "X-UA-Compatible", content: "IE=edge"}
|
6
|
+
%meta{name: "viewport", content: "width=device-width, initial-scale=1"}
|
7
|
+
|
8
|
+
%title Crono Dashboard
|
9
|
+
|
10
|
+
%link{href: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css", rel: "stylesheet"}
|
11
|
+
%link{href: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css", rel: "stylesheet"}
|
12
|
+
%link{href: "#{env['SCRIPT_NAME']}/custom.css", rel: "stylesheet"}
|
13
|
+
|
14
|
+
%body
|
15
|
+
%br
|
16
|
+
%br
|
17
|
+
.container
|
18
|
+
.page-header
|
19
|
+
%h1
|
20
|
+
Crono #{Crono::VERSION}
|
21
|
+
%small Dashboard
|
22
|
+
= yield
|
23
|
+
|
24
|
+
%script{src: "https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"}
|
25
|
+
%script{src: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crono
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dzmitry Plashchynski
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -122,6 +122,48 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: byebug
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: sinatra
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: haml
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
125
167
|
description: Job scheduler for Rails
|
126
168
|
email:
|
127
169
|
- plashchynski@gmail.com
|
@@ -142,6 +184,7 @@ files:
|
|
142
184
|
- Rakefile
|
143
185
|
- bin/crono
|
144
186
|
- crono.gemspec
|
187
|
+
- examples/crono_web_ui.png
|
145
188
|
- examples/cronotab.rb
|
146
189
|
- examples/monitrc.conf
|
147
190
|
- lib/crono.rb
|
@@ -154,6 +197,7 @@ files:
|
|
154
197
|
- lib/crono/period.rb
|
155
198
|
- lib/crono/scheduler.rb
|
156
199
|
- lib/crono/version.rb
|
200
|
+
- lib/crono/web.rb
|
157
201
|
- lib/generators/crono/install/install_generator.rb
|
158
202
|
- lib/generators/crono/install/templates/cronotab.rb.erb
|
159
203
|
- lib/generators/crono/install/templates/migrations/create_crono_jobs.rb
|
@@ -165,6 +209,11 @@ files:
|
|
165
209
|
- spec/period_spec.rb
|
166
210
|
- spec/scheduler_spec.rb
|
167
211
|
- spec/spec_helper.rb
|
212
|
+
- tmp/.gitkeep
|
213
|
+
- web/assets/custom.css
|
214
|
+
- web/views/dashboard.haml
|
215
|
+
- web/views/job.haml
|
216
|
+
- web/views/layout.haml
|
168
217
|
homepage: https://github.com/plashchynski/crono
|
169
218
|
licenses:
|
170
219
|
- Apache-2.0
|