atlas_rb 1.1.1 → 1.1.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9660fb0f48db5601e75f8fb0579794cd398d42fbdbe1c2e849b67bb32569d9c1
4
- data.tar.gz: fa8f43e4f7577027c3368e30f4ebf5c231202edbcaa1004ef0711582925680ee
3
+ metadata.gz: 195a3c85a8653e6835bb472b7cda45847e254057075694e37ecfa779efe2dd39
4
+ data.tar.gz: ea58c157df06abcfa8d3f4c6b18fd00e5f87892a8b4231b526ac3e60a8e13510
5
5
  SHA512:
6
- metadata.gz: b98eab79df77eda36139468d6701ea8e56f5ae16ee85e3ef22635bc11f42aed762654bd9dbf02b87a4f8521bb4de335724b249c3700397d748572bd734bf62b4
7
- data.tar.gz: c8f565644a54f99e6110131e6d1b361c21f51e068c565837c5226d21eb700b488fa13e1be9e59d591b587b4303196c785abf0c1fc8bb5eec000840b1515f2961
6
+ metadata.gz: 2782eeb3e29454728e68e85144ba5046dd86d9b2ff58eea1cfd704bf2ce03e70f81e977a5b9ad5ffe4091d69d99225746ed2076e875891f358308038983cbfe6
7
+ data.tar.gz: 8dc180f51b17ffdb1feec818445573ec9c25eab3ee4e4245e9afb31f564a14dfbc93db40e3bd174a078e89f31bd57c240eb85b17f69828494ebaab3c0f23f9f4
data/.version CHANGED
@@ -1 +1 @@
1
- 1.1.1
1
+ 1.1.2
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- atlas_rb (1.1.1)
4
+ atlas_rb (1.1.2)
5
5
  faraday (~> 2.7)
6
6
  faraday-follow_redirects (~> 0.3.0)
7
7
  faraday-multipart (~> 1)
@@ -23,7 +23,7 @@ GEM
23
23
  net-http (~> 0.5)
24
24
  hashie (5.1.0)
25
25
  logger
26
- json (2.19.5)
26
+ json (2.19.7)
27
27
  logger (1.7.0)
28
28
  multipart-post (2.4.1)
29
29
  net-http (0.9.1)
@@ -173,6 +173,9 @@ module AtlasRb
173
173
  # `User:` header. Required for cerberus-token requests; legacy bearer
174
174
  # tokens still resolve without it.
175
175
  # @return [AtlasRb::Mash] the parsed JSON response.
176
+ # @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
177
+ # conflict that exhausted its internal retry budget (HTTP 409 with
178
+ # `error: "stale_resource"`).
176
179
  #
177
180
  # @example
178
181
  # AtlasRb::Collection.set_thumbnails(
@@ -179,6 +179,9 @@ module AtlasRb
179
179
  # `User:` header. Required for cerberus-token requests; legacy bearer
180
180
  # tokens still resolve without it.
181
181
  # @return [AtlasRb::Mash] the parsed JSON response.
182
+ # @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
183
+ # conflict that exhausted its internal retry budget (HTTP 409 with
184
+ # `error: "stale_resource"`).
182
185
  #
183
186
  # @example
184
187
  # AtlasRb::Community.set_thumbnails(
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ # Base error for atlas_rb. Subclassed for specific wire-level conditions
5
+ # that callers want to handle distinctly. Most non-2xx responses still
6
+ # flow through as Mashes today; we mint typed exceptions only where
7
+ # callers genuinely need to discriminate (currently: optimistic-lock
8
+ # conflicts that ActiveJob `retry_on` policies need to key on).
9
+ class Error < StandardError; end
10
+
11
+ # Raised when Atlas responds with HTTP 409 + `error: "stale_resource"`,
12
+ # indicating an optimistic-lock conflict that either (a) exhausted
13
+ # Atlas's internal retry budget for a retry-safe action, or (b) hit a
14
+ # retry-unsafe action and surfaced immediately.
15
+ #
16
+ # Callers (typically ActiveJob subclasses in Cerberus) handle this via:
17
+ #
18
+ # retry_on AtlasRb::StaleResourceError, attempts: 5, wait: :polynomially_longer
19
+ #
20
+ # The exception carries the resource_id and action from Atlas's envelope
21
+ # so failure logs are useful without needing the full HTTP response.
22
+ class StaleResourceError < Error
23
+ # @return [String, nil] the conflicted resource's ID, from the envelope.
24
+ attr_reader :resource_id
25
+
26
+ # @return [String, nil] the controller action that conflicted, from the
27
+ # envelope (e.g. `"update_thumbnails"`).
28
+ attr_reader :action
29
+
30
+ # @param message [String] human-readable conflict description.
31
+ # @param resource_id [String, nil] the conflicted resource's ID.
32
+ # @param action [String, nil] the controller action that conflicted.
33
+ def initialize(message, resource_id: nil, action: nil)
34
+ super(message)
35
+ @resource_id = resource_id
36
+ @action = action
37
+ end
38
+ end
39
+ end
@@ -59,6 +59,7 @@ module AtlasRb
59
59
  params: params,
60
60
  headers: headers
61
61
  ) do |f|
62
+ f.use AtlasRb::Middleware::RaiseOnStaleResource
62
63
  f.response :follow_redirects
63
64
  f.adapter Faraday.default_adapter
64
65
  end
@@ -103,6 +104,7 @@ module AtlasRb
103
104
  url: ENV.fetch("ATLAS_URL", nil),
104
105
  headers: headers
105
106
  ) do |f|
107
+ f.use AtlasRb::Middleware::RaiseOnStaleResource
106
108
  f.request :multipart
107
109
  f.request :url_encoded
108
110
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AtlasRb
4
+ # Faraday middleware namespace.
5
+ module Middleware
6
+ # Translates Atlas's structured optimistic-lock conflict response into a
7
+ # typed Ruby exception.
8
+ #
9
+ # Atlas surfaces an exhausted-retry (or retry-unsafe) optimistic-lock
10
+ # conflict as an HTTP `409 Conflict` whose JSON body carries the
11
+ # discriminator `error: "stale_resource"`. This middleware keys on the
12
+ # **status + discriminator pair** and raises {AtlasRb::StaleResourceError},
13
+ # carrying the envelope's `resource_id` and `action` through so callers'
14
+ # failure logs are useful without the full response.
15
+ #
16
+ # It is intentionally narrow: any other status, or a 409 without the
17
+ # discriminator, passes through untouched so the caller still sees the
18
+ # response as a Mash (see {AtlasRb::StaleResourceError} for the rationale —
19
+ # atlas_rb stays a thin Faraday binding and translates only the one wire
20
+ # signal Cerberus jobs need to discriminate on).
21
+ class RaiseOnStaleResource < Faraday::Middleware
22
+ # @param env [Faraday::Env] the completed response environment.
23
+ # @raise [AtlasRb::StaleResourceError] on a 409 whose body carries
24
+ # `error: "stale_resource"`.
25
+ # @return [void]
26
+ def on_complete(env)
27
+ return unless env.status == 409
28
+
29
+ body = parse_json(env.body)
30
+ return unless body.is_a?(Hash) && body["error"] == "stale_resource"
31
+
32
+ raise AtlasRb::StaleResourceError.new(
33
+ body["message"] || "Atlas reported a stale-resource conflict",
34
+ resource_id: body["resource_id"],
35
+ action: body["action"]
36
+ )
37
+ end
38
+
39
+ private
40
+
41
+ def parse_json(body)
42
+ return body if body.is_a?(Hash)
43
+
44
+ JSON.parse(body.to_s)
45
+ rescue JSON::ParserError
46
+ nil
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/atlas_rb/work.rb CHANGED
@@ -170,6 +170,9 @@ module AtlasRb
170
170
  # header. Falls through to {AtlasRb.config}.default_on_behalf_of when
171
171
  # omitted.
172
172
  # @return [Faraday::Response] the raw response. Status `200` on success.
173
+ # @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
174
+ # conflict that exhausted its internal retry budget (HTTP 409 with
175
+ # `error: "stale_resource"`).
173
176
  #
174
177
  # @example
175
178
  # AtlasRb::Work.complete("w-789")
@@ -243,6 +246,9 @@ module AtlasRb
243
246
  # `User:` header. Required for cerberus-token requests; legacy bearer
244
247
  # tokens still resolve without it.
245
248
  # @return [AtlasRb::Mash] the parsed JSON response.
249
+ # @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
250
+ # conflict that exhausted its internal retry budget (HTTP 409 with
251
+ # `error: "stale_resource"`).
246
252
  #
247
253
  # @example
248
254
  # AtlasRb::Work.set_thumbnails(
@@ -276,6 +282,9 @@ module AtlasRb
276
282
  # `User:` header. Required for cerberus-token requests; legacy bearer
277
283
  # tokens still resolve without it.
278
284
  # @return [AtlasRb::Mash] the parsed JSON response.
285
+ # @raise [AtlasRb::StaleResourceError] if Atlas reports an optimistic-lock
286
+ # conflict that exhausted its internal retry budget (HTTP 409 with
287
+ # `error: "stale_resource"`).
279
288
  #
280
289
  # @example
281
290
  # AtlasRb::Work.set_image_derivatives(
data/lib/atlas_rb.rb CHANGED
@@ -4,7 +4,9 @@ require "faraday"
4
4
  require "faraday/multipart"
5
5
  require "faraday/follow_redirects"
6
6
  require_relative "atlas_rb/version"
7
+ require_relative "atlas_rb/errors"
7
8
  require_relative "atlas_rb/configuration"
9
+ require_relative "atlas_rb/middleware/raise_on_stale_resource"
8
10
  require_relative "atlas_rb/faraday_helper"
9
11
  require_relative "atlas_rb/mash"
10
12
  require_relative "atlas_rb/authentication"
@@ -69,10 +71,8 @@ require_relative "atlas_rb/system/user"
69
71
  # AtlasRb::Blob.content(blob["id"]) { |chunk| f.write(chunk) }
70
72
  # end
71
73
  module AtlasRb
72
- # Generic error raised by future code paths; not currently used by any
73
- # resource class. Atlas errors today surface as raw `Faraday::Response`
74
- # objects or `JSON::ParserError`s on malformed bodies.
75
- class Error < StandardError; end
74
+ # The error hierarchy ({AtlasRb::Error}, {AtlasRb::StaleResourceError}) lives
75
+ # in `atlas_rb/errors.rb`, required above.
76
76
 
77
77
  # The gem-wide configuration instance. Lazily initialized — host
78
78
  # applications register defaults via {AtlasRb.configure}.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atlas_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cliff
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-27 00:00:00.000000000 Z
11
+ date: 2026-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -125,9 +125,11 @@ files:
125
125
  - lib/atlas_rb/community.rb
126
126
  - lib/atlas_rb/configuration.rb
127
127
  - lib/atlas_rb/delegate.rb
128
+ - lib/atlas_rb/errors.rb
128
129
  - lib/atlas_rb/faraday_helper.rb
129
130
  - lib/atlas_rb/file_set.rb
130
131
  - lib/atlas_rb/mash.rb
132
+ - lib/atlas_rb/middleware/raise_on_stale_resource.rb
131
133
  - lib/atlas_rb/resource.rb
132
134
  - lib/atlas_rb/system/user.rb
133
135
  - lib/atlas_rb/version.rb