| Safe Haskell | None |
|---|---|
| Language | GHC2021 |
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
- data MirrorQueue = MirrorQueue {
- enqueue :: MirrorJob -> IO (Either TransportFault ())
- receive :: IO (Either TransportFault [QueueMessage])
- ack :: ReceiptHandle -> IO (Either TransportFault ())
- extendVisibility :: ReceiptHandle -> Seconds -> IO (Either TransportFault ())
- deadLetter :: ReceiptHandle -> IO (Either TransportFault ())
- deliveryBudget :: DeliveryBudget
- deadLetterTerminus :: Either TransportFault DeadLetterTerminus
- noMirrorQueue :: MirrorQueue
- data MirrorJob = MirrorJob {}
- data RemoteSpanContext = RemoteSpanContext {}
- data QueueMessage = QueueMessage {}
- encodeJob :: MirrorJob -> Text
- decodeJob :: (Ecosystem -> Maybe Text -> Text -> Either Text PackageName) -> (Text -> Either Text RegistryUrl) -> Text -> Either Text MirrorJob
- data ReceiptHandle
- mkReceiptHandle :: Text -> ReceiptHandle
- unReceiptHandle :: ReceiptHandle -> Text
- newtype Seconds = Seconds Int
- data ReceiptLease = ReceiptLease {}
- data DeadLetterTerminus
- newtype DeliveryBudget = DeliveryBudget Int
- defaultDeliveryBudget :: DeliveryBudget
- effectiveDeliveryBudget :: DeliveryBudget -> DeadLetterTerminus -> DeliveryBudget
- retiringDelivery :: DeliveryBudget -> Int
- deliveryBudgetSpent :: DeliveryBudget -> QueueMessage -> Bool
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
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
| |
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
| |
Instances
| Show RemoteSpanContext Source # | |
Defined in Ecluse.Core.Queue Methods showsPrec :: Int -> RemoteSpanContext -> ShowS # show :: RemoteSpanContext -> String # showList :: [RemoteSpanContext] -> ShowS # | |
| Eq RemoteSpanContext Source # | |
Defined in Ecluse.Core.Queue Methods (==) :: RemoteSpanContext -> RemoteSpanContext -> Bool # (/=) :: RemoteSpanContext -> RemoteSpanContext -> Bool # | |
data QueueMessage Source #
A received message: the job to process and the handle that settles this delivery.
Constructors
| QueueMessage | |
Fields
| |
Instances
| Show QueueMessage Source # | |
Defined in Ecluse.Core.Queue Methods showsPrec :: Int -> QueueMessage -> ShowS # show :: QueueMessage -> String # showList :: [QueueMessage] -> ShowS # | |
| Eq QueueMessage Source # | |
Defined in Ecluse.Core.Queue | |
The payload's wire mapping
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.
Instances
| Show ReceiptHandle Source # | |
Defined in Ecluse.Core.Queue Methods showsPrec :: Int -> ReceiptHandle -> ShowS # show :: ReceiptHandle -> String # showList :: [ReceiptHandle] -> ShowS # | |
| Eq ReceiptHandle Source # | |
Defined in Ecluse.Core.Queue Methods (==) :: ReceiptHandle -> ReceiptHandle -> Bool # (/=) :: ReceiptHandle -> ReceiptHandle -> Bool # | |
| Ord ReceiptHandle Source # | |
Defined in Ecluse.Core.Queue Methods compare :: ReceiptHandle -> ReceiptHandle -> Ordering # (<) :: ReceiptHandle -> ReceiptHandle -> Bool # (<=) :: ReceiptHandle -> ReceiptHandle -> Bool # (>) :: ReceiptHandle -> ReceiptHandle -> Bool # (>=) :: ReceiptHandle -> ReceiptHandle -> Bool # max :: ReceiptHandle -> ReceiptHandle -> ReceiptHandle # min :: ReceiptHandle -> ReceiptHandle -> ReceiptHandle # | |
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
A duration in whole seconds, for extendVisibility. A 'newtype', so a
raw Int of seconds cannot pass for some other count.
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
| |
Instances
| Show ReceiptLease Source # | |
Defined in Ecluse.Core.Queue.Lease Methods showsPrec :: Int -> ReceiptLease -> ShowS # show :: ReceiptLease -> String # showList :: [ReceiptLease] -> ShowS # | |
| Eq ReceiptLease Source # | |
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. |
Instances
| Show DeadLetterTerminus Source # | |
Defined in Ecluse.Core.Queue Methods showsPrec :: Int -> DeadLetterTerminus -> ShowS # show :: DeadLetterTerminus -> String # showList :: [DeadLetterTerminus] -> ShowS # | |
| Eq DeadLetterTerminus Source # | |
Defined in Ecluse.Core.Queue Methods (==) :: DeadLetterTerminus -> DeadLetterTerminus -> Bool # (/=) :: DeadLetterTerminus -> DeadLetterTerminus -> Bool # | |
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 |
Instances
| Show DeliveryBudget Source # | |
Defined in Ecluse.Core.Queue Methods showsPrec :: Int -> DeliveryBudget -> ShowS # show :: DeliveryBudget -> String # showList :: [DeliveryBudget] -> ShowS # | |
| Eq DeliveryBudget Source # | |
Defined in Ecluse.Core.Queue Methods (==) :: DeliveryBudget -> DeliveryBudget -> Bool # (/=) :: DeliveryBudget -> DeliveryBudget -> Bool # | |
| Ord DeliveryBudget Source # | |
Defined in Ecluse.Core.Queue Methods compare :: DeliveryBudget -> DeliveryBudget -> Ordering # (<) :: DeliveryBudget -> DeliveryBudget -> Bool # (<=) :: DeliveryBudget -> DeliveryBudget -> Bool # (>) :: DeliveryBudget -> DeliveryBudget -> Bool # (>=) :: DeliveryBudget -> DeliveryBudget -> Bool # max :: DeliveryBudget -> DeliveryBudget -> DeliveryBudget # min :: DeliveryBudget -> DeliveryBudget -> DeliveryBudget # | |
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.