Class: Cosmo::API::Cron::Entry

Inherits:
Object
  • Object
show all
Defined in:
lib/cosmo/api/cron/entry.rb

Overview

Value object representing a single cron schedule entry. Each schedule maps one job class (and optional args) to a NATS 2.14 message schedule.

NATS 2.14 message scheduling uses a 6-field cron format:

second minute hour day-of-month month day-of-week

@-shortcuts (@daily, @every 5m, @at …) are passed through unchanged —the server understands them natively. Plain 5-field UNIX cron expressions need a seconds field prepended to become valid 6-field expressions.

"0 9 * * 1-5"  →  "0 0 9 * * 1-5"   (at 09:00 on weekdays)
"@daily"        →  "@daily"            (unchanged)

Constant Summary collapse

SUBJECT_PREFIX =
"cosmo.cron"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(class_name:, stream:, expression:, args: [], timezone: nil, name: nil) ⇒ Entry

Returns a new instance of Entry.

Parameters:

  • class_name (String)

    Fully-qualified Ruby class name (e.g. “ReportJob”)

  • stream (String)

    Target job stream name (e.g. “default”)

  • expression (String)

    NATS schedule expression (@daily, @every 5m, “0 0 9 * * 1-5”, etc.)

  • args (Array) (defaults to: [])

    Arguments passed to the job’s perform method

  • timezone (String, nil) (defaults to: nil)

    IANA timezone name (e.g. “America/New_York”). Cron expressions only.

  • name (String, Symbol, nil) (defaults to: nil)

    Disambiguates multiple schedules on the same class.



40
41
42
43
44
45
46
47
# File 'lib/cosmo/api/cron/entry.rb', line 40

def initialize(class_name:, stream:, expression:, args: [], timezone: nil, name: nil)
  @class_name = class_name.to_s
  @stream     = stream.to_s
  @expression = self.class.normalize_expression(expression)
  @args       = Array(args)
  @timezone   = timezone
  @name       = name&.to_s
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def args
  @args
end

#class_nameObject (readonly)

Returns the value of attribute class_name.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def class_name
  @class_name
end

#expressionObject (readonly)

Returns the value of attribute expression.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def expression
  @expression
end

#nameObject (readonly)

Returns the value of attribute name.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def name
  @name
end

#streamObject (readonly)

Returns the value of attribute stream.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def stream
  @stream
end

#timezoneObject (readonly)

Returns the value of attribute timezone.



32
33
34
# File 'lib/cosmo/api/cron/entry.rb', line 32

def timezone
  @timezone
end

Class Method Details

.normalize_expression(expr) ⇒ Object



24
25
26
27
28
29
30
# File 'lib/cosmo/api/cron/entry.rb', line 24

def self.normalize_expression(expr)
  str = expr.to_s.strip
  return str if str.start_with?("@")

  fields = str.split
  fields.size == 5 ? "0 #{str}" : str
end

Instance Method Details

#as_jsonObject



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/cosmo/api/cron/entry.rb', line 67

def as_json
  {
    class: @class_name,
    stream: @stream,
    schedule: @expression,
    timezone: @timezone,
    args: @args,
    name: @name,
    schedule_subject: schedule_subject,
    target_subject: target_subject
  }.compact
end

#job_nameObject



63
64
65
# File 'lib/cosmo/api/cron/entry.rb', line 63

def job_name
  @job_name ||= Utils::String.underscore(@class_name)
end

#job_payloadObject

JSON payload sent as the body of the schedule message. Mirrors the format produced by Job::Data so the job processor can handle it.



82
83
84
85
86
87
88
89
90
# File 'lib/cosmo/api/cron/entry.rb', line 82

def job_payload
  Utils::Json.dump({
                     jid: SecureRandom.hex(12),
                     class: @class_name,
                     args: @args,
                     retry: ::Cosmo::Job::Data::DEFAULTS[:retry],
                     dead: ::Cosmo::Job::Data::DEFAULTS[:dead]
                   })
end

#schedule_subjectObject

Subject where the schedule message lives in NATS (one per unique schedule). e.g. “cosmo.cron.default.report_job” or “cosmo.cron.default.report_job.monthly”



51
52
53
54
55
# File 'lib/cosmo/api/cron/entry.rb', line 51

def schedule_subject
  parts = [SUBJECT_PREFIX, @stream, job_name]
  parts << @name if @name
  parts.join(".")
end

#target_subjectObject

Subject where NATS fires the generated job message. Must be a subject covered by the same stream.



59
60
61
# File 'lib/cosmo/api/cron/entry.rb', line 59

def target_subject
  "jobs.#{@stream}.#{job_name}"
end

#to_sObject Also known as: inspect



92
93
94
# File 'lib/cosmo/api/cron/entry.rb', line 92

def to_s
  "#<Cosmo::API::Cron::Entry class=#{@class_name} expression=#{@expression} stream=#{@stream}>"
end