smplkit 3.0.95 → 3.0.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,9 +26,9 @@ module Smplkit
26
26
  # arguments) carry the data that targeting rules evaluate against.
27
27
  #
28
28
  # Used for both authoring (+flag.get(context: [...])+,
29
- # +client.set_context([...])+, +mgmt.contexts.register([...])+) and reading
30
- # (+mgmt.contexts.list/get+ return populated +Context+ instances with
31
- # +save+ / +delete+ ready to call).
29
+ # +client.set_context([...])+, +client.platform.contexts.register([...])+) and
30
+ # reading (+client.platform.contexts.list/get+ return populated +Context+
31
+ # instances with +save+ / +delete+ ready to call).
32
32
  #
33
33
  # Examples:
34
34
  #
@@ -141,10 +141,9 @@ module Smplkit
141
141
 
142
142
  # Describes a flag declaration for buffered registration.
143
143
  #
144
- # Used by +Smplkit::ManagementClient#flags#register+ to queue declarations
145
- # for bulk registration. +service+ and +environment+ default to +nil+; the
146
- # runtime client fills them from the active +Smplkit::Client+ when it
147
- # forwards declarations.
144
+ # Used by +client.flags.register+ to queue declarations for bulk
145
+ # registration. +service+ and +environment+ default to +nil+; the client
146
+ # fills them from the active +Smplkit::Client+ when it forwards declarations.
148
147
  class FlagDeclaration
149
148
  attr_reader :id, :type, :default, :service, :environment
150
149
 
@@ -1,39 +1,149 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # The Smpl Jobs client — one unified +JobsClient+.
4
+ #
5
+ # Smpl Jobs schedules HTTP calls (cron-style +schedule+ + +http+ configuration)
6
+ # and records their run history. Unlike Config/Flags/Logging it installs no
7
+ # in-process machinery, so it has no runtime/management split: a single
8
+ # +JobsClient+ exposes the full surface and is reachable as +client.jobs+ on
9
+ # +Smplkit::Client+ or constructed directly.
10
+ #
11
+ # client.jobs.{new,get,list,delete,run,usage}
12
+ # client.jobs.runs.{list,get,cancel,rerun}
13
+ # Job#{save,delete}
14
+ #
15
+ # The shared model classes (+Job+, +Run+, +Usage+, +HttpConfig+) live in
16
+ # +lib/smplkit/jobs/models.rb+.
3
17
  module Smplkit
4
- module Management
5
- # Smpl Jobs management surface accessed via +mgmt.jobs+.
18
+ module Jobs
19
+ # +client.jobs.runs.*+ read-only run history plus the cancel / rerun run
20
+ # actions.
21
+ class RunsClient
22
+ def initialize(api)
23
+ @api = api
24
+ end
25
+
26
+ # List runs for the authenticated account, newest first. Cursor paginated
27
+ # (ADR-014): pass +page_size+ and the +after+ cursor from the prior page.
28
+ # Pass +job+ to scope to a single job's history.
29
+ #
30
+ # @param job [String, nil] Filter to a single job's run history, by job id.
31
+ # @param page_size [Integer, nil] Items per page (cursor pagination).
32
+ # @param after [String, nil] Opaque cursor token from a prior page.
33
+ # @return [Array<Smplkit::Jobs::Run>]
34
+ def list(job: nil, page_size: nil, after: nil)
35
+ opts = {}
36
+ opts[:filter_job] = job unless job.nil?
37
+ opts[:page_size] = page_size unless page_size.nil?
38
+ opts[:page_after] = after unless after.nil?
39
+
40
+ resp = Jobs.call_api { @api.list_runs(opts) }
41
+ (resp.data || []).map { |r| Run.from_resource(r) }
42
+ end
43
+
44
+ # Fetch a single run by id.
45
+ #
46
+ # @param run_id [String]
47
+ # @return [Smplkit::Jobs::Run]
48
+ def get(run_id)
49
+ resp = Jobs.call_api { @api.get_run(run_id) }
50
+ Run.from_resource(resp.data)
51
+ end
52
+
53
+ # Cancel a pending run.
54
+ #
55
+ # @param run_id [String]
56
+ # @return [Smplkit::Jobs::Run]
57
+ def cancel(run_id)
58
+ resp = Jobs.call_api { @api.cancel_run(run_id) }
59
+ Run.from_resource(resp.data)
60
+ end
61
+
62
+ # Re-run a prior run, spawning a new +RERUN+ run.
63
+ #
64
+ # @param run_id [String]
65
+ # @return [Smplkit::Jobs::Run]
66
+ def rerun(run_id)
67
+ resp = Jobs.call_api { @api.rerun_run(run_id) }
68
+ Run.from_resource(resp.data)
69
+ end
70
+ end
71
+
72
+ # The Smpl Jobs client — accessed via +client.jobs+.
6
73
  #
7
74
  # Unlike Config/Flags/Logging, Jobs has no live "phone-home" agent — no
8
75
  # environment registration, no WebSocket — so its entire surface lives on
9
- # the management client. Defining a job, triggering a run, and reading run
10
- # history are all plain request/response calls here:
76
+ # one client. Defining a job, triggering a run, and reading run history are
77
+ # all plain request/response calls here:
11
78
  #
12
- # mgmt.jobs.{new,get,list,delete,run,usage}
13
- # mgmt.jobs.runs.{list,get,cancel,rerun}
79
+ # client.jobs.{new,get,list,delete,run,usage}
80
+ # client.jobs.runs.{list,get,cancel,rerun}
14
81
  # Job#{save,delete}
15
82
  #
83
+ # Build a standalone Smpl Jobs transport from resolved config.
84
+ #
85
+ # Reuses the config resolver (jobs is account-global and never
86
+ # environment-scoped) so a standalone jobs client resolves
87
+ # credentials/base-domain from +~/.smplkit+ / env vars / constructor args
88
+ # exactly like the top-level clients do. Smpl Jobs is JSON:API, so the
89
+ # transport carries the +application/vnd.api+json+ Accept header.
90
+ def self.jobs_transport(api_key:, profile:, base_domain:, scheme:, debug:, extra_headers:)
91
+ cfg = ConfigResolution.resolve_management_config(
92
+ profile: profile, api_key: api_key, base_domain: base_domain, scheme: scheme, debug: debug
93
+ )
94
+ merged = {}
95
+ merged.merge!(cfg.extra_headers || {})
96
+ merged.merge!(extra_headers || {})
97
+ tcfg = ConfigResolution::ResolvedManagementConfig.new(
98
+ api_key: cfg.api_key, base_domain: cfg.base_domain, scheme: cfg.scheme,
99
+ debug: cfg.debug, extra_headers: merged
100
+ )
101
+ Transport.build_api_client(SmplkitGeneratedClient::Jobs, "jobs", tcfg, accept: "application/vnd.api+json")
102
+ end
103
+
16
104
  # The active-record entry point is {#new}: instantiate a draft, mutate
17
- # fields, then call {Smplkit::Jobs::Job#save}. Run history and the
18
- # cancel / rerun run actions live on {#runs}.
19
- class JobsNamespace
20
- # @return [RunsNamespace] Run history and run actions (+mgmt.jobs.runs+).
105
+ # fields, then call {Smplkit::Jobs::Job#save}. Run history and the cancel /
106
+ # rerun run actions live on {#runs}.
107
+ #
108
+ # Reachable as +client.jobs+ (+Smplkit::Client+) or constructed directly
109
+ # +JobsClient.new+ resolves credentials from +~/.smplkit+ / env vars.
110
+ class JobsClient
111
+ # @return [RunsClient] Run history and run actions (+client.jobs.runs+).
21
112
  attr_reader :runs
22
113
 
23
- def initialize(api_client)
24
- @api = SmplkitGeneratedClient::Jobs::JobsApi.new(api_client)
25
- @runs = RunsNamespace.new(
26
- SmplkitGeneratedClient::Jobs::RunsApi.new(api_client)
114
+ def initialize(api_key = nil, profile: nil, base_domain: nil, scheme: nil,
115
+ debug: nil, extra_headers: nil, auth_client: nil)
116
+ auth = auth_client || Jobs.jobs_transport(
117
+ api_key: api_key, profile: profile, base_domain: base_domain,
118
+ scheme: scheme, debug: debug, extra_headers: extra_headers
27
119
  )
28
- @usage_api = SmplkitGeneratedClient::Jobs::UsageApi.new(api_client)
120
+ @api = SmplkitGeneratedClient::Jobs::JobsApi.new(auth)
121
+ @runs = RunsClient.new(SmplkitGeneratedClient::Jobs::RunsApi.new(auth))
122
+ @usage_api = SmplkitGeneratedClient::Jobs::UsageApi.new(auth)
123
+ end
124
+
125
+ # The generated ApiClient owns Faraday connections that release on GC;
126
+ # there is no explicit shutdown to call.
127
+ def close
128
+ nil
129
+ end
130
+
131
+ # Construct, yield to the block, and close on exit.
132
+ def self.open(*args, **kwargs)
133
+ client = new(*args, **kwargs)
134
+ begin
135
+ yield client
136
+ ensure
137
+ client.close
138
+ end
29
139
  end
30
140
 
31
- # Construct an unsaved {Smplkit::Jobs::Job} bound to this namespace. Call
141
+ # Construct an unsaved {Smplkit::Jobs::Job} bound to this client. Call
32
142
  # +#save+ on the returned instance to create it.
33
143
  #
34
- # @param id [String] Caller-supplied unique identifier for the job.
35
- # Unique within the account and immutable; the service returns 409 if
36
- # another live job already uses this id.
144
+ # @param id [String] Caller-supplied unique identifier for the job. Unique
145
+ # within the account and immutable; the service returns 409 if another
146
+ # live job already uses this id.
37
147
  # @param name [String] Human-readable name for the job.
38
148
  # @param schedule [String] An ISO-8601 datetime, a 5-field UTC cron
39
149
  # expression, or the literal +"now"+.
@@ -46,7 +156,7 @@ module Smplkit
46
156
  # @return [Smplkit::Jobs::Job]
47
157
  def new(id, name:, schedule:, configuration:, description: nil,
48
158
  enabled: true, concurrency_policy: "ALLOW")
49
- Smplkit::Jobs::Job.new(
159
+ Job.new(
50
160
  self,
51
161
  id: id,
52
162
  name: name,
@@ -70,18 +180,18 @@ module Smplkit
70
180
  opts[:page_number] = page_number unless page_number.nil?
71
181
  opts[:page_size] = page_size unless page_size.nil?
72
182
 
73
- resp = Smplkit::Jobs.call_api { @api.list_jobs(opts) }
74
- (resp.data || []).map { |r| Smplkit::Jobs::Job.from_resource(r, client: self) }
183
+ resp = Jobs.call_api { @api.list_jobs(opts) }
184
+ (resp.data || []).map { |r| Job.from_resource(r, client: self) }
75
185
  end
76
186
 
77
- # Fetch a single job by id. The returned instance is bound to this
78
- # namespace, so +job.save+ and +job.delete+ work.
187
+ # Fetch a single job by id. The returned instance is bound to this client,
188
+ # so +job.save+ and +job.delete+ work.
79
189
  #
80
190
  # @param id [String]
81
191
  # @return [Smplkit::Jobs::Job]
82
192
  def get(id)
83
- resp = Smplkit::Jobs.call_api { @api.get_job(id) }
84
- Smplkit::Jobs::Job.from_resource(resp.data, client: self)
193
+ resp = Jobs.call_api { @api.get_job(id) }
194
+ Job.from_resource(resp.data, client: self)
85
195
  end
86
196
 
87
197
  # Soft-delete a job.
@@ -89,7 +199,7 @@ module Smplkit
89
199
  # @param id [String]
90
200
  # @return [nil]
91
201
  def delete(id)
92
- Smplkit::Jobs.call_api { @api.delete_job(id) }
202
+ Jobs.call_api { @api.delete_job(id) }
93
203
  nil
94
204
  end
95
205
 
@@ -98,16 +208,16 @@ module Smplkit
98
208
  # @param id [String]
99
209
  # @return [Smplkit::Jobs::Run]
100
210
  def run(id)
101
- resp = Smplkit::Jobs.call_api { @api.run_job_now(id) }
102
- Smplkit::Jobs::Run.from_resource(resp.data)
211
+ resp = Jobs.call_api { @api.run_job_now(id) }
212
+ Run.from_resource(resp.data)
103
213
  end
104
214
 
105
215
  # Current-period usage counters for the account.
106
216
  #
107
217
  # @return [Smplkit::Jobs::Usage]
108
218
  def usage
109
- resp = Smplkit::Jobs.call_api { @usage_api.get_usage }
110
- Smplkit::Jobs::Usage.from_resource(resp.data)
219
+ resp = Jobs.call_api { @usage_api.get_usage }
220
+ Usage.from_resource(resp.data)
111
221
  end
112
222
 
113
223
  # @api private — POST a new job. Called by {Smplkit::Jobs::Job#save} on
@@ -116,8 +226,8 @@ module Smplkit
116
226
  def _create_job(job)
117
227
  raise ArgumentError, "Job.id is required on create (caller-supplied key)" if job.id.nil? || job.id.empty?
118
228
 
119
- resp = Smplkit::Jobs.call_api { @api.create_job(build_create_body(job)) }
120
- Smplkit::Jobs::Job.from_resource(resp.data, client: self)
229
+ resp = Jobs.call_api { @api.create_job(build_create_body(job)) }
230
+ Job.from_resource(resp.data, client: self)
121
231
  end
122
232
 
123
233
  # @api private — Full-replace PUT for an existing job. Called by
@@ -129,8 +239,8 @@ module Smplkit
129
239
  def _update_job(job)
130
240
  raise ArgumentError, "cannot update a Job with no id" if job.id.nil?
131
241
 
132
- resp = Smplkit::Jobs.call_api { @api.update_job(job.id, build_body(job)) }
133
- Smplkit::Jobs::Job.from_resource(resp.data, client: self)
242
+ resp = Jobs.call_api { @api.update_job(job.id, build_body(job)) }
243
+ Job.from_resource(resp.data, client: self)
134
244
  end
135
245
 
136
246
  private
@@ -142,7 +252,7 @@ module Smplkit
142
252
  enabled: job.enabled,
143
253
  type: job.type,
144
254
  schedule: job.schedule,
145
- configuration: Smplkit::Jobs::HttpConfig.to_wire(job.configuration),
255
+ configuration: HttpConfig.to_wire(job.configuration),
146
256
  concurrency_policy: job.concurrency_policy
147
257
  )
148
258
  end
@@ -169,58 +279,7 @@ module Smplkit
169
279
  SmplkitGeneratedClient::Jobs::JobRequest.new(data: resource)
170
280
  end
171
281
  end
172
-
173
- # +mgmt.jobs.runs.*+ — read-only run history plus the cancel / rerun run
174
- # actions.
175
- class RunsNamespace
176
- def initialize(api)
177
- @api = api
178
- end
179
-
180
- # List runs for the authenticated account, newest first. Cursor
181
- # paginated (ADR-014): pass +page_size+ and the +after+ cursor from the
182
- # prior page. Pass +job+ to scope to a single job's history.
183
- #
184
- # @param job [String, nil] Filter to a single job's run history, by job id.
185
- # @param page_size [Integer, nil] Items per page (cursor pagination).
186
- # @param after [String, nil] Opaque cursor token from a prior page.
187
- # @return [Array<Smplkit::Jobs::Run>]
188
- def list(job: nil, page_size: nil, after: nil)
189
- opts = {}
190
- opts[:filter_job] = job unless job.nil?
191
- opts[:page_size] = page_size unless page_size.nil?
192
- opts[:page_after] = after unless after.nil?
193
-
194
- resp = Smplkit::Jobs.call_api { @api.list_runs(opts) }
195
- (resp.data || []).map { |r| Smplkit::Jobs::Run.from_resource(r) }
196
- end
197
-
198
- # Fetch a single run by id.
199
- #
200
- # @param run_id [String]
201
- # @return [Smplkit::Jobs::Run]
202
- def get(run_id)
203
- resp = Smplkit::Jobs.call_api { @api.get_run(run_id) }
204
- Smplkit::Jobs::Run.from_resource(resp.data)
205
- end
206
-
207
- # Cancel a pending run.
208
- #
209
- # @param run_id [String]
210
- # @return [Smplkit::Jobs::Run]
211
- def cancel(run_id)
212
- resp = Smplkit::Jobs.call_api { @api.cancel_run(run_id) }
213
- Smplkit::Jobs::Run.from_resource(resp.data)
214
- end
215
-
216
- # Re-run a prior run, spawning a new +RERUN+ run.
217
- #
218
- # @param run_id [String]
219
- # @return [Smplkit::Jobs::Run]
220
- def rerun(run_id)
221
- resp = Smplkit::Jobs.call_api { @api.rerun_run(run_id) }
222
- Smplkit::Jobs::Run.from_resource(resp.data)
223
- end
224
- end
225
282
  end
283
+
284
+ JobsClient = Jobs::JobsClient
226
285
  end