mirror of
https://github.com/plashchynski/crono.git
synced 2026-01-14 14:23:27 +01:00
Compare commits
21 Commits
v1.0.0.pre
...
v1.0.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7155ce797c | ||
|
|
d18866564a | ||
|
|
b39be015b1 | ||
|
|
51c914ea8a | ||
|
|
ac71db0d68 | ||
|
|
4e3ca885a8 | ||
|
|
8c998794b4 | ||
|
|
de070d5bfa | ||
|
|
e1c143db60 | ||
|
|
ad6d6cf9d6 | ||
|
|
01cc0864f2 | ||
|
|
87deadf00e | ||
|
|
3e5ff2871d | ||
|
|
b2f107f83f | ||
|
|
33867f1a25 | ||
|
|
f240036fcd | ||
|
|
fa69ed0fd9 | ||
|
|
95d8e13563 | ||
|
|
63283509cb | ||
|
|
16ca450033 | ||
|
|
acbfea2308 |
@@ -6,10 +6,15 @@ rvm:
|
||||
- 2.0.0
|
||||
- 2.1.7
|
||||
- 2.2.3
|
||||
- 2.3.1
|
||||
matrix:
|
||||
exclude:
|
||||
- rvm: 2.3.1
|
||||
os: osx
|
||||
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
|
||||
|
||||
26
Changes.md
26
Changes.md
@@ -1,3 +1,29 @@
|
||||
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
|
||||
|
||||
51
Gemfile.lock
51
Gemfile.lock
@@ -1,47 +1,44 @@
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
crono (1.0.0.pre)
|
||||
activerecord (~> 4.0)
|
||||
activesupport (~> 4.0)
|
||||
crono (1.0.3)
|
||||
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)
|
||||
activesupport (= 5.0.0)
|
||||
activerecord (5.0.0)
|
||||
activemodel (= 5.0.0)
|
||||
activesupport (= 5.0.0)
|
||||
arel (~> 7.0)
|
||||
activesupport (5.0.0)
|
||||
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)
|
||||
arel (7.0.0)
|
||||
byebug (9.0.5)
|
||||
concurrent-ruby (1.0.2)
|
||||
daemons (1.2.3)
|
||||
diff-lcs (1.2.5)
|
||||
haml (4.0.7)
|
||||
tilt
|
||||
i18n (0.7.0)
|
||||
json (1.8.3)
|
||||
minitest (5.8.3)
|
||||
minitest (5.9.0)
|
||||
rack (1.6.4)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rake (10.5.0)
|
||||
rake (11.2.2)
|
||||
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-core (3.4.4)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-expectations (3.4.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
@@ -50,14 +47,14 @@ GEM
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.4.0)
|
||||
rspec-support (3.4.1)
|
||||
sinatra (1.4.6)
|
||||
rack (~> 1.4)
|
||||
sinatra (1.4.7)
|
||||
rack (~> 1.5)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (>= 1.3, < 3)
|
||||
sqlite3 (1.3.11)
|
||||
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
|
||||
|
||||
42
README.md
42
README.md
@@ -11,14 +11,14 @@ Crono is a time-based background job scheduler daemon (just like Cron) for Ruby
|
||||
|
||||
## 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.3, 2.2, 2.1 and 2.0) and Rails 3.2+ (including Rails 5).
|
||||
Other versions are untested but might work fine.
|
||||
|
||||
|
||||
@@ -47,7 +47,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 +61,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.
|
||||
@@ -111,7 +111,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 +131,38 @@ serialized using JSON.generate
|
||||
Crono.perform(TestJob, 'some', 'args').every 1.day, at: {hour: 12, min: 15}
|
||||
```
|
||||
|
||||
#### Run daemon
|
||||
#### Run
|
||||
|
||||
To run Crono daemon, in your Rails project root directory:
|
||||
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
|
||||
|
||||
@@ -180,6 +195,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'
|
||||
|
||||
@@ -122,7 +124,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 +138,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
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ module Crono
|
||||
saved_log = model.reload.log || ''
|
||||
log_to_save = saved_log + job_log.string
|
||||
model.update(last_performed_at: last_performed_at, log: log_to_save,
|
||||
healthy: healthy, args: job_args)
|
||||
healthy: healthy)
|
||||
end
|
||||
|
||||
def perform_job
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Crono
|
||||
VERSION = '1.0.0.pre'
|
||||
VERSION = '1.0.3'
|
||||
end
|
||||
|
||||
@@ -5,7 +5,6 @@ class CreateCronoJobs < ActiveRecord::Migration
|
||||
t.text :log
|
||||
t.datetime :last_performed_at
|
||||
t.boolean :healthy
|
||||
t.text :args
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :crono_jobs, [:job_id], unique: true
|
||||
|
||||
@@ -105,7 +105,6 @@ 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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -61,14 +66,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
|
||||
|
||||
Reference in New Issue
Block a user