Module: Smplkit::Jobs

Defined in:
lib/smplkit/jobs/models.rb,
lib/smplkit/jobs/client.rb

Overview

Smpl Jobs surface — exposed through client.jobs.*.

Unlike Config/Flags/Logging, Jobs has no live “phone-home” agent — no environment registration, no WebSocket — so its entire surface lives on a single client. A Job is an active record: build it with client.jobs.new_recurring_job(…) / new_manual_job(…) / schedule(…), set fields, and call Job#save (create when new, full-replace update when it already exists) or Job#delete. Runs are read-only views with rerun / cancel actions; run history lives on client.jobs.runs.

A job is enabled per environment: a recurring (cron) job may run in several environments at once, a manual job (no schedule) runs only when triggered, and a one-off (now / future datetime) job runs a single time in the environment it was created in. Base Job#enabled is a derived roll-up (true when enabled in at least one environment), computed from the per-environment Job#environments map.

Defined Under Namespace

Modules: Backoff, HttpMethod, JobKind, RunTrigger Classes: HttpConfig, Job, JobEnvironment, JobsClient, RetryPoliciesClient, RetryPolicy, Run, RunRetry, RunsClient, Usage

Constant Summary collapse

JOB_ENV_SCALAR_LEAVES =

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

The per-environment scalar override leaves (everything except enabled and headers, which are addressed individually as headers.<name>). These map 1:1 onto JobEnvironment fields and onto the flat overlay’s leaf paths, in payload order.

%i[schedule timezone retry_policy url method timeout body success_status tls_verify ca_cert].freeze
JOB_ENV_SCALAR_LEAF_NAMES =

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

The same leaves as wire-key strings, for parsing the flat overlay.

JOB_ENV_SCALAR_LEAVES.map(&:to_s).freeze

Class Method Summary collapse

Class Method Details

.call_apiObject

Wrap a generated-jobs-API call and translate ApiError into the Smplkit::Error hierarchy. Connection-level failures (no response code) become ConnectionError; status-coded failures route through Errors.raise_for_status, which emits PaymentRequiredError / NotFoundError / ConflictError / ValidationError / Error depending on the JSON:API body.



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/smplkit/jobs/models.rb', line 28

def self.call_api
  yield
rescue SmplkitGeneratedClient::Jobs::ApiError => e
  raise Smplkit::ConnectionError, e.message.to_s if e.code.nil? || e.code.zero?

  Smplkit::Errors.raise_for_status(e.code, e.response_body.to_s)
  # raise_for_status only returns on 2xx; if we get here the generated
  # layer raised on a 2xx (shouldn't happen) — re-raise the original so
  # the caller can inspect.
  raise
end

.jobs_transport(api_key:, profile:, base_domain:, scheme:, debug:, extra_headers:) ⇒ Object

The Smpl Jobs client — accessed via client.jobs.

Unlike Config/Flags/Logging, Jobs has no live “phone-home” agent — no environment registration, no WebSocket — so its entire surface lives on one client. Defining a job, triggering a run, and reading run history are all plain request/response calls here:

client.jobs.{new_recurring_job,new_manual_job,schedule,get,list,delete,run,usage}
client.jobs.runs.{list,get,cancel,rerun}
client.jobs.retry_policies.{new,list,get,delete}
Job#{save,delete,trigger,list_runs}
Run#{rerun,cancel}
RetryPolicy#{save,delete}

Build a standalone Smpl Jobs transport from resolved config.

Reuses the config resolver (jobs is account-global and never environment-scoped at the transport layer) so a standalone jobs client resolves credentials/base-domain from ~/.smplkit / env vars / constructor args exactly like the top-level clients do. Smpl Jobs is JSON:API, so the transport carries the application/vnd.apijson+ Accept header.



290
291
292
293
294
295
296
297
298
299
300
301
302
# File 'lib/smplkit/jobs/client.rb', line 290

def self.jobs_transport(api_key:, profile:, base_domain:, scheme:, debug:, extra_headers:)
  cfg = ConfigResolution.resolve_client_config(
    profile: profile, api_key: api_key, base_domain: base_domain, scheme: scheme, debug: debug
  )
  merged = {}
  merged.merge!(cfg.extra_headers || {})
  merged.merge!(extra_headers || {})
  tcfg = ConfigResolution::ResolvedClientConfig.new(
    api_key: cfg.api_key, base_domain: cfg.base_domain, scheme: cfg.scheme,
    debug: cfg.debug, extra_headers: merged
  )
  Transport.build_api_client(SmplkitGeneratedClient::Jobs, "jobs", tcfg, accept: "application/vnd.api+json")
end

.join_environments(environments) ⇒ 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.

Coerce a caller-supplied environments value into the comma-separated string the GET /api/v1/runs endpoint expects for filter[environment], or nil when no filter should be sent.

nil or an empty array (or one whose entries are all blank) returns nil so the caller omits the query param entirely and the read covers every environment the credential can access.



49
50
51
52
53
54
# File 'lib/smplkit/jobs/models.rb', line 49

def self.join_environments(environments)
  return nil if environments.nil?

  values = Array(environments).map { |e| e.to_s.strip }.reject(&:empty?)
  values.empty? ? nil : values.join(",")
end

.normalize_environments(environments) ⇒ 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.

Coerce a caller’s environments map to JobEnvironment instances.

Accepts either JobEnvironment values or plain hashes of its constructor kwargs (+{ enabled: true, schedule: “0 3 * * *”, url: “prod/warm”, headers: { “Authorization” => “Bearer prod” } }+) so callers can use the lightweight hash form without importing the model. Each hash is splatted into JobEnvironment.new; both symbol- and string-keyed hashes work.



85
86
87
88
89
90
91
92
# File 'lib/smplkit/jobs/models.rb', line 85

def self.normalize_environments(environments)
  return {} if environments.nil? || environments.empty?

  environments.each_with_object({}) do |(env_key, value), out|
    out[env_key.to_s] =
      value.is_a?(JobEnvironment) ? value : JobEnvironment.new(**value.transform_keys(&:to_sym))
  end
end

.resolve_environment_filter(environments, default) ⇒ String?

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.

Resolve the filter[environment] value for the runs listing.

An explicit, non-empty environments list always wins and is comma-joined via join_environments. Otherwise the client’s configured default environment scopes the read. A client with no configured environment and no explicit list returns nil so the caller omits the query param and the credential’s own scoping applies server-side.

Parameters:

  • environments (Array<String>, String, nil)

    Explicit per-call environment filter; an empty/blank value falls through to default.

  • default (String, nil)

    The client’s configured environment.

Returns:

  • (String, nil)

    The filter[environment] value, or nil to omit it.



69
70
71
72
73
74
# File 'lib/smplkit/jobs/models.rb', line 69

def self.resolve_environment_filter(environments, default)
  joined = join_environments(environments)
  return joined unless joined.nil?

  default
end