Module: CronSwanson

Defined in:
lib/cron_swanson.rb,
lib/cron_swanson/version.rb,
lib/cron_swanson/whenever.rb

Overview

CronSwanson is a utility to generate run times for cron jobs which are regular, but which vary per job.

Defined Under Namespace

Classes: Whenever

Constant Summary collapse

SECONDS_PER_HOUR =
60 * 60
SECONDS_PER_DAY =
SECONDS_PER_HOUR * 24
VERSION =
"0.2.0"

Class Method Summary collapse

Class Method Details

.default_intervalObject



11
12
13
# File 'lib/cron_swanson.rb', line 11

def self.default_interval
  SECONDS_PER_DAY
end

.offset(job_identifier, interval: default_interval) ⇒ Integer

offset within a time period

if the interval is 6 hours, the returned offset will be some number of seconds between 0 and 60 * 60 * 6 seconds (6 hours).

Parameters:

  • job_identifier (String)

    if nil, method will determine this on its own

  • interval (Integer) (defaults to: default_interval)

    how often will the job be run?

Returns:

  • (Integer)

    number of seconds to offset this job



24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/cron_swanson.rb', line 24

def self.offset(job_identifier, interval: default_interval)
  sha = Digest::SHA256.hexdigest(job_identifier.to_s)

  # largest possible hex sha256 value
  max_sha256_value = (16**64).to_f

  # what % of the max sha256 is the job_identifier?
  sha_pct_of_max_sha256 = sha.to_i(16) / max_sha256_value

  # apply that same % to the desired interval to get an offset
  offset_seconds = (sha_pct_of_max_sha256 * interval).round

  offset_seconds
end

.schedule(job_identifier, interval: default_interval) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/cron_swanson.rb', line 39

def self.schedule(job_identifier, interval: default_interval)
  if interval > SECONDS_PER_DAY
    raise ArgumentError, "interval must be less than 1 day (#{SECONDS_PER_DAY} seconds)."
  end

  if SECONDS_PER_DAY % interval != 0
    raise ArgumentError, "A day (#{SECONDS_PER_DAY} seconds) must be evenly " \
      "divisible by the given interval."
  end

  # figure out how many times job will happen in a day
  runs_per_day = SECONDS_PER_DAY / interval

  run_at = Time.at(offset(job_identifier, interval: interval)).utc

  hours = []
  runs_per_day.times do |i|
    hours << run_at.hour + (i * interval / SECONDS_PER_HOUR)
  end

  "#{run_at.min} #{hours.join(',')} * * *"
end