Skip to content

ATS-PFM-NOT-018Send association e-mail with retry and capacity control: Capability Test Specification

Markdown

ATS-PFM-NOT-018

Send association e-mail with retry and capacity control: Capability Test Specification

Markdown
  • DocumentProposed

KindAcceptance test setProduct areaPlatformModuleStaff Notifications and Association CommunicationsRevision2

Read atservices-platform ad3f6a65react-console baf6dae3

Coverage

  • Rule covered
  • Transition gap: FND-PFM-NOT-079
  • Validation covered
  • Permission covered
  • Edge covered
  • Failure covered
  • Boundary covered
  • Concurrency covered
  • Invariant covered
  • Interaction covered

Test Scenarios

15 scenarios proving CAP-PFM-NOT-018; 14 bound to an existing test.

01 Dispatch committed pointers with recoverable claimsconcurrencyapitest
Proves
BR-CAP-PFM-NOT-018-01
Preconditions
Pointer rows in two workspaces, more than one batch.
Steps
Dispatch accepted pointers, reject one queue publish, compete two runs and end a run at its time budget.
Expected
Acknowledged pointers publish in ascending creation order and are deleted; refused work returns later. Exclusive concurrent claims prevent duplicate taking, and time-limited remaining work waits for another run.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/dispatch-communications.integration.spec.js#publishes a pointer and nothing of the request: the version, the kind, the tenant and the key
services-platform:modules/communications/tests/integration/services/dispatch/dispatch-communications.integration.spec.js#offers it again once its claim has lapsed, and nothing on the row says it was ever refused
services-platform:modules/communications/tests/integration/services/dispatch/dispatch-communications.integration.spec.js#stops before it enters a tenant, so the run ends inside the function’s timeout
Source
services-platform:modules/communications/tests/integration/services/dispatch/dispatch-communications.integration.spec.js#publishes every row of the tenant it was given, oldest first
02 Skip final and temporarily ambiguous submissionsinvariantapitest
Proves
BR-CAP-PFM-NOT-018-02 INV-DOM-PFM-NOT-005-04
Preconditions
Prepare a request item processed once.
Steps
Replay the processed request and attempt to claim another message whose provider handoff may still be in flight.
Expected
Final messages are not resubmitted; the potentially in-flight message remains untouched during the ambiguity interval.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#answers in_flight for a submission that may still be with the provider, so it is never sent twice
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#skips a message already settled, so a repeated queue item never sends twice
Source
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#sends nothing a second time
03 Back off throttled sends and expose exhaustionfailureapinegativetest
Proves
BR-CAP-PFM-NOT-018-03
Preconditions
Prepare a request of three recipients and a throttling provider.
Steps
Throttle the initial receive, allow recovery, and exhaust a different request's recipient on its final receive.
Expected
Throttled drafts return with backoff and eligible sends complete in the retry fixture. At exhaustion the refused message fails and the item goes to dead-letter handling; remaining drafts are attempted only while invocation time remains.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#stops the rest of the request for this receive rather than pressing an unwell provider
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#gives the item back with the backoff of this receive, which SQS times and Postgres does not
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#still sends the e-mails the failure did not reach, so one bad recipient does not hold the rest
services-platform:modules/communications/tests/integration/services/dispatch/send-handler.integration.spec.js#extends the item’s visibility by the backoff of this receive, so SQS waits that long and not less
Source
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#stops the rest of the request for this receive rather than pressing an unwell provider
04 Redrive only exhausted sendstransitionapitest
Proves
BR-CAP-PFM-NOT-018-04
Preconditions
Prepare a dead-lettered request with one exhausted, one sent and one rejected e-mail.
Steps
Reoffer the exhausted item through operator redrive.
Expected
Only the exhausted message is submitted again for processing.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#leaves a message the provider refused for good alone, so a redrive never sends what was refused
Source
services-platform:modules/communications/tests/integration/services/dispatch/process-communication-request.integration.spec.js#offers the exhausted e-mail to the provider again
05 Apply expiry and recipient checks immediately before sendedgeapinegativetest
Proves
BR-CAP-PFM-NOT-018-05 INV-DOM-PFM-NOT-005-05
Preconditions
Prepare draft messages that are expired, newly suppressed after acceptance or addressed to a reserved domain.
Steps
Attempt provider-submission claims for all three messages.
Expected
Stale messages expire without attempts; newly suppressed and reserved-domain addresses are withheld with their respective reasons.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#withholds a message whose recipient was suppressed since acceptance, state and reason written together
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#withholds a draft to a reserved domain, as one accepted before the rule would be, under a policy that delivers to everybody
Source
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#expires a message whose expiry has passed, without an attempt
06 Recover uncertain submission after the waitboundaryapitest
Proves
BR-CAP-PFM-NOT-018-06
Preconditions
Prepare a message left submitting.
Steps
Attempt a claim before the ambiguity interval ends and another after it ends.
Expected
The message is initially left alone; after the interval it is claimed again and its unknown attempt is closed.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#answers in_flight for a submission that may still be with the provider, so it is never sent twice
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#claims it again once the ambiguity window has passed, the unknown attempt closed
Source
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#answers in_flight for a submission that may still be with the provider, so it is never sent twice
07 Allow cancellation only before submissionpermissionapinegativetest
Proves
BR-CAP-PFM-NOT-018-07
Preconditions
Prepare a draft, a withheld and a submitted message.
Steps
Try cancellation in every fixture state and repeat the accepted draft cancellation.
Expected
The draft becomes cancelled. Other states and repeated cancellation are rejected.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/e2e/messages.e2e.spec.js#refuses cancelling the same message twice as 400, it no longer being queued
services-platform:modules/communications/tests/e2e/messages.e2e.spec.js#refuses cancelling a message that was withheld rather than drafted as 400
services-platform:modules/communications/tests/integration/services/persistence/messages.integration.spec.js#refuses a message that has already been submitted, which cannot be recalled
Source
services-platform:modules/communications/tests/e2e/messages.e2e.spec.js#answers 200 and the message cancelled
08 Separate transactional and Marketing workboundaryapitest
Proves
BR-CAP-PFM-NOT-018-08
Preconditions
Prepare a marketing and a transactional request; an execution without the marketing queue.
Steps
Dispatch both, next without the marketing queue.
Expected
Each classification uses its own queue; Marketing remains pending when its queue is unavailable.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#leaves the marketing row for the next run, never publishing it to the other lane
services-platform:modules/communications/tests/unit/services/dispatch/lanes.spec.js#puts a purpose whose classification is marketing on the marketing lane
Source
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#publishes a marketing request to the marketing queue
09 Reserve lane capacity with one-way borrowingruleunittest
Proves
BR-CAP-PFM-NOT-018-09
Preconditions
Initialize lane token buckets using a known provider sending rate.
Steps
Consume Marketing capacity, exhaust transactional capacity and inspect a lane without a previously loaded rate.
Expected
Marketing cannot exceed sixty percent, transactional traffic borrows unused capacity and an unrated lane remains unlimited.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/unit/services/dispatch/lane-bucket.spec.js#lets the marketing lane take its 60 % and no more in one second
services-platform:modules/communications/tests/unit/services/dispatch/lane-bucket.spec.js#lets the transactional lane borrow the marketing lane’s unused tokens once its own are gone
services-platform:modules/communications/tests/unit/services/dispatch/lane-bucket.spec.js#never lets the marketing lane borrow the transactional lane’s reserved tokens
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#lets transactional mail borrow the marketing lane’s unused tokens once its own are gone
Source
services-platform:modules/communications/tests/unit/services/dispatch/lane-bucket.spec.js#lets the marketing lane take its 60 % and no more in one second
10 Delay rate-limited work without spending retriesedgeapitest
Proves
BR-CAP-PFM-NOT-018-10
Preconditions
Prepare a request larger than the bucket.
Steps
Process limited-budget work, replenish tokens and process the remainder.
Expected
Available capacity sends eligible messages; remaining drafts return with delay and later complete without repeating final messages.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#requeues the item rather than giving it back to the queue to spend a receive
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#acknowledges the original instead of reporting it a failure, even on its last receive
Source
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#sends the messages its tokens cover
11 Pause only Marketing near account quotatransitionapitest
Proves
BR-CAP-PFM-NOT-018-11
Preconditions
Prepare a account at 89, 90 and next 80 per cent of its quota.
Steps
Evaluate quota guard separately at each configured quota fixture.
Expected
The lane starts running, pauses by disabling its consumer at threshold while transactional mail continues, then resumes and processes held work.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#disables the marketing consumer’s queue mapping when it pauses and enables it when it resumes
Source
services-platform:modules/communications/tests/integration/services/persistence/lane-budgets.integration.spec.js#does not pause the marketing lane just below 90 %
12 Validate and attach unsubscribe metadatavalidationapinegativetest
Proves
BR-CAP-PFM-NOT-018-12
Preconditions
Prepare transactional and Marketing envelopes with present and absent subscription and unsubscribe metadata.
Steps
Submit every envelope and deliver only the accepted classifications.
Expected
Classification mismatches reject submission without queuing. Marketing messages contain unsubscribe headers; transactional messages do not.
Data
Use only records created and owned by this suite.
Bound to
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#refuses a marketing request without a subscription type, with the library’s message
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#refuses a marketing request without unsubscribe targets, with the library’s message
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#refuses a transactional request that carries a subscription type, with the library’s message
Source
services-platform:modules/communications/tests/integration/services/dispatch/marketing-lane.integration.spec.js#refuses a marketing request without a subscription type, with the library’s message
13 Submit each deliverable recipient in the normal lifecycleinteractionapitest
Proves
AS-JNY-PFM-NOT-006-02
Preconditions
Prepare a accepted request.
Steps
Repeat dispatch and consumption after the first completed run.
Expected
Each eligible contact receives one provider submission in the exercised path.
Data
The lifecycle suite's organization type, contacts and recording provider.
Bound to
Source
services-platform:modules/communications/tests/integration/lifecycle/contact-role-compliance-communication.integration.spec.js#publishes the request once, whatever its recipients turn out to be
14 Late protection and feedback constrain retry outcomesinteractionapiproposed
Proves
BR-CAP-PFM-NOT-018-05
Preconditions
Accept messages for two eligible recipients, then suppress one before claiming it and throttle the other once.
Steps
Run the send consumer, retry after backoff, report delivery and inspect attempts and final outcomes.
Expected
The newly protected message has no provider attempt. The other message submits through the retry path and retains provider delivery separately from dispatch state.
Data
A suite-owned workspace, named staff accounts and unique occurrence keys; external adapters record attempts without shared writes.
Source
rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-018-deliver-association-e-mail-reliably-and-within-sending.md#frontmatter,rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-019-record-what-became-of-each-e-mail.md#frontmatter,rhythm-v2-docs:specs/platform/notifications/planning/capabilities/CAP-PFM-NOT-020-protect-deliverability-and-the-associations-sending-address.md#frontmatter
15 Read supported communication queue items and reject malformed versionsboundaryunitnegativetest
Proves
BR-CAP-PFM-NOT-018-01
Preconditions
Prepare current request pointers, send items, earlier camel-case items, legacy message items and malformed input.
Steps
Serialize and parse each item shape using the communication queue helpers.
Expected
Current and supported earlier item shapes round-trip into the current contract. The parser identifies legacy message work and returns no supported item for malformed or unknown-version input.
Data
Pure queue item inputs in one process.
Bound to
Source
services-platform:modules/communications/tests/unit/services/dispatch/send-queue.spec.js#reads back exactly what the dispatcher published

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.