|
| 1 | +-- Email delivery retries |
| 2 | +ALTER TABLE email_deliveries |
| 3 | + ADD COLUMN retry_count INT NOT NULL DEFAULT 0, |
| 4 | + ADD COLUMN next_retry_at TIMESTAMPTZ NULL, |
| 5 | + ADD COLUMN retryable BOOLEAN NOT NULL DEFAULT TRUE, |
| 6 | + ADD COLUMN first_failed_at TIMESTAMPTZ NULL, |
| 7 | + ADD COLUMN last_attempt_at TIMESTAMPTZ NULL; |
| 8 | + |
| 9 | +UPDATE email_deliveries |
| 10 | +SET retryable = FALSE |
| 11 | +WHERE sent = FALSE |
| 12 | + AND error IS NOT NULL; |
| 13 | + |
| 14 | +ALTER TABLE email_deliveries |
| 15 | + DROP COLUMN IF EXISTS error; |
| 16 | + |
| 17 | +CREATE TABLE email_delivery_errors ( |
| 18 | + id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), |
| 19 | + email_delivery_id UUID NOT NULL REFERENCES email_deliveries (id) ON DELETE CASCADE, |
| 20 | + attempt INT NOT NULL, |
| 21 | + error_message TEXT NOT NULL, |
| 22 | + error_code TEXT NULL, |
| 23 | + smtp_response TEXT NULL, |
| 24 | + smtp_response_code INT NULL, |
| 25 | + is_transient BOOLEAN NOT NULL, |
| 26 | + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), |
| 27 | + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), |
| 28 | + deleted_at TIMESTAMPTZ NULL |
| 29 | +); |
| 30 | + |
| 31 | +CREATE TRIGGER set_timestamp BEFORE |
| 32 | +UPDATE ON email_delivery_errors FOR EACH ROW EXECUTE PROCEDURE trigger_set_timestamp(); |
| 33 | + |
| 34 | +CREATE INDEX email_delivery_errors_email_delivery_id_idx ON email_delivery_errors (email_delivery_id); |
| 35 | + |
| 36 | +CREATE INDEX email_delivery_errors_created_at_idx ON email_delivery_errors (created_at); |
| 37 | + |
| 38 | +CREATE INDEX email_deliveries_retry_queue_idx ON email_deliveries (next_retry_at) |
| 39 | +WHERE sent = FALSE |
| 40 | + AND retryable = TRUE |
| 41 | + AND deleted_at IS NULL; |
| 42 | + |
| 43 | +COMMENT ON TABLE email_delivery_errors IS 'Log of individual email delivery failures.'; |
| 44 | + |
| 45 | +COMMENT ON COLUMN email_delivery_errors.id IS 'Stable identifier for an individual email delivery error entry.'; |
| 46 | + |
| 47 | +COMMENT ON COLUMN email_delivery_errors.email_delivery_id IS 'Foreign key to the parent email_deliveries row this error belongs to.'; |
| 48 | + |
| 49 | +COMMENT ON COLUMN email_delivery_errors.attempt IS '1-based send attempt number at which this error occurred.'; |
| 50 | + |
| 51 | +COMMENT ON COLUMN email_delivery_errors.error_message IS 'Human-readable description of the failure returned by the mailer or application.'; |
| 52 | + |
| 53 | +COMMENT ON COLUMN email_delivery_errors.error_code IS 'Short machine-friendly classification of the failure (e.g. transient, permanent, timeout).'; |
| 54 | + |
| 55 | +COMMENT ON COLUMN email_delivery_errors.smtp_response IS 'Raw SMTP response text associated with the failure when available.'; |
| 56 | + |
| 57 | +COMMENT ON COLUMN email_delivery_errors.smtp_response_code IS 'Numeric SMTP status code associated with the failure when available.'; |
| 58 | + |
| 59 | +COMMENT ON COLUMN email_delivery_errors.is_transient IS 'Indicates whether the failure is considered transient and therefore retryable.'; |
| 60 | + |
| 61 | +COMMENT ON COLUMN email_delivery_errors.created_at IS 'Timestamp when this email delivery error entry was recorded.'; |
| 62 | + |
| 63 | +COMMENT ON COLUMN email_delivery_errors.updated_at IS 'Timestamp when this email delivery error entry was last updated. The field is updated automatically by the set_timestamp trigger.'; |
| 64 | + |
| 65 | +COMMENT ON COLUMN email_delivery_errors.deleted_at IS 'Timestamp when this email delivery error entry was soft deleted.'; |
| 66 | + |
| 67 | +COMMENT ON COLUMN email_deliveries.retry_count IS 'Number of failed delivery attempts recorded so far for this email.'; |
| 68 | + |
| 69 | +COMMENT ON COLUMN email_deliveries.next_retry_at IS 'Next scheduled time when this email delivery will be retried, or NULL when no retry is scheduled.'; |
| 70 | + |
| 71 | +COMMENT ON COLUMN email_deliveries.retryable IS 'Indicates whether this email delivery is still eligible for further retry attempts.'; |
| 72 | + |
| 73 | +COMMENT ON COLUMN email_deliveries.first_failed_at IS 'Timestamp of the first failed delivery attempt for this email, used as the retry window anchor.'; |
| 74 | + |
| 75 | +COMMENT ON COLUMN email_deliveries.last_attempt_at IS 'Timestamp of the most recent delivery attempt for this email.'; |
0 commit comments