Skip to content

Email Async - #67

Open
isabellalam12 wants to merge 4 commits into
mainfrom
email-async
Open

Email Async #67
isabellalam12 wants to merge 4 commits into
mainfrom
email-async

Conversation

@isabellalam12

@isabellalam12 isabellalam12 commented Jul 28, 2026

Copy link
Copy Markdown
Member
  • create email async plans
  • implement asynchronous email backend and UI
  • swap to database-backed templates.

Screenshot 2026-08-03 at 1.59.45 PM.png

Screenshot 2026-08-03 at 1.59.54 PM.pngScreenshot 2026-08-03 at 2.09.05 PM.png

isabellalam12 commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@isabellalam12 isabellalam12 changed the title create email async plans Email Async Aug 3, 2026
@isabellalam12
isabellalam12 force-pushed the email-async branch 4 times, most recently from 6e59825 to d48461a Compare August 3, 2026 17:40
@isabellalam12 isabellalam12 self-assigned this Aug 3, 2026
@isabellalam12 isabellalam12 added the enhancement New feature or request label Aug 3, 2026 — with Graphite App
@isabellalam12
isabellalam12 force-pushed the email-async branch 2 times, most recently from 0531ddc to 37de9df Compare August 3, 2026 18:07
@isabellalam12
isabellalam12 marked this pull request as ready for review August 3, 2026 18:10
@isabellalam12
isabellalam12 requested a review from a team August 3, 2026 18:10
Comment thread src/main/java/org/patinanetwork/patchats/email/MatchingSendService.java Outdated
@isabellalam12
isabellalam12 force-pushed the email-async branch 2 times, most recently from 669a336 to eee10a1 Compare August 3, 2026 18:48

/** Enqueues a batch. {@code source} distinguishes the producer (MANUAL vs MATCHING). */
@Transactional
public EnqueueEmailResponse enqueue(final EnqueueEmailRequest request, final EmailSource source) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how big are these batches? are we planning on sending them all in one for a given month?

Comment thread src/main/java/org/patinanetwork/patchats/email/MatchingSendService.java Outdated
@spiffyy99

Copy link
Copy Markdown

This is a very interesting and technically cool approach, but i can't help but feel we might benefit from testing sending out some actual emails due to the complexity and how many parts can go wrong. That can probably be either a manual test run (especially at first) or through integration testing with a fake in-memory SMTP server such as https://github.com/gessnerfl/fake-smtp-server

The main thing i'm concerned about is not only the emails actually being sent out, but the retry logic. we'd want to verify that users don't get spammed with multiple emails unnecessariliy.

This can definitely be relegated to a future task though, no need for this PR.

Comment on lines +59 to +63
public int softDelete(final UUID id) {
return jdbc.sql("DELETE FROM email_templates WHERE id = :id")
.param("id", id)
.update();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The softDelete() method performs a hard DELETE instead of a soft delete. This contradicts the method name, the Javadoc in EmailTemplateRepo, and the design intent documented in TemplateManagementService (which states templates should be preserved for audit history). Additionally, the migration file lacks a deleted_at column needed for soft deletion.

Impact: This will permanently delete templates that are referenced by past emails, breaking audit trails and making it impossible to reconstruct what was sent. The delete protection logic in TemplateManagementService.deleteTemplate() prevents deletion of currently-referenced templates, but this protection doesn't help templates that were used in the past for already-sent emails.

Fix: Add a deleted_at TIMESTAMPTZ column to the email_templates table migration, and change the implementation to:

public int softDelete(final UUID id) {
    return jdbc.sql("UPDATE email_templates SET deleted_at = NOW() WHERE id = :id AND deleted_at IS NULL")
            .param("id", id)
            .update();
}

Also update findAll() to exclude soft-deleted rows:

public List<EmailTemplate> findAll() {
    return jdbc.sql("SELECT * FROM email_templates WHERE deleted_at IS NULL ORDER BY name")
            .query((rs, rowNum) -> parseResultSet(rs))
            .list();
}

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@isabellalam12
isabellalam12 force-pushed the email-async branch 2 times, most recently from fa78dcb to e144d6c Compare August 7, 2026 17:54
@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown


---

## 1a. Data model — `db/migration/V0004__Create_email_tables.sql`

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migration file name mismatch with actual implementation

Documentation references V0004__Create_email_tables.sql but the actual migration file is V0005__Create_email_tables.sql. This will cause confusion during implementation and code reviews. The version number must match between docs and implementation for Flyway to work correctly.

Fix: Update reference to match actual file:

## 1a. Data model — `db/migration/V0005__Create_email_tables.sql`
Suggested change
## 1a. Data model — `db/migration/V0004__Create_email_tables.sql`
## 1a. Data model — `db/migration/V0005__Create_email_tables.sql`

Spotted by Graphite

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants