ecluse:ecluse-core
Safe HaskellNone
LanguageGHC2021

Ecluse.Core.Queue

Description

The mirror-queue handle: the durable hand-off from the request path to the mirror worker.

Mirroring is demand-driven, so the serve path enqueues a MirrorJob and answers at once while a worker receives it, verifies the artifact, publishes it and acks. At-least-once delivery is safe because publishing is idempotent, which is why retry is "do not ack" and there is no nack. This cloud surface is the one whose API differs materially per provider, so it is a record of functions and ReceiptHandle is opaque. See docs/architecture/cloud-backends.md, "Mirror Queue".

Synopsis

Queue handle

data MirrorQueue Source #

The mirror-queue handle: a record of functions over a backend whose state the closures capture. Every operation reports failure as an TransportFault value.

Constructors

MirrorQueue 

Fields

noMirrorQueue :: MirrorQueue Source #

The inert queue a deployment with zero mirroring mounts carries, so the composition-root Env keeps its shape. Reached anyway, enqueue refuses with a typed fault rather than crashing.

Payloads

data MirrorJob Source #

Everything the worker needs to back-fill one artifact into the mirror target. The payload is a trust boundary: it carries selection keys and never authority, so no digest, no size.

Constructors

MirrorJob 

Fields

Instances

Instances details
Show MirrorJob Source # 
Instance details

Defined in Ecluse.Core.Queue

Eq MirrorJob Source # 
Instance details

Defined in Ecluse.Core.Queue

data RemoteSpanContext Source #

The traceparent and tracestate of the enqueueing span, verbatim. The queue never parses them, so an unparseable carrier yields no span link rather than a decode failure.

Constructors

RemoteSpanContext 

Fields

  • rscTraceparent :: Text

    The W3C traceparent header value of the enqueueing span.

  • rscTracestate :: Text

    The W3C tracestate value (possibly empty), so vendor trace state survives the hop.

data QueueMessage Source #

A received message: the job to process and the handle that settles this delivery.

Constructors

QueueMessage 

Fields

Instances

Instances details
Show QueueMessage Source # 
Instance details

Defined in Ecluse.Core.Queue

Eq QueueMessage Source # 
Instance details

Defined in Ecluse.Core.Queue

The payload's wire mapping

encodeJob :: MirrorJob -> Text Source #

Encode a MirrorJob as the JSON text of a queue message body, the inverse of decodeJob. The identity rides as a namespace and a base name, so a namespaced name round-trips on any ecosystem.

decodeJob Source #

Arguments

:: (Ecosystem -> Maybe Text -> Text -> Either Text PackageName)

Read a wire namespace and base name through the ecosystem's own grammar.

-> (Text -> Either Text RegistryUrl)

Re-form the artifact URL's validated https egress witness.

-> Text 
-> Either Text MirrorJob 

Decode a queue message body back into a MirrorJob. The payload is a trust boundary, so the name, the filename, and the artifact URL each go back through their own gate.

Opaque receipt

data ReceiptHandle Source #

The backend's own delivery token (an SQS receipt handle, a Pub/Sub ackId). The constructor is hidden, so worker code only takes one from a QueueMessage that receive returned.

mkReceiptHandle :: Text -> ReceiptHandle Source #

Wrap a backend's delivery token. For backend implementations only.

unReceiptHandle :: ReceiptHandle -> Text Source #

Recover a backend's delivery token to pass back to it. For backend implementations only.

Durations and the receipt lease

newtype Seconds Source #

A duration in whole seconds, for extendVisibility. A 'newtype', so a raw Int of seconds cannot pass for some other count.

Constructors

Seconds Int 

Instances

Instances details
Show Seconds Source # 
Instance details

Defined in Ecluse.Core.Queue.Lease

Eq Seconds Source # 
Instance details

Defined in Ecluse.Core.Queue.Lease

Methods

(==) :: Seconds -> Seconds -> Bool #

(/=) :: Seconds -> Seconds -> Bool #

Ord Seconds Source # 
Instance details

Defined in Ecluse.Core.Queue.Lease

data ReceiptLease Source #

What one delivery's lease grants: the window it stays hidden for, when that window lapses, and the ceiling the backend holds the whole receipt under.

Constructors

ReceiptLease 

Fields

  • rlWindow :: Seconds

    The window the backend granted, which each renewal asks for again.

  • rlExpiresAt :: MonoTime

    When the current window lapses and another consumer may take the delivery.

  • rlCeilingAt :: MonoTime

    The last instant the backend holds this receipt at all, however often it is renewed (SQS allows twelve hours from the first receipt).

Instances

Instances details
Show ReceiptLease Source # 
Instance details

Defined in Ecluse.Core.Queue.Lease

Eq ReceiptLease Source # 
Instance details

Defined in Ecluse.Core.Queue.Lease

Dead-letter terminus and the redelivery budget

data DeadLetterTerminus Source #

Whether a queue has somewhere that captures a message the worker can never mirror. Without one the message cycles until the queue's retention window discards it unseen.

Constructors

TerminusAttached (Maybe DeliveryBudget)

A terminus captures poison messages, at this capture count when the backend reports one.

TerminusAbsent

Nothing captures poison messages: the worker's budget is the only terminus.

newtype DeliveryBudget Source #

How many deliveries of one message a queue grants before the worker itself retires it. A 'newtype', so no caller confuses a count of receives with some other Int.

Constructors

DeliveryBudget Int 

defaultDeliveryBudget :: DeliveryBudget Source #

The redelivery budget a backend holds when the operator configures none: five deliveries, SQS's own redrive convention, pinned to this same value in config/default.yaml.

effectiveDeliveryBudget :: DeliveryBudget -> DeadLetterTerminus -> DeliveryBudget Source #

The budget the worker enforces: the configured floor, raised past an attached terminus's capture count, so the dead-letter queue always captures a poison message first.

retiringDelivery :: DeliveryBudget -> Int Source #

The delivery a budget retires on: the configured value, floored at two, so a first delivery never spends it. The verdict and the worker's alarm read this one number, so they cannot disagree.

deliveryBudgetSpent :: DeliveryBudget -> QueueMessage -> Bool Source #

Whether this delivery spends the queue's redelivery budget. A backend supplies the count (msgReceiveCount), never the verdict.