Class: AtlasRb::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/atlas_rb/configuration.rb

Overview

Holds gem-wide configuration registered via configure.

The configuration model is deliberately tiny: a handful of slots, all of which accept callables. The gem stays consumer-agnostic — it knows nothing about Rails, Devise, or any host application's request lifecycle — and instead lets the consumer hand it lambdas that resolve the per-request ambient context when a request is about to go out.

Slots

  • #default_nuid — callable that returns the acting user's NUID when a resource method is called without an explicit nuid: kwarg. Typically a lambda reading from ActiveSupport::CurrentAttributes in a Rails host (-> { Current.nuid }). Set to nil (the default) to disable the fall-through — callers must then pass nuid: explicitly.

  • #default_on_behalf_of — callable that returns the NUID an Atlas request is being made on behalf of, sent as the On-Behalf-Of: header. Used by the acting-as / view-as feature on the consumer side. nil (the default) sends no header.

Carve-outs

System-path calls under System route through FaradayHelper#system_connection, which never consults either slot — the SSO provisioning endpoint authenticates as the system fixture, not as the ambient user. Admin-path calls under Admin still consult the slots (the operator is a real user) but require an explicit confirm: kwarg as the friction marker for destructive intent.

Examples:

Rails host registration (typically in a config initializer)

AtlasRb.configure do |config|
  config.default_nuid         = -> { Current.nuid }
  config.default_on_behalf_of = -> { Current.on_behalf_of }
end

Instance Attribute Summary collapse

Instance Attribute Details

#assertion_signing_keyString, ...

Relay signing. When set, the regular relay path signs a short-lived assertion (ES256, sub = acting nuid) — identity is proven, not asserted. This is the relay credential: with no signing key configured (and no ATLAS_JWT), the transport raises AtlasRb::ConfigurationError.

Accepts either a value or a callable (resolved per request, so a Rails host can read it from request-scoped state / credentials). The value may be a PEM string or an OpenSSL::PKey; a PEM is parsed for you.

Examples:

Rails host (initializer), reading the EC private key from credentials

AtlasRb.configure do |config|
  config.assertion_signing_key = -> { Rails.application.credentials.cerberus_signing_key }
  config.assertion_signing_kid = -> { Rails.application.credentials.cerberus_signing_kid }
end


73
74
75
# File 'lib/atlas_rb/configuration.rb', line 73

def assertion_signing_key
  @assertion_signing_key
end

#assertion_signing_kidString, ...



78
79
80
# File 'lib/atlas_rb/configuration.rb', line 78

def assertion_signing_kid
  @assertion_signing_kid
end

#connection_max_requestsInteger?

Requests to send on one pooled socket before replacing it. nil (the default) means no cap, which is what a direct connection to Puma wants. Set it when something between the client and Puma caps requests per connection, because the request after that cap fails with ECONNRESET rather than reconnecting.



151
152
153
# File 'lib/atlas_rb/configuration.rb', line 151

def connection_max_requests
  @connection_max_requests
end

#connection_pool_sizeInteger?

Sockets the transport keeps open per Atlas host. Size it to the host's own concurrency — a consumer that fans out N reads per request thread wants N times its thread count, plus headroom — rather than to the net-http-persistent default of 256, which is a file-descriptor budget rather than a considered number. nil takes Transport::DEFAULT_POOL_SIZE.

Read when a connection is first built, so set it before the first Atlas call; changing it later has no effect until Transport.reset_connections!.



92
93
94
# File 'lib/atlas_rb/configuration.rb', line 92

def connection_pool_size
  @connection_pool_size
end

#default_accountProc?



55
56
57
# File 'lib/atlas_rb/configuration.rb', line 55

def 
  
end

#default_nuidProc?



42
43
44
# File 'lib/atlas_rb/configuration.rb', line 42

def default_nuid
  @default_nuid
end

#default_on_behalf_ofProc?



46
47
48
# File 'lib/atlas_rb/configuration.rb', line 46

def default_on_behalf_of
  @default_on_behalf_of
end

#open_timeoutNumeric, ...

Seconds to wait for a socket to open. nil takes Transport::DEFAULT_OPEN_TIMEOUT; false removes the deadline.

Set on every connection the gem builds, because Net::HTTP's 60s default is a fallback rather than a considered number, and a refused connect is the fast case anyway — this bounds the connect that hangs.



102
103
104
# File 'lib/atlas_rb/configuration.rb', line 102

def open_timeout
  @open_timeout
end

#read_retriesInteger?

Extra attempts a read gets when it fails in transport (a refused or reset connection, a timeout) — so 2 means three attempts in all. nil takes Transport::DEFAULT_READ_RETRIES; 0 disables retrying.

Only idempotent reads are replayed, and only on an exception: a response Atlas actually sent is never retried. The maintenance 503 is the case that matters there — its Retry-After is measured in minutes, so an in-band retry would ignore it and hammer the window instead of letting ReadOnlyModeError reach the caller.



142
143
144
# File 'lib/atlas_rb/configuration.rb', line 142

def read_retries
  @read_retries
end

#read_timeoutNumeric, ...

Seconds to wait for a response on the JSON and system connections. nil takes Transport::DEFAULT_READ_TIMEOUT; false removes the deadline.

This is the slot that protects the host, not the gem: a consumer that fans out several reads per request thread parks that thread — and its share of the socket pool — for as long as a hung Atlas keeps the socket open, so an unbounded read turns one degraded backend into a front-end outage. It is a per-socket-read deadline, not a whole-response budget, so a long streaming download is unaffected as long as bytes keep arriving.

A call that legitimately outlives the budget overrides it per request:

connection({}, nuid).get(path) { |req| req.options.timeout = 120 }


120
121
122
# File 'lib/atlas_rb/configuration.rb', line 120

def read_timeout
  @read_timeout
end

#upload_read_timeoutNumeric?

Seconds to wait for a response on the multipart connection. nil (the default) leaves it uncapped, because a multi-gigabyte binary upload has no defensible cap and those calls run in jobs rather than on a request thread.



128
129
130
# File 'lib/atlas_rb/configuration.rb', line 128

def upload_read_timeout
  @upload_read_timeout
end