You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
first draft for concurrency using an approach at the database level (#12)
* first draft for concurrency using an approach at the database level
* Revert "first draft for concurrency using an approach at the database level"
This reverts commit 15c22d4.
* refactor Email entity by embedding EmailContent and adding new fields
* solve concurrency issue between pods using atomic compare-and-set; Add new configurables and make sendOrFail not retry
* add test for concurrency and schedule functionality
* update readme.md
* test fixes
* truncate OffsetDateTime to MICROS for pipeline to run successfully
* remove unnecessary errorMessage set
* requested changes
* consider all error cases that can happen on a schedule pass
* remove the first try catch since it is overkill
* make last save be in its on transaction so it can never be rolled back
|`aboutbits.emailservice.scheduling.enabled`| true | Enables the scheduler sending the emails. |
81
+
|`aboutbits.emailservice.scheduling.cleanup.enabled`| true | Enables cleanup of attachment files after sending. |
82
+
|`aboutbits.emailservice.scheduling.interval`| 30000 | Milliseconds delay between runs of the scheduler. |
83
+
|`aboutbits.emailservice.scheduling.stuck-sending-recovery-threshold`| PT30M | How long an email may stay in `SENDING` before being considered abandoned (crashed pod) and eligible to be re-claimed. Must comfortably exceed the worst-case SMTP send duration: JavaMail's default connect/read/write timeouts are infinite, so configure `spring.mail.properties.mail.smtp.connectiontimeout`, `spring.mail.properties.mail.smtp.timeout` and `spring.mail.properties.mail.smtp.writetimeout` well below this threshold, otherwise a slow in-flight send can be re-claimed by another pod and delivered twice. |
84
+
|`aboutbits.emailservice.scheduling.max-attempts`| 3 | Maximum number of send attempts before an email is marked as `ERROR`. Applies only to the scheduled retry loop. Failed attempts are retried with exponential backoff (`scheduling.interval` × 2^attempts); with the defaults a persistently failing email runs attempt 1 → +60s → attempt 2 → +120s → attempt 3 → `ERROR`. |
85
+
86
+
## Multi-pod deployments
87
+
88
+
The scheduler is safe to run on every pod concurrently: the database arbitrates which pod sends each email.
89
+
Delivery is at-least-once - if a pod crashes after the SMTP server accepted the message but before the result was persisted, the email may be sent again on recovery.
0 commit comments