Class: Philiprehberger::CronKit::Scheduler
- Inherits:
-
Object
- Object
- Philiprehberger::CronKit::Scheduler
- Includes:
- TimeoutHandler
- Defined in:
- lib/philiprehberger/cron_kit/scheduler.rb
Overview
A simple in-process cron scheduler that checks registered jobs every 60 seconds.
Defined Under Namespace
Classes: Job
Instance Method Summary collapse
- #every(expression, name: nil, timeout: nil, overlap: true, &block) ⇒ Object
-
#initialize ⇒ Scheduler
constructor
A new instance of Scheduler.
- #job_names ⇒ Object
- #next_runs(from: Time.now) ⇒ Object
- #on_error(&block) ⇒ Object
- #remove(name) ⇒ Object
-
#run_now(name) ⇒ Object?
Manually trigger a registered job by name.
- #running? ⇒ Boolean
- #running_jobs ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
Constructor Details
#initialize ⇒ Scheduler
Returns a new instance of Scheduler.
11 12 13 14 15 16 17 18 19 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 11 def initialize @jobs = [] @mutex = Mutex.new @thread = nil @running = false @on_error = nil @running_threads = [] @job_threads = {} end |
Instance Method Details
#every(expression, name: nil, timeout: nil, overlap: true, &block) ⇒ Object
31 32 33 34 35 36 37 38 39 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 31 def every(expression, name: nil, timeout: nil, overlap: true, &block) expr = expression.is_a?(Expression) ? expression : Expression.new(expression) @mutex.synchronize do @jobs << Job.new(expression: expr, block: block, name: name, timeout: timeout, overlap: overlap) end self end |
#job_names ⇒ Object
41 42 43 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 41 def job_names @mutex.synchronize { @jobs.map(&:name).compact } end |
#next_runs(from: Time.now) ⇒ Object
71 72 73 74 75 76 77 78 79 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 71 def next_runs(from: Time.now) jobs = @mutex.synchronize { @jobs.dup } jobs.each_with_object({}) do |job, hash| next unless job.name hash[job.name] = job.expression.next_at(from: from) end end |
#on_error(&block) ⇒ Object
21 22 23 24 25 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 21 def on_error(&block) return @on_error unless block @on_error = block end |
#remove(name) ⇒ Object
45 46 47 48 49 50 51 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 45 def remove(name) @mutex.synchronize do initial_size = @jobs.size @jobs.reject! { |job| job.name == name } @jobs.size < initial_size end end |
#run_now(name) ⇒ Object?
Manually trigger a registered job by name.
Reuses the standard execution path (timeout + overlap-skip), but runs synchronously so the caller can capture the return value. Useful for testing and operator-driven re-runs.
63 64 65 66 67 68 69 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 63 def run_now(name) job = @mutex.synchronize { @jobs.find { |j| j.name == name } } raise KeyError, "job not registered: #{name.inspect}" unless job return nil if skip_overlapping?(job) execute_now(job) end |
#running? ⇒ Boolean
102 103 104 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 102 def running? @mutex.synchronize { @running } end |
#running_jobs ⇒ Object
27 28 29 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 27 def running_jobs @mutex.synchronize { @running_threads.count(&:alive?) } end |
#start ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 81 def start @mutex.synchronize do return self if @running @running = true end @thread = Thread.new { run_loop } @thread.abort_on_exception = true self end |
#stop ⇒ Object
94 95 96 97 98 99 100 |
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 94 def stop @mutex.synchronize { @running = false } @thread&.join(5) @thread = nil self end |