crono 0.5.2 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d44592e0e575b43cbfbc08ae70a3ba2b48fe4c56
4
- data.tar.gz: f7155bff1058414b3772e008a497e5932e1117f1
3
+ metadata.gz: 64a9cf0a8dfbbb07d720a55e4e8d00fdcf38d792
4
+ data.tar.gz: b17baffc9f7f8c8c20ea747ff95003cffc2c0593
5
5
  SHA512:
6
- metadata.gz: cc7a404b38391f25500e7ac662e06426d7bd9129c8911bc909a82262f4d231a824852b33a30f4a52ae58503c7e6ec7eacddd27a3379d1292de0bc61ab5cb5dd9
7
- data.tar.gz: 6c101c91fc475b626baacd442725cdd7bd55b86b6e77c5d3cf3bbfa312062fa0931215ba683cb593c7ec9371972657d0968144f37e9a355f89c95f4a4adbbe40
6
+ metadata.gz: e660b9fc13581744848bfa9efcd70d2350c3f97741118f0b29c15b6c544c2f164fab47324d1bd937ecccf0d2e8426bf344d4b521f9e41236da00b8cb19a38d63
7
+ data.tar.gz: b85e7a57c38a82db19827206dc93bc30033107f21b21857d9ef460472b437f54360f761891b268d7549fd002b5e92363e210a950d2a1c434b87b9c326543ae3d
data/Changes.md CHANGED
@@ -4,11 +4,16 @@
4
4
  - Initial release!
5
5
 
6
6
  0.5.1
7
- ———————————
7
+ -----------
8
8
 
9
9
  - Added -e/--environment ENV option to set the daemon rails environment.
10
10
 
11
11
  0.5.2
12
- ———————————
12
+ -----------
13
+
14
+ - Fix: Scheduled time now related to the last performing time.
15
+
16
+ 0.6.1
17
+ -----------
13
18
 
14
- - Fix: Scheduled time now related to the last performing time.
19
+ - Persist job state to your database.
@@ -1,8 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- crono (0.5.1)
4
+ crono (0.6.1)
5
5
  activejob (~> 4.0)
6
+ activerecord (~> 4.0)
6
7
  activesupport (~> 4.0)
7
8
 
8
9
  GEM
@@ -11,12 +12,21 @@ GEM
11
12
  activejob (4.2.0)
12
13
  activesupport (= 4.2.0)
13
14
  globalid (>= 0.3.0)
15
+ activemodel (4.2.0)
16
+ activesupport (= 4.2.0)
17
+ builder (~> 3.1)
18
+ activerecord (4.2.0)
19
+ activemodel (= 4.2.0)
20
+ activesupport (= 4.2.0)
21
+ arel (~> 6.0)
14
22
  activesupport (4.2.0)
15
23
  i18n (~> 0.7)
16
24
  json (~> 1.7, >= 1.7.7)
17
25
  minitest (~> 5.1)
18
26
  thread_safe (~> 0.3, >= 0.3.4)
19
27
  tzinfo (~> 1.1)
28
+ arel (6.0.0)
29
+ builder (3.2.2)
20
30
  diff-lcs (1.2.5)
21
31
  globalid (0.3.3)
22
32
  activesupport (>= 4.1.0)
@@ -37,6 +47,7 @@ GEM
37
47
  diff-lcs (>= 1.2.0, < 2.0)
38
48
  rspec-support (~> 3.2.0)
39
49
  rspec-support (3.2.2)
50
+ sqlite3 (1.3.10)
40
51
  thread_safe (0.3.4)
41
52
  timecop (0.7.3)
42
53
  tzinfo (1.2.2)
@@ -50,4 +61,5 @@ DEPENDENCIES
50
61
  crono!
51
62
  rake (~> 10.0)
52
63
  rspec (~> 3.0)
64
+ sqlite3
53
65
  timecop (~> 0.7)
data/README.md CHANGED
@@ -11,7 +11,7 @@ Crono is a time-based background job scheduler daemon (just like Cron) for Ruby
11
11
 
12
12
  ## The Idea
13
13
 
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. You have total control of jobs performing process. You have the code in Ruby, so you can understand and modify it to fit your needs.
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
16
 
17
17
  ## Requirements
@@ -31,7 +31,11 @@ After you install Crono, you can run the generator:
31
31
 
32
32
  rails generate crono:install
33
33
 
34
- It will create a configuration file `config/cronotab.rb`
34
+ It will create a configuration file `config/cronotab.rb` and migration
35
+ Run the migration:
36
+
37
+ rake db:migrate
38
+
35
39
  Now you are ready to move forward to create a job and schedule it.
36
40
 
37
41
 
data/bin/crono CHANGED
@@ -5,8 +5,7 @@ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
5
5
  require "crono/cli"
6
6
 
7
7
  begin
8
- cli = Crono::CLI.instance
9
- cli.run
8
+ Crono::CLI.instance.run
10
9
  rescue => e
11
10
  raise e if $DEBUG
12
11
  STDERR.puts e.message
@@ -15,10 +15,12 @@ Gem::Specification.new do |s|
15
15
 
16
16
  s.add_runtime_dependency "activejob", "~> 4.0"
17
17
  s.add_runtime_dependency "activesupport", "~> 4.0"
18
+ s.add_runtime_dependency "activerecord", "~> 4.0"
18
19
  s.add_development_dependency "rake", "~> 10.0"
19
20
  s.add_development_dependency "bundler", ">= 1.0.0"
20
21
  s.add_development_dependency "rspec", "~> 3.0"
21
22
  s.add_development_dependency "timecop", "~> 0.7"
23
+ s.add_development_dependency "sqlite3"
22
24
 
23
25
  s.files = `git ls-files`.split("\n")
24
26
  s.executables = `git ls-files`.split("\n").map{|f| f =~ /^bin\/(.*)/ ? $1 : nil}.compact
@@ -1,6 +1,6 @@
1
1
  check process crono_myapp
2
2
  with pidfile /path/to/crono.pid
3
- start program = "bundle exec crono" with timeout 30 seconds
3
+ start program = "bundle exec crono -e production" with timeout 30 seconds
4
4
  stop program = "kill -s TERM `cat /path/to/crono.pid`" with timeout 30 seconds
5
5
  if totalmem is greater than 500 MB for 2 cycles then restart
6
6
  group myapp_crono
@@ -3,8 +3,10 @@ end
3
3
 
4
4
  require "active_support/all"
5
5
  require "crono/version.rb"
6
+ require "crono/logging.rb"
6
7
  require "crono/period.rb"
7
8
  require "crono/job.rb"
8
- require "crono/schedule.rb"
9
+ require "crono/scheduler.rb"
9
10
  require "crono/config.rb"
10
11
  require "crono/performer_proxy.rb"
12
+ require "crono/orm/active_record/crono_job.rb"
@@ -2,25 +2,34 @@ require 'crono'
2
2
  require 'optparse'
3
3
 
4
4
  module Crono
5
- mattr_accessor :schedule
6
- mattr_accessor :logger
5
+ mattr_accessor :scheduler
7
6
 
8
7
  class CLI
9
8
  include Singleton
9
+ include Logging
10
+
10
11
  attr_accessor :config
11
12
 
12
13
  def initialize
13
14
  self.config = Config.new
14
- Crono.schedule = Schedule.new
15
+ Crono.scheduler = Scheduler.new
15
16
  end
16
17
 
17
18
  def run
18
19
  parse_options(ARGV)
19
- init_logger
20
- daemonize if config.daemonize
20
+
21
+ if config.daemonize
22
+ set_log_to(config.logfile)
23
+ daemonize
24
+ else
25
+ set_log_to(STDOUT)
26
+ end
27
+
21
28
  write_pid
22
29
  load_rails
23
30
  print_banner
31
+
32
+ check_jobs
24
33
  start_working_loop
25
34
  end
26
35
 
@@ -32,6 +41,7 @@ module Crono
32
41
  File.open(config.logfile, 'ab') { |f| io.reopen(f) }
33
42
  io.sync = true
34
43
  end
44
+
35
45
  $stdin.reopen("/dev/null")
36
46
  end
37
47
 
@@ -40,14 +50,14 @@ module Crono
40
50
  File.write(pidfile, ::Process.pid)
41
51
  end
42
52
 
43
- def init_logger
44
- logfile = config.daemonize ? config.logfile : STDOUT
45
- Crono.logger = Logger.new(logfile)
46
- end
47
-
48
53
  def print_banner
49
- Crono.logger.info "Loading Crono #{Crono::VERSION}"
50
- Crono.logger.info "Running in #{RUBY_DESCRIPTION}"
54
+ logger.info "Loading Crono #{Crono::VERSION}"
55
+ logger.info "Running in #{RUBY_DESCRIPTION}"
56
+
57
+ logger.info "Jobs:"
58
+ Crono.scheduler.jobs.each do |job|
59
+ logger.info job.description
60
+ end
51
61
  end
52
62
 
53
63
  def load_rails
@@ -58,9 +68,15 @@ module Crono
58
68
  require File.expand_path(config.cronotab)
59
69
  end
60
70
 
71
+ def check_jobs
72
+ if Crono.scheduler.jobs.empty?
73
+ logger.error "You have no jobs defined in you cronotab file #{config.cronotab}"
74
+ end
75
+ end
76
+
61
77
  def start_working_loop
62
- loop do
63
- job = Crono.schedule.next
78
+ Thread.abort_on_exception = true
79
+ while job = Crono.scheduler.next do
64
80
  sleep(job.next - Time.now)
65
81
  job.perform
66
82
  end
@@ -1,5 +1,7 @@
1
1
  module Crono
2
2
  class Job
3
+ include Logging
4
+
3
5
  attr_accessor :performer
4
6
  attr_accessor :period
5
7
  attr_accessor :last_performed_at
@@ -9,13 +11,39 @@ module Crono
9
11
  end
10
12
 
11
13
  def next
12
- period.next(since: last_performed_at)
14
+ next_time = period.next(since: last_performed_at)
15
+ next_time.past? ? period.next : next_time
16
+ end
17
+
18
+ def description
19
+ "Perform #{performer} #{period.description}"
20
+ end
21
+
22
+ def job_id
23
+ description
13
24
  end
14
25
 
15
26
  def perform
16
- Crono.logger.info "Perform #{performer}"
27
+ logger.info "Perform #{performer}"
17
28
  self.last_performed_at = Time.now
18
- Thread.new { performer.new.perform }
29
+ save
30
+ Thread.new do
31
+ performer.new.perform
32
+ logger.info "Finished #{performer} in %.2f seconds" % (Time.now - last_performed_at)
33
+ end
34
+ end
35
+
36
+ def save
37
+ model.update(last_performed_at: last_performed_at)
38
+ end
39
+
40
+ def load
41
+ self.last_performed_at = model.last_performed_at
42
+ end
43
+
44
+ private
45
+ def model
46
+ @model ||= Crono::CronoJob.find_or_create_by(job_id: job_id)
19
47
  end
20
48
  end
21
49
  end
@@ -0,0 +1,13 @@
1
+ module Crono
2
+ mattr_accessor :logger
3
+
4
+ module Logging
5
+ def set_log_to(logfile)
6
+ Crono.logger = Logger.new(logfile)
7
+ end
8
+
9
+ def logger
10
+ Crono.logger
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'active_record'
2
+
3
+ module Crono
4
+ class CronoJob < ActiveRecord::Base
5
+ self.table_name = "crono_jobs"
6
+ validates :job_id, presence: true, uniqueness: true
7
+ end
8
+ end
@@ -1,17 +1,17 @@
1
1
  module Crono
2
2
  class PerformerProxy
3
- def initialize(performer, schedule)
3
+ def initialize(performer, scheduler)
4
4
  @performer = performer
5
- @schedule = schedule
5
+ @scheduler = scheduler
6
6
  end
7
7
 
8
8
  def every(period, *args)
9
9
  job = Job.new(@performer, Period.new(period, *args))
10
- @schedule.add(job)
10
+ @scheduler.add_job(job)
11
11
  end
12
12
  end
13
13
 
14
14
  def self.perform(performer)
15
- PerformerProxy.new(performer, Crono.schedule)
15
+ PerformerProxy.new(performer, Crono.scheduler)
16
16
  end
17
17
  end
@@ -10,6 +10,12 @@ module Crono
10
10
  @period.since(since).change({hour: @at_hour, min: @at_min}.compact)
11
11
  end
12
12
 
13
+ def description
14
+ desc = "every #{@period.inspect}"
15
+ desc += " at %.2i:%.2i" % [@at_hour, @at_min] if @at_hour && @at_min
16
+ desc
17
+ end
18
+
13
19
  def parse_at(at)
14
20
  case at
15
21
  when String
@@ -0,0 +1,23 @@
1
+ module Crono
2
+ class Scheduler
3
+ attr_accessor :jobs
4
+
5
+ def initialize
6
+ self.jobs = []
7
+ end
8
+
9
+ def add_job(job)
10
+ job.load
11
+ jobs << job
12
+ end
13
+
14
+ def next
15
+ queue.first
16
+ end
17
+
18
+ private
19
+ def queue
20
+ jobs.sort_by(&:next)
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Crono
2
- VERSION = "0.5.2"
2
+ VERSION = '0.6.1'
3
3
  end
@@ -1,12 +1,26 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+ require 'rails/generators/active_record'
4
+
1
5
  module Crono
2
6
  module Generators
3
7
  class InstallGenerator < ::Rails::Generators::Base
8
+ include Rails::Generators::Migration
9
+
10
+ def self.next_migration_number(path)
11
+ ActiveRecord::Generators::Base.next_migration_number(path)
12
+ end
13
+
4
14
  desc "Installs crono and generates the necessary configuration files"
5
15
  source_root File.expand_path("../templates", __FILE__)
6
16
 
7
17
  def copy_config
8
18
  template 'cronotab.rb.erb', 'config/cronotab.rb'
9
19
  end
20
+
21
+ def create_migrations
22
+ migration_template 'migrations/create_crono_jobs.rb', 'db/migrate/create_crono_jobs.rb'
23
+ end
10
24
  end
11
25
  end
12
26
  end
@@ -0,0 +1,15 @@
1
+ class CreateCronoJobs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :crono_jobs do |t|
4
+ t.string :job_id, null: false
5
+ t.text :log
6
+ t.datetime :last_performed_at
7
+ t.timestamps
8
+ end
9
+ add_index :crono_jobs, [:job_id], unique: true
10
+ end
11
+
12
+ def self.down
13
+ drop_table :crono_jobs
14
+ end
15
+ end
@@ -18,5 +18,45 @@ describe Crono::Job do
18
18
  thread = job.perform.join
19
19
  expect(thread).to be_stop
20
20
  end
21
+
22
+ it "should call Job#save after run" do
23
+ expect(job).to receive(:save)
24
+ job.perform.join
25
+ job.send(:model).destroy
26
+ end
27
+ end
28
+
29
+ describe "#description" do
30
+ it "should return job identificator" do
31
+ expect(job.description).to be_eql("Perform TestJob every 2 days")
32
+ end
33
+ end
34
+
35
+ describe "#save" do
36
+ it "should save new job to DB" do
37
+ expect(Crono::CronoJob.where(job_id: job.job_id)).to_not exist
38
+ job.save
39
+ expect(Crono::CronoJob.where(job_id: job.job_id)).to exist
40
+ end
41
+
42
+ it "should update saved job" do
43
+ job.last_performed_at = Time.now
44
+ job.save
45
+ @crono_job = Crono::CronoJob.find_by(job_id: job.job_id)
46
+ expect(@crono_job.last_performed_at).to be_eql(job.last_performed_at)
47
+ end
48
+ end
49
+
50
+ describe "#load" do
51
+ before do
52
+ @saved_last_performed_at = job.last_performed_at = Time.now
53
+ job.save
54
+ end
55
+
56
+ it "should load info from DB" do
57
+ @job = Crono::Job.new(TestJob, period)
58
+ @job.load
59
+ expect(@job.last_performed_at).to be_eql @saved_last_performed_at
60
+ end
21
61
  end
22
62
  end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Crono::CronoJob do
4
+ let(:valid_attrs) do
5
+ {
6
+ job_id: "Perform TestJob every 3 days"
7
+ }
8
+ end
9
+
10
+ it "should validate presence of job_id" do
11
+ @crono_job = Crono::CronoJob.new()
12
+ expect(@crono_job).not_to be_valid
13
+ expect(@crono_job.errors.added?(:job_id, :blank)).to be true
14
+ end
15
+
16
+ it "should validate uniqueness of job_id" do
17
+ Crono::CronoJob.create!(job_id: "TestJob every 2 days")
18
+ @crono_job = Crono::CronoJob.create(job_id: "TestJob every 2 days")
19
+ expect(@crono_job).not_to be_valid
20
+ expect(@crono_job.errors.added?(:job_id, :taken)).to be true
21
+ end
22
+
23
+ it "should save job_id to DB" do
24
+ Crono::CronoJob.create!(valid_attrs)
25
+ @crono_job = Crono::CronoJob.find_by(job_id: valid_attrs[:job_id])
26
+ expect(@crono_job).to be_present
27
+ end
28
+ end
@@ -6,7 +6,7 @@ end
6
6
 
7
7
  describe Crono::PerformerProxy do
8
8
  it "should add job to schedule" do
9
- expect(Crono.schedule).to receive(:add).with(kind_of(Crono::Job))
9
+ expect(Crono.scheduler).to receive(:add_job).with(kind_of(Crono::Job))
10
10
  Crono.perform(TestJob).every(2.days, at: "15:30")
11
11
  end
12
12
  end
@@ -7,6 +7,13 @@ describe Crono::Period do
7
7
  end
8
8
  end
9
9
 
10
+ describe "#description" do
11
+ it "should return period description" do
12
+ @period = Crono::Period.new(2.day, at: "15:20")
13
+ expect(@period.description).to be_eql("every 2 days at 15:20")
14
+ end
15
+ end
16
+
10
17
  describe "#next" do
11
18
  context "in daily basis" do
12
19
  it "should return the time 2 days from now" do
@@ -4,24 +4,32 @@ class TestJob
4
4
  def perform;end
5
5
  end
6
6
 
7
- describe Crono::Schedule do
7
+ describe Crono::Scheduler do
8
8
  before(:each) do
9
- @schedule = Crono::Schedule.new
9
+ @scheduler = Crono::Scheduler.new
10
10
  @jobs = [
11
11
  Crono::Period.new(3.day, at: "18:55"),
12
12
  Crono::Period.new(1.day, at: "15:30"),
13
13
  Crono::Period.new(7.day, at: "06:05")
14
14
  ].map { |period| Crono::Job.new(TestJob, period) }
15
- @schedule.schedule = @jobs
15
+ @scheduler.jobs = @jobs
16
+ end
17
+
18
+ describe "#add_job" do
19
+ it "should call Job#load on Job" do
20
+ @job = Crono::Job.new(TestJob, Crono::Period.new(10.day, at: "04:05"))
21
+ expect(@job).to receive(:load)
22
+ @scheduler.add_job(@job)
23
+ end
16
24
  end
17
25
 
18
26
  describe "#next" do
19
27
  it "should return next job in schedule" do
20
- expect(@schedule.next).to be @jobs[1]
28
+ expect(@scheduler.next).to be @jobs[1]
21
29
  end
22
30
 
23
31
  it "should return next based on last" do
24
- expect(@schedule.next)
32
+ expect(@scheduler.next)
25
33
  end
26
34
  end
27
35
  end
@@ -3,6 +3,11 @@ Bundler.setup
3
3
 
4
4
  require 'timecop'
5
5
  require 'crono'
6
+ require 'generators/crono/install/templates/migrations/create_crono_jobs.rb'
7
+
8
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
9
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
10
+ CreateCronoJobs.up
6
11
 
7
12
  RSpec.configure do |config|
8
13
  end
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.5.2
4
+ version: 0.6.1
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-04 00:00:00.000000000 Z
11
+ date: 2015-03-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activerecord
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rake
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +108,20 @@ dependencies:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: '0.7'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sqlite3
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  description: Job scheduler for Rails
98
126
  email:
99
127
  - plashchynski@gmail.com
@@ -120,18 +148,22 @@ files:
120
148
  - lib/crono/cli.rb
121
149
  - lib/crono/config.rb
122
150
  - lib/crono/job.rb
151
+ - lib/crono/logging.rb
152
+ - lib/crono/orm/active_record/crono_job.rb
123
153
  - lib/crono/performer_proxy.rb
124
154
  - lib/crono/period.rb
125
- - lib/crono/schedule.rb
155
+ - lib/crono/scheduler.rb
126
156
  - lib/crono/version.rb
127
157
  - lib/generators/crono/install/install_generator.rb
128
158
  - lib/generators/crono/install/templates/cronotab.rb.erb
159
+ - lib/generators/crono/install/templates/migrations/create_crono_jobs.rb
129
160
  - spec/cli_spec.rb
130
161
  - spec/config_spec.rb
131
162
  - spec/job_spec.rb
163
+ - spec/orm/active_record/crono_job_spec.rb
132
164
  - spec/performer_proxy_spec.rb
133
165
  - spec/period_spec.rb
134
- - spec/schedule_spec.rb
166
+ - spec/scheduler_spec.rb
135
167
  - spec/spec_helper.rb
136
168
  homepage: https://github.com/plashchynski/crono
137
169
  licenses:
@@ -1,22 +0,0 @@
1
- module Crono
2
- class Schedule
3
- attr_accessor :schedule
4
-
5
- def initialize
6
- self.schedule = []
7
- end
8
-
9
- def add(job)
10
- schedule << job
11
- end
12
-
13
- def next
14
- queue.first
15
- end
16
-
17
- private
18
- def queue
19
- schedule.sort { |a,b| a.next <=> b.next }
20
- end
21
- end
22
- end