atlas_rb 1.1.0 → 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 +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +2 -2
- data/lib/atlas_rb/collection.rb +3 -0
- data/lib/atlas_rb/community.rb +3 -0
- data/lib/atlas_rb/errors.rb +39 -0
- data/lib/atlas_rb/faraday_helper.rb +2 -0
- data/lib/atlas_rb/middleware/raise_on_stale_resource.rb +50 -0
- data/lib/atlas_rb/work.rb +24 -2
- data/lib/atlas_rb.rb +4 -4
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 195a3c85a8653e6835bb472b7cda45847e254057075694e37ecfa779efe2dd39
|
|
4
|
+
data.tar.gz: ea58c157df06abcfa8d3f4c6b18fd00e5f87892a8b4231b526ac3e60a8e13510
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2782eeb3e29454728e68e85144ba5046dd86d9b2ff58eea1cfd704bf2ce03e70f81e977a5b9ad5ffe4091d69d99225746ed2076e875891f358308038983cbfe6
|
|
7
|
+
data.tar.gz: 8dc180f51b17ffdb1feec818445573ec9c25eab3ee4e4245e9afb31f564a14dfbc93db40e3bd174a078e89f31bd57c240eb85b17f69828494ebaab3c0f23f9f4
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.1.
|
|
1
|
+
1.1.2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.1
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`depositor:` kwarg on `AtlasRb::Work.create`** — optional NUID
|
|
8
|
+
forwarded as the `depositor` query param on `POST /works`. When
|
|
9
|
+
omitted, behaviour is unchanged: Atlas defaults the depositor to the
|
|
10
|
+
acting user. When provided, Atlas stamps the named NUID as the Work's
|
|
11
|
+
`depositor` and records the acting user as the `proxy_uploader`.
|
|
12
|
+
|
|
13
|
+
Motivation: proxy deposit. Librarians and bulk-deposit jobs frequently
|
|
14
|
+
upload Works on behalf of a researcher who is the rightful credited
|
|
15
|
+
depositor. Until now there was no way to express that split through
|
|
16
|
+
the gem — callers had to choose between misattributing the deposit to
|
|
17
|
+
the librarian or dropping to a raw Faraday call. The depositor is
|
|
18
|
+
immutable post-create; there is no corresponding setter on the update
|
|
19
|
+
surface.
|
|
20
|
+
|
|
3
21
|
## 1.1.0
|
|
4
22
|
|
|
5
23
|
### Added
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
atlas_rb (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.
|
|
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)
|
data/lib/atlas_rb/collection.rb
CHANGED
|
@@ -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(
|
data/lib/atlas_rb/community.rb
CHANGED
|
@@ -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
|
@@ -93,6 +93,13 @@ module AtlasRb
|
|
|
93
93
|
# @param on_behalf_of [String, nil] optional NUID for the `On-Behalf-Of`
|
|
94
94
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
95
95
|
# omitted.
|
|
96
|
+
# @param depositor [String, nil] optional NUID to stamp on the new Work's
|
|
97
|
+
# `depositor` field. When omitted, Atlas defaults the depositor to the
|
|
98
|
+
# acting user (`nuid:`); this kwarg is the proxy / batch escape hatch
|
|
99
|
+
# where the librarian who uploaded the Work is distinct from the person
|
|
100
|
+
# it should be attributed to. The acting user becomes the Work's
|
|
101
|
+
# `proxy_uploader`. The depositor is immutable post-create; there is no
|
|
102
|
+
# setter on the update surface.
|
|
96
103
|
# @return [Hash] the created Work payload (post-update if `xml_path` was
|
|
97
104
|
# supplied).
|
|
98
105
|
#
|
|
@@ -105,9 +112,15 @@ module AtlasRb
|
|
|
105
112
|
# @example Retry-safe bulk-deposit create
|
|
106
113
|
# key = SecureRandom.uuid
|
|
107
114
|
# AtlasRb::Work.create("col-456", idempotency_key: key)
|
|
108
|
-
|
|
115
|
+
#
|
|
116
|
+
# @example Proxy deposit — librarian uploads on behalf of a researcher
|
|
117
|
+
# AtlasRb::Work.create("col-456", depositor: "000000123")
|
|
118
|
+
def self.create(id, xml_path = nil, idempotency_key: nil, nuid: nil,
|
|
119
|
+
on_behalf_of: nil, depositor: nil)
|
|
120
|
+
params = { collection_id: id }
|
|
121
|
+
params[:depositor] = depositor if depositor
|
|
109
122
|
result = AtlasRb::Mash.new(JSON.parse(
|
|
110
|
-
connection(
|
|
123
|
+
connection(params, nuid,
|
|
111
124
|
on_behalf_of: on_behalf_of, idempotency_key: idempotency_key).post(ROUTE)&.body
|
|
112
125
|
))["work"]
|
|
113
126
|
return result unless xml_path.present?
|
|
@@ -157,6 +170,9 @@ module AtlasRb
|
|
|
157
170
|
# header. Falls through to {AtlasRb.config}.default_on_behalf_of when
|
|
158
171
|
# omitted.
|
|
159
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"`).
|
|
160
176
|
#
|
|
161
177
|
# @example
|
|
162
178
|
# AtlasRb::Work.complete("w-789")
|
|
@@ -230,6 +246,9 @@ module AtlasRb
|
|
|
230
246
|
# `User:` header. Required for cerberus-token requests; legacy bearer
|
|
231
247
|
# tokens still resolve without it.
|
|
232
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"`).
|
|
233
252
|
#
|
|
234
253
|
# @example
|
|
235
254
|
# AtlasRb::Work.set_thumbnails(
|
|
@@ -263,6 +282,9 @@ module AtlasRb
|
|
|
263
282
|
# `User:` header. Required for cerberus-token requests; legacy bearer
|
|
264
283
|
# tokens still resolve without it.
|
|
265
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"`).
|
|
266
288
|
#
|
|
267
289
|
# @example
|
|
268
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
|
-
#
|
|
73
|
-
#
|
|
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.
|
|
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-
|
|
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
|