Class: Smplkit::Jobs::Job

Inherits:
Object
  • Object
show all
Defined in:
lib/smplkit/jobs/models.rb

Overview

A unit of work: an HTTP request, run on a schedule or triggered on demand.

Active-record style: instantiate via client.jobs.new_recurring_job(…), new_manual_job(…), or schedule(…), mutate fields directly, and call #save to persist or #delete to remove. Header values in configuration.headers are returned in plaintext on reads, so fetching a job, mutating it, and calling #save preserves its header values without re-entering secrets.

A job’s #kind follows from its #schedule: a recurring (cron) job, a manual job (no schedule, runs only when triggered), or a one-off (now / datetime) job that runs a single time. Enablement and every other override is per environment: reach an environment’s sparse override via #environment and set its enabled / leaf fields (+job.environment(“production”).enabled = true+). Base #enabled is a read-only roll-up over #environments (true when enabled in at least one environment). Base fields (#schedule, #timezone, #retry_policy, #configuration) are set by direct assignment.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client = nil, id:, name:, configuration:, schedule: nil, timezone: nil, retry_policy: nil, description: nil, environments: nil, kind: nil, type: "http", concurrency_policy: "ALLOW", birth_environment: nil, created_at: nil, updated_at: nil, deleted_at: nil, version: nil) ⇒ Job

Returns a new instance of Job.



571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
# File 'lib/smplkit/jobs/models.rb', line 571

def initialize(client = nil, id:, name:, configuration:, schedule: nil,
               timezone: nil, retry_policy: nil, description: nil, environments: nil,
               kind: nil, type: "http", concurrency_policy: "ALLOW",
               birth_environment: nil, created_at: nil,
               updated_at: nil, deleted_at: nil, version: nil)
  @client = client
  @id = id
  @name = name
  @description = description
  @environments = environments || {}
  @kind = kind
  @type = type
  @schedule = schedule
  @timezone = timezone
  self.retry_policy = retry_policy
  @configuration = configuration
  @concurrency_policy = concurrency_policy
  @birth_environment = birth_environment
  @created_at = created_at
  @updated_at = updated_at
  @deleted_at = deleted_at
  @version = version
end

Instance Attribute Details

#birth_environmentObject



569
570
571
# File 'lib/smplkit/jobs/models.rb', line 569

def birth_environment
  @birth_environment
end

#concurrency_policyString

Returns How overlapping runs are handled. “ALLOW” (the only value) permits them.

Returns:

  • (String)

    How overlapping runs are handled. “ALLOW” (the only value) permits them.



548
549
550
# File 'lib/smplkit/jobs/models.rb', line 548

def concurrency_policy
  @concurrency_policy
end

#configurationHttpConfig

Returns The base HTTP request to perform when the job fires. Per-environment overrides live in #environments.

Returns:

  • (HttpConfig)

    The base HTTP request to perform when the job fires. Per-environment overrides live in #environments.



544
545
546
# File 'lib/smplkit/jobs/models.rb', line 544

def configuration
  @configuration
end

#created_atString?

Returns ISO-8601 timestamp of first persist. nil for an unsaved instance.

Returns:

  • (String, nil)

    ISO-8601 timestamp of first persist. nil for an unsaved instance.



552
553
554
# File 'lib/smplkit/jobs/models.rb', line 552

def created_at
  @created_at
end

#deleted_atString?

Returns Timestamp when the job was deleted; nil for live jobs.

Returns:

  • (String, nil)

    Timestamp when the job was deleted; nil for live jobs.



559
560
561
# File 'lib/smplkit/jobs/models.rb', line 559

def deleted_at
  @deleted_at
end

#descriptionString?

Returns Free-text description. nil when unset.

Returns:

  • (String, nil)

    Free-text description. nil when unset.



482
483
484
# File 'lib/smplkit/jobs/models.rb', line 482

def description
  @description
end

#environmentsHash{String => JobEnvironment}

Returns Per-environment sparse overrides keyed by environment key (e.g. “production”). A job runs in an environment only when environments[env].enabled is true. Each entry overrides only the leaves it sets; omitted leaves inherit the base definition. Reach one via #environment. Every referenced environment must exist and be managed for the account.

Returns:

  • (Hash{String => JobEnvironment})

    Per-environment sparse overrides keyed by environment key (e.g. “production”). A job runs in an environment only when environments[env].enabled is true. Each entry overrides only the leaves it sets; omitted leaves inherit the base definition. Reach one via #environment. Every referenced environment must exist and be managed for the account.



498
499
500
# File 'lib/smplkit/jobs/models.rb', line 498

def environments
  @environments
end

#idString

Caller-supplied unique identifier for the job (the resource id). Unique within the account and immutable; the service returns 409 if another live job already uses this id.

Returns:

  • (String)

    Caller-supplied unique identifier for the job (the resource id). Unique within the account and immutable; the service returns 409 if another live job already uses this id.



476
477
478
# File 'lib/smplkit/jobs/models.rb', line 476

def id
  @id
end

#kindString?

Returns Read-only. How the job runs, derived from its #schedule by the server: one of Smplkit::Jobs::JobKind::RECURRING, Smplkit::Jobs::JobKind::MANUAL, or Smplkit::Jobs::JobKind::ONE_OFF. nil on an unsaved instance.

Returns:



503
504
505
# File 'lib/smplkit/jobs/models.rb', line 503

def kind
  @kind
end

#nameString

Returns Human-readable name for the job.

Returns:

  • (String)

    Human-readable name for the job.



479
480
481
# File 'lib/smplkit/jobs/models.rb', line 479

def name
  @name
end

#retry_policyString?

Returns The base retry policy for failed runs — the id of a RetryPolicy, overridable per environment via Smplkit::Jobs::JobEnvironment#retry_policy. nil (the default, omitted on the wire) uses the built-in “Default” policy, which never retries. Assigning accepts a RetryPolicy (its id is used) or a policy id string; sent on writes only when present.

Returns:

  • (String, nil)

    The base retry policy for failed runs — the id of a RetryPolicy, overridable per environment via Smplkit::Jobs::JobEnvironment#retry_policy. nil (the default, omitted on the wire) uses the built-in “Default” policy, which never retries. Assigning accepts a RetryPolicy (its id is used) or a policy id string; sent on writes only when present.



534
535
536
# File 'lib/smplkit/jobs/models.rb', line 534

def retry_policy
  @retry_policy
end

#scheduleString?

Returns The base schedule every environment inherits, and the field that determines the job’s #kind: nil (omitted) for a permanent manual job that never auto-fires; a 5-field cron expression evaluated in UTC for a recurring job; an ISO-8601 datetime for a one-off run at that instant; or the literal “now” for a one-off run as soon as possible. A datetime or “now” job disables itself after it fires. The schedule is environment-agnostic — set it by direct assignment; per-environment cron overrides live on job.environment(env).schedule.

Returns:

  • (String, nil)

    The base schedule every environment inherits, and the field that determines the job’s #kind: nil (omitted) for a permanent manual job that never auto-fires; a 5-field cron expression evaluated in UTC for a recurring job; an ISO-8601 datetime for a one-off run at that instant; or the literal “now” for a one-off run as soon as possible. A datetime or “now” job disables itself after it fires. The schedule is environment-agnostic — set it by direct assignment; per-environment cron overrides live on job.environment(env).schedule.



517
518
519
# File 'lib/smplkit/jobs/models.rb', line 517

def schedule
  @schedule
end

#timezoneString?

Returns The base IANA timezone the cron #schedule is evaluated in (e.g. “America/New_York”); nil (the default) means UTC. The base every environment inherits unless it sets its own Smplkit::Jobs::JobEnvironment#timezone. The cron fires on this zone’s wall clock (DST-aware) while next_run_at is still reported as a UTC instant. Only valid on a recurring (cron) job — leave nil for a manual or one-off job. Sent on writes only when present.

Returns:

  • (String, nil)

    The base IANA timezone the cron #schedule is evaluated in (e.g. “America/New_York”); nil (the default) means UTC. The base every environment inherits unless it sets its own Smplkit::Jobs::JobEnvironment#timezone. The cron fires on this zone’s wall clock (DST-aware) while next_run_at is still reported as a UTC instant. Only valid on a recurring (cron) job — leave nil for a manual or one-off job. Sent on writes only when present.



526
527
528
# File 'lib/smplkit/jobs/models.rb', line 526

def timezone
  @timezone
end

#typeString

Returns Job type. Only “http” is supported today.

Returns:

  • (String)

    Job type. Only “http” is supported today.



506
507
508
# File 'lib/smplkit/jobs/models.rb', line 506

def type
  @type
end

#updated_atString?

Returns ISO-8601 timestamp of the most recent mutation.

Returns:

  • (String, nil)

    ISO-8601 timestamp of the most recent mutation.



555
556
557
# File 'lib/smplkit/jobs/models.rb', line 555

def updated_at
  @updated_at
end

#versionInteger?

Returns Monotonic version counter, bumped on every server-side write.

Returns:

  • (Integer, nil)

    Monotonic version counter, bumped on every server-side write.



563
564
565
# File 'lib/smplkit/jobs/models.rb', line 563

def version
  @version
end

Class Method Details

.from_resource(resource, client: nil) ⇒ Job

Returns The hydrated job.

Parameters:

  • resource (Object)

    The JSON:API resource (id + attributes).

  • client (JobsClient, nil) (defaults to: nil)

    Client to bind the job to.

Returns:

  • (Job)

    The hydrated job.



730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
# File 'lib/smplkit/jobs/models.rb', line 730

def self.from_resource(resource, client: nil)
  a = resource.attributes
  environments = (a.environments || {}).each_with_object({}) do |(env_key, env_raw), out|
    out[env_key.to_s] = JobEnvironment.from_flat(env_raw)
  end
  new(
    client,
    id: resource.id,
    name: a.name,
    description: a.description,
    # The base +enabled+ roll-up is derived from +environments+, not read
    # from the wire — the API no longer carries a top-level +enabled+.
    environments: environments,
    kind: a.kind,
    type: a.type || "http",
    schedule: a.schedule,
    timezone: a.timezone,
    retry_policy: a.retry_policy,
    configuration: HttpConfig.from_wire(a.configuration),
    concurrency_policy: a.concurrency_policy || "ALLOW",
    created_at: a.created_at,
    updated_at: a.updated_at,
    deleted_at: a.deleted_at,
    version: a.version
  )
end

Instance Method Details

#_apply(other) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
# File 'lib/smplkit/jobs/models.rb', line 706

def _apply(other)
  @id = other.id
  @name = other.name
  @description = other.description
  @environments = other.environments
  @kind = other.kind
  @type = other.type
  @schedule = other.schedule
  @timezone = other.timezone
  @retry_policy = other.retry_policy
  @configuration = other.configuration
  @concurrency_policy = other.concurrency_policy
  @created_at = other.created_at
  @updated_at = other.updated_at
  @deleted_at = other.deleted_at
  @version = other.version
end

#deletenil Also known as: delete!

Delete this job on the server.

Returns:

  • (nil)


616
617
618
619
620
# File 'lib/smplkit/jobs/models.rb', line 616

def delete
  raise "Job was constructed without a client or id; cannot delete" if @client.nil? || @id.nil?

  @client.delete(@id)
end

#enabledBoolean

Returns Read-only roll-up: true when the job is enabled in at least one environment. Computed from #environments rather than read from the wire — the API has no top-level enabled. Enable per environment via job.environment(env).enabled = true.

Returns:

  • (Boolean)

    Read-only roll-up: true when the job is enabled in at least one environment. Computed from #environments rather than read from the wire — the API has no top-level enabled. Enable per environment via job.environment(env).enabled = true.



488
489
490
# File 'lib/smplkit/jobs/models.rb', line 488

def enabled
  (@environments || {}).each_value.any?(&:enabled)
end

#environment(environment) ⇒ JobEnvironment

The per-environment override for environment — the single place to read or set what this job overrides there (ADR-056).

Returns the Smplkit::Jobs::JobEnvironment for environment, creating an empty one (and inserting it into #environments) on first access, so you can set overrides directly:

job.environment("production").enabled = true
job.environment("production").url = "https://prod.example.com/warm"
job.environment("production").set_header("Authorization", "Bearer prod")

Only the leaves you set are sent on save; everything else inherits the base definition (the server resolves base ⊕ overrides when the job fires).

Parameters:

  • environment (String)

    The environment key.

Returns:



639
640
641
# File 'lib/smplkit/jobs/models.rb', line 639

def environment(environment)
  @environments[environment] ||= JobEnvironment.new
end

#is_manualBoolean

Whether this is a manual job — no schedule; runs only when triggered.

Returns:

  • (Boolean)


653
654
655
# File 'lib/smplkit/jobs/models.rb', line 653

def is_manual
  @kind == JobKind::MANUAL
end

#is_one_offBoolean

Whether this is a one-off job — a single now / datetime run.

Returns:

  • (Boolean)


660
661
662
# File 'lib/smplkit/jobs/models.rb', line 660

def is_one_off
  @kind == JobKind::ONE_OFF
end

#is_recurringBoolean

Whether this is a recurring (cron-scheduled) job.

Returns:

  • (Boolean)


646
647
648
# File 'lib/smplkit/jobs/models.rb', line 646

def is_recurring
  @kind == JobKind::RECURRING
end

#list_runs(environment: nil, triggers: nil, last_run_only: false, page_size: nil, after: nil) ⇒ Array<Smplkit::Jobs::Run>

List this job’s run history, most recent first.

Parameters:

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

    Restrict to runs stamped with this environment. nil covers every environment you can access.

  • triggers (Array<String>, nil) (defaults to: nil)

    Restrict to runs started by any of these triggers (see RunTrigger) — e.g. [RunTrigger::RETRY] for automatic retries. nil covers every trigger.

  • last_run_only (Boolean) (defaults to: false)

    When true, return only the last completed run per environment (in-flight runs excluded). Defaults to false.

  • page_size (Integer, nil) (defaults to: nil)

    Maximum number of runs to return in this page.

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

    Opaque cursor from a previous page.

Returns:

Raises:

  • (RuntimeError)

    when this job has no bound client.



692
693
694
695
696
697
698
699
700
701
702
703
# File 'lib/smplkit/jobs/models.rb', line 692

def list_runs(environment: nil, triggers: nil, last_run_only: false, page_size: nil, after: nil)
  raise "Job was constructed without a client; cannot list runs" if @client.nil?

  @client.runs.list(
    job: @id,
    environments: environment.nil? ? nil : [environment],
    triggers: triggers,
    last_run_only: last_run_only,
    page_size: page_size,
    after: after
  )
end

#saveself Also known as: save!

Create this job, or full-replace it if it already exists.

Upsert behavior is driven by #created_at: a job with no created_at is created (POST); otherwise it’s full-replace updated (PUT). After the call, every field is refreshed from the server response (including newly-assigned created_at, version, and per-environment next_run_at inside #environments).

Returns:

  • (self)


604
605
606
607
608
609
610
# File 'lib/smplkit/jobs/models.rb', line 604

def save
  raise "Job was constructed without a client; cannot save" if @client.nil?

  updated = @created_at.nil? ? @client._create_job(self) : @client._update_job(self)
  _apply(updated)
  self
end

#trigger(environment: nil) ⇒ Smplkit::Jobs::Run

Trigger one immediate, manual run of this job (a MANUAL run).

Parameters:

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

    Environment the run executes in. Defaults to the client’s configured environment; when the job is enabled in exactly one environment that environment is used.

Returns:

Raises:

  • (RuntimeError)

    when this job has no bound client.



671
672
673
674
675
# File 'lib/smplkit/jobs/models.rb', line 671

def trigger(environment: nil)
  raise "Job was constructed without a client; cannot trigger a run" if @client.nil?

  @client.run(@id, environment: environment)
end