mirror of
https://github.com/plashchynski/crono.git
synced 2026-01-14 14:23:27 +01:00
Compare commits
44 Commits
v1.0.0.pre
...
v1.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a7488df85b | ||
|
|
c777933044 | ||
|
|
0c2f52d9bc | ||
|
|
33e9794621 | ||
|
|
c336b6d00b | ||
|
|
1cf37ee30f | ||
|
|
137dfe6d19 | ||
|
|
14c3e3162e | ||
|
|
d1e15b8537 | ||
|
|
f5d65b6cc7 | ||
|
|
64dde82342 | ||
|
|
e331490c48 | ||
|
|
8a61e65963 | ||
|
|
3f9ea8350d | ||
|
|
1d9d30ef89 | ||
|
|
72810a95ae | ||
|
|
4401c6bba4 | ||
|
|
e7df4bb067 | ||
|
|
935bdebd84 | ||
|
|
b22845cba6 | ||
|
|
77481f1143 | ||
|
|
42dc1bbc4f | ||
|
|
63c52896f7 | ||
|
|
977f49a3a4 | ||
|
|
7155ce797c | ||
|
|
d18866564a | ||
|
|
b39be015b1 | ||
|
|
51c914ea8a | ||
|
|
ac71db0d68 | ||
|
|
4e3ca885a8 | ||
|
|
8c998794b4 | ||
|
|
de070d5bfa | ||
|
|
e1c143db60 | ||
|
|
ad6d6cf9d6 | ||
|
|
01cc0864f2 | ||
|
|
87deadf00e | ||
|
|
3e5ff2871d | ||
|
|
b2f107f83f | ||
|
|
33867f1a25 | ||
|
|
f240036fcd | ||
|
|
fa69ed0fd9 | ||
|
|
95d8e13563 | ||
|
|
63283509cb | ||
|
|
16ca450033 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,3 +7,4 @@
|
||||
/spec/reports/
|
||||
/tmp/
|
||||
log/*.log
|
||||
.byebug_history
|
||||
|
||||
@@ -3,13 +3,12 @@ os:
|
||||
- linux
|
||||
- osx
|
||||
rvm:
|
||||
- 2.0.0
|
||||
- 2.1.7
|
||||
- 2.2.3
|
||||
- 2.2.6
|
||||
- 2.3.3
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/907e95dada362be2a13c
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
on_failure: always # options: [always|never|change] default: always
|
||||
on_start: false # default: false
|
||||
on_start: never # options: [always|never|change] default: always
|
||||
|
||||
36
Changes.md
36
Changes.md
@@ -1,3 +1,39 @@
|
||||
1.1.0
|
||||
-----------
|
||||
- Rails 3 and old Rubies are not supported anymore, sorry rails 3 guys...
|
||||
- Requires Ruby 2.2.2 or newer
|
||||
- Fixed crash when no jobs defined in your cronotab
|
||||
- Some doc updates (thanks to @pachacamac)
|
||||
- Job will schedule on: today if at: time not passed (thanks to @acolyer)
|
||||
- Job log truncating (thanks to @reiz)
|
||||
|
||||
|
||||
1.0.3
|
||||
-----------
|
||||
- "every 1 week" jobs now displaying on Rails 5 as "1 week" not as "7 days"
|
||||
- Liberal gem dependencies to support both Rails 4 and Rails 5
|
||||
|
||||
|
||||
1.0.2
|
||||
-----------
|
||||
- Fix table_name_suffix/prefix issue: https://github.com/plashchynski/crono/issues/33
|
||||
|
||||
|
||||
1.0.1
|
||||
-----------
|
||||
- Fix job saving
|
||||
|
||||
|
||||
1.0.0
|
||||
-----------
|
||||
- Rails 5 support (thanks to @adamico)
|
||||
- Possibility to schedule jobs with arguments (thanks to @preisanalytics)
|
||||
- Added :within option to run only within given time interval (thanks to @lhz)
|
||||
- daemon gem support (thanks to @preisanalytics) https://github.com/plashchynski/crono/pull/37
|
||||
- Support multiple nodes (thanks to @Natural-Intelligence)
|
||||
- Fixed DB connection pool issue (thanks to @ChandravatiSG)
|
||||
|
||||
|
||||
0.9.1
|
||||
-----------
|
||||
- Add ability to define minimal time between job executions to support multiple corno nodes, so two different nodes will not execute the same job
|
||||
|
||||
79
Gemfile.lock
79
Gemfile.lock
@@ -1,63 +1,60 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
crono (1.0.0.pre2)
|
||||
activerecord (~> 4.0)
|
||||
activesupport (~> 4.0)
|
||||
crono (1.1.2)
|
||||
activerecord (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.5)
|
||||
activemodel (= 4.2.5)
|
||||
activesupport (= 4.2.5)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.5)
|
||||
activemodel (5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
activerecord (5.0.0.1)
|
||||
activemodel (= 5.0.0.1)
|
||||
activesupport (= 5.0.0.1)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.0.1)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
arel (6.0.3)
|
||||
builder (3.2.2)
|
||||
byebug (8.2.1)
|
||||
daemons (1.2.3)
|
||||
arel (7.1.4)
|
||||
byebug (9.0.6)
|
||||
concurrent-ruby (1.0.2)
|
||||
daemons (1.2.4)
|
||||
diff-lcs (1.2.5)
|
||||
haml (4.0.7)
|
||||
tilt
|
||||
i18n (0.7.0)
|
||||
json (1.8.3)
|
||||
minitest (5.8.3)
|
||||
rack (1.6.4)
|
||||
minitest (5.9.1)
|
||||
rack (1.6.5)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rake (10.5.0)
|
||||
rspec (3.4.0)
|
||||
rspec-core (~> 3.4.0)
|
||||
rspec-expectations (~> 3.4.0)
|
||||
rspec-mocks (~> 3.4.0)
|
||||
rspec-core (3.4.1)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
rake (11.3.0)
|
||||
rspec (3.5.0)
|
||||
rspec-core (~> 3.5.0)
|
||||
rspec-expectations (~> 3.5.0)
|
||||
rspec-mocks (~> 3.5.0)
|
||||
rspec-core (3.5.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-expectations (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-mocks (3.4.1)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-mocks (3.5.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (3.4.1)
|
||||
sinatra (1.4.6)
|
||||
rack (~> 1.4)
|
||||
rspec-support (~> 3.5.0)
|
||||
rspec-support (3.5.0)
|
||||
sinatra (1.4.7)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
sqlite3 (1.3.11)
|
||||
sqlite3 (1.3.12)
|
||||
thread_safe (0.3.5)
|
||||
tilt (2.0.2)
|
||||
timecop (0.8.0)
|
||||
tilt (2.0.5)
|
||||
timecop (0.8.1)
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
|
||||
@@ -71,11 +68,11 @@ DEPENDENCIES
|
||||
daemons
|
||||
haml
|
||||
rack-test
|
||||
rake (~> 10.0)
|
||||
rspec (~> 3.0)
|
||||
rake (>= 10.0)
|
||||
rspec (>= 3.0)
|
||||
sinatra
|
||||
sqlite3
|
||||
timecop (~> 0.7)
|
||||
timecop (>= 0.7)
|
||||
|
||||
BUNDLED WITH
|
||||
1.11.2
|
||||
1.13.6
|
||||
|
||||
61
README.md
61
README.md
@@ -4,21 +4,20 @@ Crono — Job scheduler for Rails
|
||||
[](https://travis-ci.org/plashchynski/crono)
|
||||
[](https://codeclimate.com/github/plashchynski/crono)
|
||||
[](https://hakiri.io/github/plashchynski/crono/master)
|
||||
[](https://gitter.im/plashchynski/crono?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
Crono is a time-based background job scheduler daemon (just like Cron) for Ruby on Rails.
|
||||
|
||||
|
||||
## The Purpose
|
||||
|
||||
Currently there is no such thing as Ruby Cron for Rails. Well, there's [Whenever](https://github.com/javan/whenever) but it works on top of Unix Cron, so you haven't 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 states to your database using Active Record. You have full control of jobs performing process. It's Ruby, so you can understand and modify it to fit your needs.
|
||||
Currently, there is no such thing as Ruby Cron for Rails. Well, there's [Whenever](https://github.com/javan/whenever) but it works on top of Unix Cron, so you can't manage 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 states to your database using Active Record. You have full control of jobs performing process. It's Ruby, so you can understand and modify it to fit your needs.
|
||||
|
||||

|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
Tested with latest MRI Ruby (2.2, 2.1 and 2.0) and Rails 3.2+
|
||||
Tested with latest MRI Ruby 2.2+, 2.3+, Rails 4.\*, and Rails 5.\*.
|
||||
Other versions are untested but might work fine.
|
||||
|
||||
|
||||
@@ -47,7 +46,7 @@ Now you are ready to move forward to create a job and schedule it.
|
||||
|
||||
#### Create Job
|
||||
|
||||
Crono can use Active Job jobs from `app/jobs/`. The only requirements is that the `perform` method should take no arguments.
|
||||
Crono can use Active Job jobs from `app/jobs/`. The only requirement is that the `perform` method should take no arguments.
|
||||
|
||||
Here's an example of a job:
|
||||
|
||||
@@ -61,7 +60,7 @@ class TestJob < ActiveJob::Base
|
||||
end
|
||||
```
|
||||
|
||||
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`:
|
||||
The ActiveJob jobs are 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`:
|
||||
|
||||
```ruby
|
||||
class TestJob # This is not an Active Job job, but pretty legal Crono job.
|
||||
@@ -77,8 +76,8 @@ Here's an example of a Rake Task within a job:
|
||||
```ruby
|
||||
# config/cronotab.rb
|
||||
require 'rake'
|
||||
# Be sure to change AppName to your application name!
|
||||
AppName::Application.load_tasks
|
||||
|
||||
Rails.app_class.load_tasks
|
||||
|
||||
class Test
|
||||
def perform
|
||||
@@ -111,7 +110,7 @@ Crono.perform(TestJob).every 2.days, at: {hour: 15, min: 30}
|
||||
Crono.perform(TestJob).every 1.week, on: :monday, at: "15:30"
|
||||
```
|
||||
|
||||
You can schedule one job a few times, if you want the job to be performed a few times a day or a week:
|
||||
You can schedule one job a few times if you want the job to be performed a few times a day or a week:
|
||||
|
||||
```ruby
|
||||
Crono.perform(TestJob).every 1.week, on: :monday
|
||||
@@ -131,23 +130,44 @@ serialized using JSON.generate
|
||||
Crono.perform(TestJob, 'some', 'args').every 1.day, at: {hour: 12, min: 15}
|
||||
```
|
||||
|
||||
#### Run daemon
|
||||
You can set some options that not passed to the job but affect how the job will be treated by Crono. For example, you can set to truncate job logs (which stored in the database) to a certain number of records:
|
||||
|
||||
To run Crono daemon, in your Rails project root directory:
|
||||
```ruby
|
||||
Crono.perform(TestJob).with_options(truncate_log: 100).every 1.week, on: :monday
|
||||
```
|
||||
|
||||
#### Run
|
||||
|
||||
To run Crono, in your Rails project root directory:
|
||||
|
||||
bundle exec crono RAILS_ENV=development
|
||||
|
||||
crono usage:
|
||||
```
|
||||
Usage: crono [options] start|stop|restart|run
|
||||
Usage: crono [options] [start|stop|restart|run]
|
||||
-C, --cronotab PATH Path to cronotab file (Default: config/cronotab.rb)
|
||||
-L, --logfile PATH Path to writable logfile (Default: log/crono.log)
|
||||
--piddir PATH Path to piddir (Default: tmp/pids)
|
||||
-N, --process_name name Name of the process (Default: crono)
|
||||
-P, --pidfile PATH Deprecated! use --piddir with --process_name; Path to pidfile (Default: )
|
||||
-D, --piddir PATH Path to piddir (Default: tmp/pids)
|
||||
-N, --process_name NAME Name of the process (Default: crono)
|
||||
-d, --[no-]daemonize Deprecated! Instead use crono [start|stop|restart] without this option; Daemonize process (Default: false)
|
||||
-m, --monitor Start monitor process for a deamon (Default false)
|
||||
-e, --environment ENV Application environment (Default: development)
|
||||
-e, --environment ENV Application environment (Default: development)
|
||||
```
|
||||
|
||||
#### Run as a daemon
|
||||
|
||||
To run Crono as a daemon, please add to your Gemfile:
|
||||
|
||||
```ruby
|
||||
gem 'daemons'
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
bundle install; bundle exec crono start RAILS_ENV=development
|
||||
|
||||
There are "start", "stop", and "restart" commands.
|
||||
|
||||
## Web UI
|
||||
|
||||
@@ -169,6 +189,14 @@ Rails.application.routes.draw do
|
||||
|
||||
Access management and other questions described in the [wiki](https://github.com/plashchynski/crono/wiki/Web-UI).
|
||||
|
||||
#### Known issues
|
||||
|
||||
For Rails 5, in case of the errors:
|
||||
```
|
||||
`require': cannot load such file -- rack/showexceptions (LoadError)
|
||||
```
|
||||
See the related issue [#52](https://github.com/plashchynski/crono/issues/52)
|
||||
|
||||
|
||||
## Capistrano
|
||||
|
||||
@@ -180,6 +208,11 @@ Use the `capistrano-crono` gem ([github](https://github.com/plashchynski/capistr
|
||||
Feel free to create [issues](https://github.com/plashchynski/crono/issues)
|
||||
|
||||
|
||||
## Known Issues
|
||||
|
||||
* Is not compatible with the `protected_attributes` gem. See: [https://github.com/plashchynski/crono/issues/43](https://github.com/plashchynski/crono/issues/43)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Please see [LICENSE](https://github.com/plashchynski/crono/blob/master/LICENSE) for licensing details.
|
||||
|
||||
@@ -19,12 +19,12 @@ Gem::Specification.new do |spec|
|
||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
spec.require_paths = ['lib']
|
||||
|
||||
spec.add_runtime_dependency 'activesupport', '~> 4.0'
|
||||
spec.add_runtime_dependency 'activerecord', '~> 4.0'
|
||||
spec.add_development_dependency 'rake', '~> 10.0'
|
||||
spec.add_runtime_dependency 'activesupport', '>= 4.0'
|
||||
spec.add_runtime_dependency 'activerecord', '>= 4.0'
|
||||
spec.add_development_dependency 'rake', '>= 10.0'
|
||||
spec.add_development_dependency 'bundler', '>= 1.0.0'
|
||||
spec.add_development_dependency 'rspec', '~> 3.0'
|
||||
spec.add_development_dependency 'timecop', '~> 0.7'
|
||||
spec.add_development_dependency 'rspec', '>= 3.0'
|
||||
spec.add_development_dependency 'timecop', '>= 0.7'
|
||||
spec.add_development_dependency 'sqlite3'
|
||||
spec.add_development_dependency 'byebug'
|
||||
spec.add_development_dependency 'sinatra'
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
Thread.abort_on_exception = true
|
||||
|
||||
require 'crono'
|
||||
require 'optparse'
|
||||
|
||||
@@ -27,7 +29,11 @@ module Crono
|
||||
Cronotab.process(File.expand_path(config.cronotab))
|
||||
print_banner
|
||||
|
||||
check_jobs
|
||||
unless have_jobs?
|
||||
logger.error "You have no jobs in you cronotab file #{config.cronotab}"
|
||||
return
|
||||
end
|
||||
|
||||
if config.daemonize
|
||||
start_working_loop_in_daemon
|
||||
else
|
||||
@@ -37,6 +43,10 @@ module Crono
|
||||
|
||||
private
|
||||
|
||||
def have_jobs?
|
||||
Crono.scheduler.jobs.present?
|
||||
end
|
||||
|
||||
def setup_log
|
||||
if config.daemonize
|
||||
self.logfile = config.logfile
|
||||
@@ -83,11 +93,6 @@ module Crono
|
||||
::Rails.application.eager_load!
|
||||
end
|
||||
|
||||
def check_jobs
|
||||
return if Crono.scheduler.jobs.present?
|
||||
logger.error "You have no jobs in you cronotab file #{config.cronotab}"
|
||||
end
|
||||
|
||||
def start_working_loop_in_daemon
|
||||
unless ENV['RAILS_ENV'] == 'test'
|
||||
begin
|
||||
@@ -122,7 +127,7 @@ module Crono
|
||||
|
||||
def parse_options(argv)
|
||||
@argv = OptionParser.new do |opts|
|
||||
opts.banner = "Usage: crono [options] start|stop|restart|run"
|
||||
opts.banner = "Usage: crono [options] [start|stop|restart|run]"
|
||||
|
||||
opts.on("-C", "--cronotab PATH", "Path to cronotab file (Default: #{config.cronotab})") do |cronotab|
|
||||
config.cronotab = cronotab
|
||||
@@ -136,7 +141,7 @@ module Crono
|
||||
config.pidfile = pidfile
|
||||
end
|
||||
|
||||
opts.on("--piddir PATH", "Path to piddir (Default: #{config.piddir})") do |piddir|
|
||||
opts.on("-D", "--piddir PATH", "Path to piddir (Default: #{config.piddir})") do |piddir|
|
||||
config.piddir = piddir
|
||||
end
|
||||
|
||||
|
||||
@@ -6,15 +6,16 @@ module Crono
|
||||
class Job
|
||||
include Logging
|
||||
|
||||
attr_accessor :performer, :period, :job_args, :last_performed_at,
|
||||
attr_accessor :performer, :period, :job_args, :last_performed_at, :job_options,
|
||||
:next_performed_at, :job_log, :job_logger, :healthy, :execution_interval
|
||||
|
||||
def initialize(performer, period, job_args)
|
||||
def initialize(performer, period, job_args, job_options = nil)
|
||||
self.execution_interval = 0.minutes
|
||||
self.performer, self.period = performer, period
|
||||
self.job_args = JSON.generate(job_args)
|
||||
self.job_log = StringIO.new
|
||||
self.job_logger = Logger.new(job_log)
|
||||
self.job_options = job_options || {}
|
||||
self.next_performed_at = period.next
|
||||
@semaphore = Mutex.new
|
||||
end
|
||||
@@ -61,11 +62,17 @@ module Crono
|
||||
job_log.truncate(job_log.rewind)
|
||||
end
|
||||
|
||||
def truncate_log(log)
|
||||
return log.lines.last(job_options[:truncate_log]).join if job_options[:truncate_log]
|
||||
return log
|
||||
end
|
||||
|
||||
def update_model
|
||||
saved_log = model.reload.log || ''
|
||||
log_to_save = saved_log + job_log.string
|
||||
log_to_save = truncate_log(log_to_save)
|
||||
model.update(last_performed_at: last_performed_at, log: log_to_save,
|
||||
healthy: healthy, args: job_args)
|
||||
healthy: healthy)
|
||||
end
|
||||
|
||||
def perform_job
|
||||
@@ -98,7 +105,7 @@ module Crono
|
||||
|
||||
def log(message, severity = Logger::INFO)
|
||||
@semaphore.synchronize do
|
||||
logger.log severity, message
|
||||
logger.log(severity, message) if logger
|
||||
job_logger.log severity, message
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,7 +3,6 @@ require 'active_record'
|
||||
module Crono
|
||||
# Crono::CronoJob is a ActiveRecord model to store job state
|
||||
class CronoJob < ActiveRecord::Base
|
||||
self.table_name = 'crono_jobs'
|
||||
validates :job_id, presence: true, uniqueness: true
|
||||
|
||||
def self.outdated
|
||||
|
||||
@@ -8,7 +8,7 @@ module Crono
|
||||
end
|
||||
|
||||
def every(period, *args)
|
||||
@job = Job.new(@performer, Period.new(period, *args), @job_args)
|
||||
@job = Job.new(@performer, Period.new(period, *args), @job_args, @options)
|
||||
@scheduler.add_job(@job)
|
||||
self
|
||||
end
|
||||
@@ -17,6 +17,11 @@ module Crono
|
||||
@job.execution_interval = execution_interval if @job
|
||||
self
|
||||
end
|
||||
|
||||
def with_options(options)
|
||||
@options = options
|
||||
self
|
||||
end
|
||||
end
|
||||
|
||||
def self.perform(performer, *job_args)
|
||||
|
||||
@@ -23,6 +23,7 @@ module Crono
|
||||
return initial_next unless since
|
||||
@next = @period.since(since)
|
||||
end
|
||||
|
||||
@next = @next.beginning_of_week.advance(days: @on) if @on
|
||||
@next = @next.change(time_atts)
|
||||
return @next if @next.future?
|
||||
@@ -48,6 +49,7 @@ module Crono
|
||||
def initial_day
|
||||
return Time.now unless @on
|
||||
day = Time.now.beginning_of_week.advance(days: @on)
|
||||
day = day.change(time_atts)
|
||||
return day if day.future?
|
||||
@period.from_now.beginning_of_week.advance(days: @on)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Crono
|
||||
VERSION = '1.0.0.pre2'
|
||||
VERSION = '1.1.2'
|
||||
end
|
||||
|
||||
@@ -2,10 +2,9 @@ class CreateCronoJobs < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :crono_jobs do |t|
|
||||
t.string :job_id, null: false
|
||||
t.text :log
|
||||
t.text :log, limit: 1073741823 # LONGTEXT for MySQL
|
||||
t.datetime :last_performed_at
|
||||
t.boolean :healthy
|
||||
t.text :args
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :crono_jobs, [:job_id], unique: true
|
||||
|
||||
@@ -7,6 +7,7 @@ describe Crono::CLI do
|
||||
describe '#run' do
|
||||
it 'should initialize rails with #load_rails and start working loop' do
|
||||
expect(cli).to receive(:load_rails)
|
||||
expect(cli).to receive(:have_jobs?).and_return(true)
|
||||
expect(cli).to receive(:start_working_loop)
|
||||
expect(cli).to receive(:parse_options)
|
||||
expect(cli).to receive(:parse_command)
|
||||
@@ -14,12 +15,13 @@ describe Crono::CLI do
|
||||
expect(Crono::Cronotab).to receive(:process)
|
||||
cli.run
|
||||
end
|
||||
context 'should run as daemon' do
|
||||
|
||||
before {cli.config.daemonize = true}
|
||||
context 'should run as daemon' do
|
||||
before { cli.config.daemonize = true }
|
||||
|
||||
it 'should initialize rails with #load_rails and start working loop' do
|
||||
expect(cli).to receive(:load_rails)
|
||||
expect(cli).to receive(:have_jobs?).and_return(true)
|
||||
expect(cli).to receive(:start_working_loop_in_daemon)
|
||||
expect(cli).to receive(:parse_options)
|
||||
expect(cli).to receive(:parse_command)
|
||||
|
||||
@@ -105,16 +105,31 @@ describe Crono::Job do
|
||||
@crono_job = Crono::CronoJob.find_by(job_id: job.job_id)
|
||||
expect(@crono_job.last_performed_at.utc.to_s).to be_eql job.last_performed_at.utc.to_s
|
||||
expect(@crono_job.healthy).to be true
|
||||
expect(@crono_job.args).to eq '[{"some":"data"}]'
|
||||
end
|
||||
|
||||
it 'should save and truncate job log' do
|
||||
it 'should save log' do
|
||||
message = 'test message'
|
||||
job.send(:log, message)
|
||||
job.save
|
||||
expect(job.send(:model).reload.log).to include message
|
||||
expect(job.job_log.string).to be_empty
|
||||
end
|
||||
|
||||
it 'should not truncate log if not specified' do
|
||||
log = (1..100).map {|n| "line #{n}" }.join("\n")
|
||||
job = Crono::Job.new(TestJob, period, [])
|
||||
job.send(:log, log)
|
||||
job.save
|
||||
expect(job.send(:model).reload.log.lines.size).to be >= log.lines.size
|
||||
end
|
||||
|
||||
it 'should truncate log if specified' do
|
||||
log = (1..100).map {|n| "line #{n}" }.join("\n")
|
||||
job = Crono::Job.new(TestJob, period, [], truncate_log: 50)
|
||||
job.send(:log, log)
|
||||
job.save
|
||||
expect(job.send(:model).reload.log.lines.size).to be 50
|
||||
end
|
||||
end
|
||||
|
||||
describe '#load' do
|
||||
@@ -133,6 +148,7 @@ describe Crono::Job do
|
||||
describe '#log' do
|
||||
it 'should write log messages to both common and job log' do
|
||||
message = 'Test message'
|
||||
job.logfile = "/dev/null"
|
||||
expect(job.logger).to receive(:log).with(Logger::INFO, message)
|
||||
expect(job.job_logger).to receive(:log).with(Logger::INFO, message)
|
||||
job.send(:log, message)
|
||||
|
||||
@@ -20,8 +20,14 @@ describe Crono::PerformerProxy do
|
||||
end
|
||||
|
||||
it 'should add job with args to schedule' do
|
||||
expect(Crono::Job).to receive(:new).with(TestJob, kind_of(Crono::Period), [:some, {some: 'data'}])
|
||||
expect(Crono::Job).to receive(:new).with(TestJob, kind_of(Crono::Period), [:some, {some: 'data'}], nil)
|
||||
allow(Crono.scheduler).to receive(:add_job)
|
||||
Crono.perform(TestJob, :some, {some: 'data'}).every(2.days, at: '15:30')
|
||||
end
|
||||
|
||||
it 'should add job with options to schedule' do
|
||||
expect(Crono::Job).to receive(:new).with(TestJob, kind_of(Crono::Period), [], {some_option: true})
|
||||
allow(Crono.scheduler).to receive(:add_job)
|
||||
Crono.perform(TestJob).with_options(some_option: true).every(2.days, at: '15:30')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,12 @@ describe Crono::Period do
|
||||
describe '#description' do
|
||||
it 'should return period description' do
|
||||
@period = Crono::Period.new(1.week, on: :monday, at: '15:20')
|
||||
expect(@period.description).to be_eql('every 7 days at 15:20 on Monday')
|
||||
expected_description = if ActiveSupport::VERSION::MAJOR >= 5
|
||||
'every 1 week at 15:20 on Monday'
|
||||
else
|
||||
'every 7 days at 15:20 on Monday'
|
||||
end
|
||||
expect(@period.description).to be_eql(expected_description)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -44,6 +49,16 @@ describe Crono::Period do
|
||||
expect(@period.next).to be_eql(tuesday)
|
||||
end
|
||||
end
|
||||
|
||||
it 'should return today on the first run if not too late' do
|
||||
@period = Crono::Period.new(1.week, on: :sunday, at: '22:00')
|
||||
Timecop.freeze(Time.now.beginning_of_week.advance(days: 6)
|
||||
.change(hour: 21, min: 0)) do
|
||||
expect(@period.next).to be_eql(
|
||||
Time.now.beginning_of_week.advance(days: 6).change(hour: 22, min: 0)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'in daily basis' do
|
||||
@@ -61,14 +76,14 @@ describe Crono::Period do
|
||||
time = 10.minutes.ago
|
||||
at = [time.hour, time.min].join(':')
|
||||
@period = Crono::Period.new(2.days, at: at)
|
||||
expect(@period.next).to be_eql(2.days.from_now.change(hour: time.hour, min: time.min))
|
||||
expect(@period.next.to_s).to be_eql(2.days.from_now.change(hour: time.hour, min: time.min).to_s)
|
||||
end
|
||||
|
||||
it "should set time to 'at' time as a hash" do
|
||||
time = 10.minutes.ago
|
||||
at = { hour: time.hour, min: time.min }
|
||||
@period = Crono::Period.new(2.days, at: at)
|
||||
expect(@period.next).to be_eql(2.days.from_now.change(at))
|
||||
expect(@period.next.to_s).to be_eql(2.days.from_now.change(at).to_s)
|
||||
end
|
||||
|
||||
it "should raise error when 'at' is wrong" do
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
%a{ href: url('/') }
|
||||
%i.mdi-navigation-chevron-left
|
||||
Back to Home
|
||||
%h4 "#{@job.job_id}" Log:
|
||||
%h4 "#{@job.job_id}" Last log:
|
||||
|
||||
%main.container.blue-grey.lighten-4.grey-text.text-darken-4
|
||||
- if @job.healthy == false
|
||||
|
||||
Reference in New Issue
Block a user