ecluse
Safe HaskellNone
LanguageGHC2021

Ecluse.Queue.Sqs

Description

The AWS SQS backend behind the MirrorQueue handle.

Maps the handle's receive → process → ack shape onto SQS:

  • enqueueSendMessage (the MirrorJob encoded as the message body),
  • receive → one long-poll ReceiveMessage (a batch, [] on an empty poll),
  • ackDeleteMessage (the message is gone, never redelivered),
  • extendVisibilityChangeMessageVisibility (hold a long publish).

The provider differences SQS embodies — the visibility timeout, the long-poll window, the batch limit — are SqsConfig knobs with sane defaults, and the SQS receipt handle is carried opaquely in a ReceiptHandle (via mkReceiptHandle), so none of it leaks past the handle. Retry is "don't ack": a job whose processing fails is simply not acked, and SQS redelivers it once the visibility timeout lapses; persistent failures fall to the queue's native dead-letter (max-receive-count), so there is no nack (see Ecluse.Queue).

The amazonka Env is built once at newSqsQueue and captured by the handle's closures, so the backend's state never reaches the proxy's Env/App (see docs/architecture/technology-stack.md → "Key Decisions"). The MirrorJob wire mapping is a plain JSON object, decoded on receive; a body that fails to parse is dropped rather than yielded as a partial, so — like any message left unprocessed — it is not acked and SQS redelivers it, ultimately to the dead-letter queue.

The SQS queue is a trusted, operator-declared destination (the configured queue URL, or an endpoint override): like the OTLP telemetry endpoint (see Ecluse.Telemetry.Resolve), it is reached through amazonka's own client and is not subject to the data-plane egress controls (the host allowlist, the internal-range block, or the resolved-IP recheck of Ecluse.Security.Egress), which guard only untrusted package downloads — never a destination the operator configured.

Synopsis

Configuration

data SqsConfig Source #

What the SQS backend needs. The batch size, long-poll window, and visibility timeout are provider knobs (see Ecluse.Queue) with defaults in defaultSqsConfig.

Constructors

SqsConfig 

Fields

  • sqsQueueUrl :: Text

    The fully-qualified SQS queue URL mirror jobs are sent to and received from.

  • sqsRegion :: Text

    The AWS region the queue lives in (e.g. "us-east-1").

  • sqsEndpoint :: Maybe SqsEndpoint

    An endpoint override for an emulator or VPC endpoint; Nothing uses amazonka's default resolution and the ambient credential chain.

  • sqsBatchSize :: Int

    Maximum messages to pull per receive (SQS caps this at 10). A larger batch amortises the round-trip when the queue is busy.

  • sqsWaitSeconds :: Int

    The long-poll window in seconds (SQS caps this at 20): how long a receive waits for a message before returning [], so an idle worker does not hot-loop on empty polls.

  • sqsVisibilityTimeout :: Seconds

    How long a received message stays hidden from other receives before SQS redelivers it — the budget for processing-then-ack, extendable per message via extendVisibility.

Instances

Instances details
Show SqsConfig Source # 
Instance details

Defined in Ecluse.Queue.Sqs

Eq SqsConfig Source # 
Instance details

Defined in Ecluse.Queue.Sqs

data SqsEndpoint Source #

Where an SQS-compatible endpoint lives, for pointing the backend at a non-default host: a local emulator (ministack) in tests, or a VPC endpoint. A Nothing sqsEndpoint uses amazonka's default resolution and the ambient AWS credential chain; an override needs explicit credentials because an emulator is off that chain.

Constructors

SqsEndpoint 

Fields

  • endpointSecure :: Bool

    Whether to connect over HTTPS (an emulator is usually plain HTTP).

  • endpointHost :: Text

    The host to connect to (e.g. "localhost").

  • endpointPort :: Int

    The port to connect to (e.g. 4566 for ministack).

  • endpointAccessKey :: Text

    A throwaway access key id the emulator accepts (real SQS uses the chain).

  • endpointSecretKey :: Secret

    The matching secret key, held as a redacted Secret so it never reaches the derived Show of this record (the secret-redaction guarantee must survive even on an off-path log/error).

Instances

Instances details
Show SqsEndpoint Source # 
Instance details

Defined in Ecluse.Queue.Sqs

Eq SqsEndpoint Source # 
Instance details

Defined in Ecluse.Queue.Sqs

defaultSqsConfig :: Text -> Text -> SqsConfig Source #

A SqsConfig for a queue URL and region with the provider knobs at sane defaults: a full batch of 10, the maximum 20-second long poll, and a 30-second visibility timeout. Override the record fields to tune them, or set sqsEndpoint to target an emulator.

The backend

newSqsQueue :: SqsConfig -> IO MirrorQueue Source #

Build an SQS-backed MirrorQueue. The amazonka Env is constructed once here — region-scoped, and pointed at sqsEndpoint with its throwaway credentials when one is given, otherwise discovering the ambient AWS credential chain — and captured by the returned handle's closures.

Job wire mapping

encodeJob :: MirrorJob -> Text Source #

Encode a MirrorJob as the JSON text of an SQS message body. The inverse of decodeJob: the package identity is split into its ecosystem, optional scope, and bare name so it round-trips through mkPackageName, and the version keeps its raw string. The serve-time-admitted artifact descriptor (jobArtifact) — the filename, the integrity digests, and the declared size — round-trips as a nested object so the worker has the digest to verify the fetched bytes against and the inputs to assemble the publish document.

decodeJob :: Text -> Either Text MirrorJob Source #

Decode an SQS message body back into a MirrorJob, or a human-readable error if the body is not the JSON object encodeJob produces (a missing field, an unknown ecosystem, an empty hash list, malformed JSON).