Class: Philiprehberger::CronKit::Scheduler

Inherits:
Object
  • Object
show all
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

Constructor Details

#initializeScheduler

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_namesObject



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.

Parameters:

  • name (Symbol, String)

    the job name to trigger

Returns:

  • (Object, nil)

    the block’s return value, or ‘nil` when skipped due to `overlap: false`

Raises:

  • (KeyError)

    if no job is registered under ‘name`

  • (Timeout::Error)

    if the job’s ‘timeout:` is exceeded



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

Returns:

  • (Boolean)


102
103
104
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 102

def running?
  @mutex.synchronize { @running }
end

#running_jobsObject



27
28
29
# File 'lib/philiprehberger/cron_kit/scheduler.rb', line 27

def running_jobs
  @mutex.synchronize { @running_threads.count(&:alive?) }
end

#startObject



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

#stopObject



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