Skip to content

Commit 2e37606

Browse files
committed
Add ADR047: Compute submission status from delivery timestamps
Introduces a new architectural decision record (ADR047) outlining replacing the fixed delivery_status enum with a computed status method based on delivery timestamps allowing us to make S3 submission async.
1 parent 4ca04da commit 2e37606

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# ADR047: Compute submission status from delivery timestamps
2+
3+
Date: 2025-12-04
4+
5+
## Status
6+
7+
Proposed
8+
9+
## Context
10+
11+
We are making submission delivery asynchronous for all submission methods (email and S3) and we need a more robust way to track the delivery status of submissions in forms-runner.
12+
13+
### Using the Submission model for all submission types
14+
15+
To make S3 submissions asynchronous, we need to use the `Submission` model for S3 submissions. Currently, only email submissions create `Submissions`. The model only supports `pending` or `bounced` values for the `delivery_status` enum - there is no `delivered` status. This would make it difficult for S3 submission to use the `Submission` model, as we would need a way see which Submission are successful versus those that may need to be retried.
16+
17+
### Handling race conditions with async notifications
18+
19+
For email submissions, delivery and bounce notifications are processed asynchronously. This creates a race condition: we may receive and process these notifications out of order. Using timestamps for `delivered_at` and `bounced_at` allows us to accurately determine the sequence of events. We can only mark a submission as `delivered` if we can confirm that any bounce notification didn't occur after the successful delivery notification (i.e. an async bounce).
20+
21+
## Decision
22+
23+
We will replace the fixed `delivery_status` enum attribute with a computed `status` method that derives the submission status from `delivered_at` and `bounced_at` timestamp columns.
24+
25+
The implementation will proceed in three phases:
26+
27+
1. **Add new timestamp column**: Add the `bounced_at` attribute to the `Submission` model via a database migration (the `delivered_at` column already exists).
28+
29+
2. **Switch to computed status**: Replace usage of `delivery_status` with the computed `status` method throughout the codebase. The `status` method will return one of three values:
30+
- `:pending` - when both `delivered_at` and `bounced_at` are nil
31+
- `:delivered` - when `delivered_at` is present and either `bounced_at` is nil or `delivered_at` is more recent
32+
- `:bounced` - when `bounced_at` is present and either `delivered_at` is nil or `bounced_at` is more recent
33+
34+
The 'delivered_at' and 'bounced_at' should represent the most recent delivery attempt. I.e. set to nil when a new delivery attempt is made.
35+
36+
3. **Remove legacy column**: Remove the `delivery_status` enum attribute and its database column.
37+
38+
## Consequences
39+
40+
### Positive
41+
42+
- S3 submissions can use the Submission model. Adding a `delivered` status enables S3 submissions to use the same `Submission` model as email submissions, allowing us to easily see successful deliveries and those that need to be retried. This ultimately allows us to make S3 submissions asynchronous.
43+
44+
- Correct handling of async bounce notifications. Timestamps allow us to accurately determine submission status even when delivery and bounce notifications are processed out of order.
45+
46+
- Simplified logic for Submission deletion and retry. Determining which submissions to delete (those with `delivered` status) instead of finding "not_bounced" or assuming those that are "pending" are "delievered".
47+
48+
- Provides an audit trail. Timestamps record when state changes occurred, providing more context than a single enum value.
49+
50+
### Negative
51+
52+
- Requires more complicated (and potentially slower) database queries to find delivered and bounced submissions. Not likely to cause issues out our current scale.
53+
54+
55+
56+

0 commit comments

Comments
 (0)