keiro
Safe HaskellNone
LanguageGHC2024

Keiro.Inbox.Types

Description

Shared types for the idempotent integration-event inbox.

The inbox lives in the consuming bounded context. When a Kafka consumer receives an integration event, the inbox records a stable external identity for that message and runs the local handler in the same transaction. Duplicate redeliveries (Kafka offset retry, rebalance, producer republish) become observable as duplicates instead of re-running the handler.

Synopsis

Documentation

newtype RetryDelay #

Delay before retry.

Constructors

RetryDelay 

Instances

Instances details
Show RetryDelay # 
Instance details

Defined in Shibuya.Core.Ack

Eq RetryDelay # 
Instance details

Defined in Shibuya.Core.Ack

data InboxDedupePolicy Source #

Which identity is used as the inbox primary key for an IntegrationEvent.

  • PreferIntegrationMessageId (default) — use the application-level messageId minted at the producer's outbox enqueue. EP-19 / EP-20 keep this id stable across publish retries, so it is the natural primary dedupe key for Kafka-delivered events.
  • PreferSourceEventIdentity — use the sourceEventId of the private event that produced this integration event. Useful when a producer may emit the same logical fact under different messageIds (e.g. schema-upgrade republish), and the consumer wants those republishes collapsed to a single handler run.
  • KafkaDeliveryIdentity — use the Kafka topic-partition-offset triple as the dedupe key. Fallback only when neither messageId nor source identity is available. This identifies one broker delivery, not one logical producer message: if a producer republishes the same logical message, Kafka assigns a new offset and this policy will not collapse the republish.
  • CustomDedupeKey — caller supplies the key. Use only when the other policies cannot represent the identity scheme; the consuming service owns key collision resistance.

Instances

Instances details
Generic InboxDedupePolicy Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep InboxDedupePolicy 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxDedupePolicy = D1 ('MetaData "InboxDedupePolicy" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) ((C1 ('MetaCons "PreferIntegrationMessageId" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "PreferSourceEventIdentity" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "KafkaDeliveryIdentity" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "CustomDedupeKey" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text))))
Show InboxDedupePolicy Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq InboxDedupePolicy Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxDedupePolicy Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxDedupePolicy = D1 ('MetaData "InboxDedupePolicy" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) ((C1 ('MetaCons "PreferIntegrationMessageId" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "PreferSourceEventIdentity" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "KafkaDeliveryIdentity" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "CustomDedupeKey" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text))))

data InboxPersistence Source #

How much of the integration-event envelope the inbox persists on the success path.

The failure path always persists the full envelope because a failed inbox row is the operator's dead-letter record.

Instances

Instances details
Generic InboxPersistence Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep InboxPersistence 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxPersistence = D1 ('MetaData "InboxPersistence" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "PersistFullEnvelope" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "PersistDedupeOnly" 'PrefixI 'False) (U1 :: Type -> Type))
Show InboxPersistence Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq InboxPersistence Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxPersistence Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxPersistence = D1 ('MetaData "InboxPersistence" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "PersistFullEnvelope" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "PersistDedupeOnly" 'PrefixI 'False) (U1 :: Type -> Type))

data InboxStatus Source #

Lifecycle state of an inbox row.

  • InboxProcessing — legacy on-disk state from older wrappers and reserved for future async paths. Current single-transaction intake inserts fresh successful rows directly as InboxCompleted.
  • InboxCompleted — handler ran to completion; terminal.
  • InboxFailed — handler signaled a permanent failure; terminal. The caller is responsible for operator action (dead-letter, manual retry).

Instances

Instances details
Generic InboxStatus Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep InboxStatus 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxStatus = D1 ('MetaData "InboxStatus" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "InboxProcessing" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "InboxCompleted" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "InboxFailed" 'PrefixI 'False) (U1 :: Type -> Type)))
Show InboxStatus Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq InboxStatus Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxStatus Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxStatus = D1 ('MetaData "InboxStatus" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "InboxProcessing" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "InboxCompleted" 'PrefixI 'False) (U1 :: Type -> Type) :+: C1 ('MetaCons "InboxFailed" 'PrefixI 'False) (U1 :: Type -> Type)))

data InboxResult a Source #

The classified outcome of runInboxTransaction.

  • 'InboxProcessed a' — first delivery; handler ran and returned a.
  • InboxDuplicate — a previous delivery already completed; handler not run.
  • InboxInProgress — a previous attempt is currently in-flight, or a legacy processing row was read. Current single-transaction intake does not commit processing rows. Treat as transient.
  • InboxPreviouslyFailed — a previous attempt recorded a permanent failure. Operator should review before reprocessing.

Instances

Instances details
Generic (InboxResult a) Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep (InboxResult a) 
Instance details

Defined in Keiro.Inbox.Types

type Rep (InboxResult a) = D1 ('MetaData "InboxResult" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) ((C1 ('MetaCons "InboxProcessed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a)) :+: C1 ('MetaCons "InboxDuplicate" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "InboxInProgress" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "InboxPreviouslyFailed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe Text))) :+: C1 ('MetaCons "InboxHandlerFailed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int)))))

Methods

from :: InboxResult a -> Rep (InboxResult a) x #

to :: Rep (InboxResult a) x -> InboxResult a #

Show a => Show (InboxResult a) Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq a => Eq (InboxResult a) Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep (InboxResult a) Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep (InboxResult a) = D1 ('MetaData "InboxResult" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) ((C1 ('MetaCons "InboxProcessed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 a)) :+: C1 ('MetaCons "InboxDuplicate" 'PrefixI 'False) (U1 :: Type -> Type)) :+: (C1 ('MetaCons "InboxInProgress" 'PrefixI 'False) (U1 :: Type -> Type) :+: (C1 ('MetaCons "InboxPreviouslyFailed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 (Maybe Text))) :+: C1 ('MetaCons "InboxHandlerFailed" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int)))))

data InboxError Source #

Errors surfaced by the inbox wrapper that originate from the inbox itself rather than from the supplied handler.

Constructors

DedupePolicyUnsatisfied !InboxDedupePolicy

The integration event lacked the field required by the chosen policy.

Instances

Instances details
Generic InboxError Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep InboxError 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxError = D1 ('MetaData "InboxError" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "DedupePolicyUnsatisfied" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 InboxDedupePolicy)))
Show InboxError Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq InboxError Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxError Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxError = D1 ('MetaData "InboxError" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "DedupePolicyUnsatisfied" 'PrefixI 'False) (S1 ('MetaSel ('Nothing :: Maybe Symbol) 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 InboxDedupePolicy)))

data InboxRow Source #

One row read back from keiro_inbox.

Rows written with PersistDedupeOnly decode with an empty IntegrationEvent payloadBytes, no attributes, no trace context, and no schema reference. Identity, routing, source-event ids, occurrence time, and Kafka delivery metadata are still preserved.

Constructors

InboxRow 

Instances

Instances details
Generic InboxRow Source # 
Instance details

Defined in Keiro.Inbox.Types

Methods

from :: InboxRow -> Rep InboxRow x #

to :: Rep InboxRow x -> InboxRow #

Show InboxRow Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq InboxRow Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep InboxRow Source # 
Instance details

Defined in Keiro.Inbox.Types

data KafkaDeliveryRef Source #

Optional Kafka-delivery metadata recorded alongside an inbox row.

Used by KafkaDeliveryIdentity to compute the dedupe key, and stored on the row regardless of policy so operators can correlate the inbox record with Kafka logs. Not part of the EP-19 envelope.

Constructors

KafkaDeliveryRef 

Fields

Instances

Instances details
Generic KafkaDeliveryRef Source # 
Instance details

Defined in Keiro.Inbox.Types

Associated Types

type Rep KafkaDeliveryRef 
Instance details

Defined in Keiro.Inbox.Types

type Rep KafkaDeliveryRef = D1 ('MetaData "KafkaDeliveryRef" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "KafkaDeliveryRef" 'PrefixI 'True) (S1 ('MetaSel ('Just "topic") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: (S1 ('MetaSel ('Just "partition") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int64) :*: S1 ('MetaSel ('Just "offset") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int64))))
Show KafkaDeliveryRef Source # 
Instance details

Defined in Keiro.Inbox.Types

Eq KafkaDeliveryRef Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep KafkaDeliveryRef Source # 
Instance details

Defined in Keiro.Inbox.Types

type Rep KafkaDeliveryRef = D1 ('MetaData "KafkaDeliveryRef" "Keiro.Inbox.Types" "keiro-0.11.0.0-inplace" 'False) (C1 ('MetaCons "KafkaDeliveryRef" 'PrefixI 'True) (S1 ('MetaSel ('Just "topic") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Text) :*: (S1 ('MetaSel ('Just "partition") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int64) :*: S1 ('MetaSel ('Just "offset") 'NoSourceUnpackedness 'SourceStrict 'DecidedStrict) (Rec0 Int64))))

dedupeKeyFor :: InboxDedupePolicy -> IntegrationEvent -> Maybe KafkaDeliveryRef -> Either InboxError Text Source #

Compute the inbox dedupe key for an integration event under the given policy plus optional Kafka delivery context. Returns Left when the policy demands a field the envelope does not carry (for example, PreferSourceEventIdentity on an envelope with no sourceEventId).