Failed sync work returned by Scrypath.failed_sync_work/2.
Each entry reports a stable Scrypath-owned identifier, operation kind,
retryability, and summarized reason. Recovery details are exposed through an
explicit Scrypath.Operator.RecoveryAction when durable replay is possible.
Enriched fields (additive, v1.3)
attempt/max_attempts— set from the Oban job whensource == :oban;nilfor Meilisearch task rows and any path without queue attempt metadata.reason_class— bounded operator-facing classification::transport,:validation,:backend_rejected,:queue_exhausted, or:unknown(default when signals are missing or ambiguous).last_attempt_at— mirrorsfailed_atfor every constructor path (soft alias for “when this failure was last observed”).
Telemetry
Each constructed row emits once:
:telemetry.execute(
[:scrypath, :operator, :failed_work, :observed],
%{count: 1},
metadata
)Required metadata keys: :reason_class, :schema, :mode.
Optional metadata keys (v1.3): :operation, :retryable? — same meanings as
the struct fields.
Treat schema module atoms and other rich metadata as unsafe for
low-cardinality metric labels (for example Prometheus or OTel attribute rules)
unless you aggregate or sample; they are appropriate for logs, traces, and
structured handlers that filter explicitly.
Rollups
reason_class_counts/1 summarizes a row list into per-class pileup counts. If
you filter rows for a view, compute counts from that same filtered list;
total then matches the filtered length, not an unfiltered source length.
Summary
Types
@type operation() :: :upsert | :delete | :unknown
@type reason_class() ::
:transport | :validation | :backend_rejected | :queue_exhausted | :unknown
@type state() :: :failed | :retrying
@type t() :: %Scrypath.Operator.FailedWork{ attempt: non_neg_integer() | nil, failed_at: DateTime.t() | nil, id: term(), last_attempt_at: DateTime.t() | nil, max_attempts: non_neg_integer() | nil, metadata: map(), mode: :inline | :manual | :oban | atom(), operation: operation(), reason: String.t() | nil, reason_class: reason_class() | nil, recovery: Scrypath.Operator.RecoveryAction.t() | nil, retryable?: boolean(), schema: module(), source: :meilisearch | :oban | atom(), state: state() }
Functions
@spec reason_class_counts([t()]) :: Scrypath.Operator.ReasonClassCounts.t()
@spec recovery_action(t()) :: Scrypath.Operator.RecoveryAction.t() | nil