Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Payload Kinds

A payload kind is an optional Text label stored with each job. Arbiter calls kindOf during insertion. Kind labels support job filters, queue statistics, metrics, traces, and the admin UI.

HasKind defines the label for one payload and the finite set of labels for its payload type:

MemberTypeDescription
kindOfpayload -> Maybe TextReturns the label for a payload.
kindsFor[Text]Lists all labels returned by kindOf.

The fallback instance for a payload type returns Nothing and an empty list. Declare a payload-specific instance to enable kind labels.

Constructor Labels

The generic implementation uses data-constructor names. Derive Generic and declare an empty instance:

data EmailPayload
  = SendWelcome UserId
  | SendReceipt OrderId
  deriving stock (Generic)

instance HasKind EmailPayload

For this instance, kindOf (SendReceipt 7) returns Just "SendReceipt" and kindsFor @EmailPayload returns ["SendWelcome", "SendReceipt"].

Custom Labels

Implement both members when constructor names are not suitable:

data EmailKind = Welcome | Receipt | PasswordReset
  deriving stock (Bounded, Enum, Show)

emailKindText :: EmailKind -> Text
emailKindText = T.toLower . T.pack . show

data EmailPayload = EmailPayload
  { emailKind :: EmailKind
  , emailTo :: Text
  }

instance HasKind EmailPayload where
  kindOf = Just . emailKindText . emailKind
  kindsFor = map emailKindText [minBound .. maxBound]

For this instance, kindOf (EmailPayload Receipt "a@b.c") returns Just "receipt". kindsFor @EmailPayload returns ["welcome", "receipt", "passwordreset"].

kindsFor must contain each non-Nothing value that kindOf can return. Arbiter excludes undeclared labels from kind metrics and the kindCounts statistics field.

Labels from a Nested Type

constructorKind and constructorKinds read the constructors of any Generic type. They do not require a HasKind instance on that type.

data Envelope = Envelope
  { envelopeTraceId :: Text
  , envelopePayload :: EmailPayload
  }

instance HasKind Envelope where
  kindOf = Just . constructorKind . envelopePayload
  kindsFor = constructorKinds @EmailPayload

This form supports wrapper payloads and external sum types without an orphan HasKind instance.

Label Use

InterfaceLabel source
GET /api/v1/:queue/jobs?kind= and the equivalent DLQ and archive filtersStored job label
GET /api/v1/:queue/kindskindsFor
Admin UI kind columnStored job label
Admin UI kind filterkindsFor
GET /api/v1/:queue/stats field kindCountsStored labels declared by kindsFor
arbiter.queue.depth_by_kindStored labels declared by kindsFor
arbiter.jobs.* metrics and the handler histogramStored labels declared by kindsFor
Producer span attribute arbiter.kindkindOf
Consumer span attribute arbiter.kindStored job label

The finite kindsFor set limits metric cardinality. Span attributes can include an undeclared label.

API details: Arbiter.Core.Job.Kind.