Raised or returned when a call could not be made because the service's concurrency limit was already fully in use.
This is an Errata infrastructure error. The same
value is returned in an {:error, error} tuple by ExternalService.call/3 and
raised by ExternalService.call!/3.
Its :context contains:
:service— the service the call was made against.:limit— the configured concurrency limit.:in_flight— how many slots were held when the call was rejected.
Only services configured with a :concurrency limit can produce this error.
Its http_status/1 is the default 503: unlike ExternalService.RateLimited,
this is not the external service refusing you, it is your own bulkhead shedding
load — a "Service Unavailable" from your application.
Because the wrapped function never ran, this does not melt the circuit
breaker and is not retried. Retrying immediately would only find the bulkhead
full again; shedding is the point. See ExternalService.Concurrency.
Like ExternalService.RateLimited, it is still retryable in Errata's sense —
the call is worth making again once in-flight calls drain — just not on the
spot.
Summary
Functions
Returns the stable external code for this error, or nil if it has none.
Returns the user-facing display message for this error (the :message field by default).
Returns the HTTP status code associated with this error (503 by default).
Returns this error's :context with sensitive values redacted (no keys declared).
Returns whether this error is considered retryable (true by default).
Returns the severity of this error (:error by default).
Types
@type t() :: Errata.infrastructure_error()
Functions
@spec code(Errata.error()) :: String.t() | nil
Returns the stable external code for this error, or nil if it has none.
No code is set for this error type. Set one with the :code option, or
override this function to derive a code from the error's :reason or
:context. See also Errata.code/1.
@spec display_message(Errata.error()) :: String.t() | nil
Returns the user-facing display message for this error (the :message field by default).
This is distinct from Exception.message/1, which also includes the error's :reason and is
aimed at developers. Override this function to compute a message from the error's :reason or
:context:
def display_message(%{context: %{order_id: id}}), do: "order #{id} does not exist"
def display_message(error), do: error.messageErrata.display_message/1 and Errata.to_map/1 both dispatch through this function, so an
override applies to the JSON encoding and to anything rendering the error for a user. See also
Errata.display_message/1.
@spec http_status(Errata.error()) :: non_neg_integer()
Returns the HTTP status code associated with this error (503 by default).
The default is derived from the error's kind, or set via the :http_status
option. Override this function to compute a status from the error's :reason
or :context. See also Errata.http_status/1.
@spec redact_context(Errata.error()) :: map()
Returns this error's :context with sensitive values redacted (no keys declared).
Called wherever Errata serializes the context — to_map/1 and the JSON
encoding, Errata.log/2 metadata, and Errata.report/2 telemetry metadata.
The error struct itself is left alone, so the real values remain available
locally for debugging.
Declared keys are redacted recursively and match whether written as atoms or
binaries. Set them with the :redact option, add a global floor with
config :errata, redact: [...], or override this function for full control.
See Errata.Redaction.
@spec retryable?(Errata.error()) :: boolean()
Returns whether this error is considered retryable (true by default).
The default is derived from the error's kind — :infrastructure errors are
retryable, :domain and :general errors are not — or set via the
:retryable option. Override this function to decide from the error's
:reason or :context. See also Errata.retryable?/1.
@spec severity(Errata.error()) :: Logger.level()
Returns the severity of this error (:error by default).
The severity is a Logger.level/0 and is the level at which Errata.log/2
logs the error when no level is given explicitly. Set it with the :severity
option, or override this function to compute a severity from the error's
:reason or :context. See also Errata.severity/1.