Skip to content

feat(storage): define outbound stage abstractions and memory baseline #338

Description

@lykakis

Parent epic: #337
Delivery step 1; prerequisite for focused contracts #343 and #344, filesystem work #339/#345, and future PostgreSQL work #333.

Problem

Current HTTP/SMPP ingress acknowledges process-local queue insertion. Router and worker queues destructively dequeue messages; retries, multipart state, and asynchronous provider work are process-local. A durable source spool alone preserves acceptance, but resuming an expensive selected batch or a recorded destination requires separately defined storage boundaries. The existing code also injects concrete InMemoryQueueProvider in ingress, routing, worker startup and resource wiring.

Goal

Define the backend-neutral outbound storage architecture and deliver its first working memory/memory/memory vertical slice. Add the initial interfaces/classes, lifecycle coordinator/wiring, global backend selection and startup validation, and memory-backed implementations using the existing non-durable behavior. This first slice makes the abstraction executable and easy to review; #343 and #344 deepen the contracts and tests before physical backends are implemented.

Architecture and initial interfaces

Define three globally selected, startup-only stage roles, with public configuration semantics equivalent to:

sendium.sms.pending.backend=memory|file|postgresql
sendium.sms.router-queue.backend=memory|file|postgresql
sendium.sms.routed-work.backend=memory|file|postgresql

The API should expose pending admission/completion, bounded selection into a router backlog, destination recording/completion, lifecycle coordination, backend identity/readiness, and actionable failures, without leaking SQL, paths, CBOR, or physical queue classes. Choose clear interfaces, backend registration/selection, and a single startup profile validator; avoid building speculative durable operations or codecs in this issue.

accepted pending -> selected for router queue -> routed to destination(s) -> terminal completion
  • The accepted pending source remains authoritative until all destinations and required existing DLR handoff are terminal.
  • Selection chooses bounded eligible, priority-aware work; when persisted in a later backend, its committed batch is recoverable without repeating expensive selection. Taking work from an in-memory router queue is not a separate persisted state in this single-process design.
  • Routing records all chosen destinations, including copied routes. When persisted in a later backend, unfinished destinations resume without rerouting.
  • On graceful shutdown, return messages taken for routing but not yet assigned a destination to the router queue. Messages already routed remain with their chosen worker queue; drain unfinished in-flight worker work back to that queue. Before shutdown completes, persist each queue when its configured backend is durable so restart resumes at the correct stage. Memory-backed stages retain their documented non-durable behavior.
  • Document how HTTP/SMPP admission, multipart, routing/filters, worker dispatch, provider outcome and existing PostgreSQL DlrStorage cross the abstraction. Startup recovery, capacity/backpressure and ownership failures must be visible.

First working profile and rollout

Pending / selected router / routed work Future restart guarantee
memory/memory/memory Non-durable; available in this issue
file/memory/memory Recover accepted work; reselect and reroute (#339)
file/file/memory Recover selected batch; reroute (#345)
file/memory/file Reselect not-yet-routed work; recover destinations (#345)
file/file/file Recover selected batch and destinations (#345)

Durable profiles require surviving storage and remain at least once: provider submission before terminal completion may repeat. Retry count/delay, host/power-loss recovery and provider outcome checkpoints are not part of the initial lifecycle.

Deliverables and acceptance criteria

Out of scope

Detailed pending/multipart admission contract, versioned CBOR schema and tests (#343); detailed durable batch selection/routed-work transition and failure-boundary tests (#344); physical file formats and backends (#339/#345), PostgreSQL schema/queries (#333), DLR backend redesign, multi-process leases, and exactly-once provider delivery.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions