Skip to content

ENG-3301: Align messaging endpoints with service layer pattern#8138

Open
JadeCara wants to merge 6 commits intoENG-3301/messaging-provider-refactor-pr2-sesfrom
ENG-3301/messaging-service-alignment
Open

ENG-3301: Align messaging endpoints with service layer pattern#8138
JadeCara wants to merge 6 commits intoENG-3301/messaging-provider-refactor-pr2-sesfrom
ENG-3301/messaging-service-alignment

Conversation

@JadeCara
Copy link
Copy Markdown
Contributor

@JadeCara JadeCara commented May 7, 2026

Ticket ENG-3301

PR Series

This is PR 2.5 of 3 in the messaging provider refactor:

PR Branch Description Status
#8118 (PR1) messaging-provider-refactor-pr1 Extract 4 dispatchers into provider classes ✅ Review-ready
#8120 (PR2) messaging-provider-refactor-pr2-ses Migrate AWS SES to provider class ✅ Review-ready
This PR (PR2.5) messaging-service-alignment Wire route endpoints through MessagingService 🔄 In review

Base branch: ENG-3301/messaging-provider-refactor-pr2-ses (PR2)

Description Of Changes

Moves leaked dispatch and validation concerns from route endpoints into MessagingService, aligning with the service/repository pattern.

What moved:

  • dispatch_message() call in send_test_messageMessagingService.send_test_message()
  • _PROVIDER_MAP lookup + validate_on_save() in update_config_secretsMessagingService.validate_provider_on_save()

What was added:

  • get_provider_class() public accessor in message_dispatch_service.py (replaces cross-module import of private _PROVIDER_MAP)
  • Unit tests for both new service methods

What was NOT changed (intentional):

  • Deprecated send_test_message_deprecated still calls dispatch_message directly (passes str, not enum)
  • No repository layer added — model classmethods are sufficient for OSS fides
  • Non-route callers (Celery tasks, connectors) continue using dispatch_message directly

Code Changes

  • src/fides/service/messaging/messaging_service.py — added send_test_message(), validate_provider_on_save()
  • src/fides/api/service/messaging/message_dispatch_service.py — added get_provider_class() public accessor
  • src/fides/api/v1/endpoints/messaging_endpoints.py — wired 4 routes through Depends(get_messaging_service), removed _PROVIDER_MAP import
  • tests/ops/service/messaging/test_messaging_service.py — 5 new unit tests
  • tests/ops/api/v1/endpoints/test_messaging_endpoints.py — fixed pre-existing SES test (expected failure_reason=None but validate_on_save correctly rejects fake creds)

Steps to Confirm

  1. pytest tests/ops/service/messaging/test_messaging_service.py -x -q — 5 new tests pass
  2. pytest tests/ops/api/v1/endpoints/test_messaging_endpoints.py -x -q — all endpoint tests pass
  3. pytest tests/ops/service/messaging/message_dispatch_service_test.py -x -q — dispatch tests pass
  4. POST /api/v1/messaging/test/mailgun still works via MessagingService
  5. PUT /api/v1/messaging/default/aws_ses/secret returns failure_reason on bad creds

🤖 Generated with Claude Code

Move dispatch and validation logic from routes into MessagingService:

- Add MessagingService.send_test_message() — delegates to dispatch_message
- Add MessagingService.validate_provider_on_save() — runs provider
  validation after secrets save, returns failure reason or None
- Add get_provider_class() public accessor to message_dispatch_service
  (replaces cross-module import of private _PROVIDER_MAP)
- Wire route endpoints through MessagingService via Depends()
- Fix pre-existing test bug: SES secrets test expected failure_reason=None
  but validate_on_save correctly rejects fake AWS credentials

Routes no longer import _PROVIDER_MAP or call dispatch_message directly
(except the deprecated test endpoint which passes str, not enum).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@JadeCara JadeCara requested a review from a team as a code owner May 7, 2026 22:56
@JadeCara JadeCara requested review from dsill-ethyca and removed request for a team May 7, 2026 22:56
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 7, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

2 Skipped Deployments
Project Deployment Actions Updated (UTC)
fides-plus-nightly Ignored Ignored Preview May 8, 2026 8:34pm
fides-privacy-center Ignored Ignored May 8, 2026 8:34pm

Request Review

@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 73.91304% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.43%. Comparing base (66b03dc) to head (b385d48).
⚠️ Report is 3 commits behind head on ENG-3301/messaging-provider-refactor-pr2-ses.

Files with missing lines Patch % Lines
src/fides/api/v1/endpoints/messaging_endpoints.py 50.00% 4 Missing ⚠️
src/fides/service/messaging/messaging_service.py 84.61% 1 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (73.91%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage.
❌ Your project check has failed because the head coverage (83.43%) is below the target coverage (85.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@                               Coverage Diff                                @@
##           ENG-3301/messaging-provider-refactor-pr2-ses    #8138      +/-   ##
================================================================================
- Coverage                                         83.47%   83.43%   -0.05%     
================================================================================
  Files                                               643      643              
  Lines                                             42112    42130      +18     
  Branches                                           4945     4947       +2     
================================================================================
- Hits                                              35153    35151       -2     
- Misses                                             5709     5710       +1     
- Partials                                           1250     1269      +19     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@JadeCara JadeCara requested review from erosselli and removed request for dsill-ethyca May 7, 2026 23:23
@JadeCara
Copy link
Copy Markdown
Contributor Author

JadeCara commented May 7, 2026

/code-review

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Code Review — ENG-3301: Align messaging endpoints with service layer pattern

The PR is clean overall. The refactoring correctly moves dispatch_message and _PROVIDER_MAP lookups out of route handlers and into MessagingService, the new get_provider_class public accessor is a straightforward pattern, and the test file is well-structured with good coverage of both success and failure paths.

Issues

1. failure_reason is silently dropped in post_config (moderate)
update_config_secrets now returns a TestMessagingStatusMessage with a failure_reason field, but post_config (line 131–136) discards the return value. Because post_config returns a MessagingConfigResponse, validation failures from validate_provider_on_save are invisible to the caller when creating a config via POST. This should either be documented as intentional (with a comment) or surfaced — e.g., log it at WARN, or add a warning field to the POST response.

2. Uncaught ValueError in validate_provider_on_save (minor)
MessagingServiceType(messaging_config.service_type) will raise ValueError for an unrecognised string. The DB constraint makes this unlikely in production, but it's an unhandled path that would produce a 500. A simple try/except ValueError: return None guard would close it.

3. logger.error removal in aws_ses_service.py (nit)
Dropping duplicate log-before-raise is correct for the save-validation path. Be aware that get_ses_client and validate_email_and_domain_status are also called during real message sends; in that path the failure still propagates, but there's no longer any log at the SES-service level. If that loss of per-method context matters for debugging, a logger.debug call would preserve it without re-introducing the duplicate.

Positives

  • MessagingService.send_test_message and validate_provider_on_save are clean thin delegators — exactly the right layer for this logic.
  • The unit tests cover the key branches (no provider, success, exception) clearly and without over-mocking.
  • Fixing the pre-existing test assertion (failure_reason can be non-None with fake SES creds) is the right call.
  • The get_provider_class accessor is a clean way to avoid cross-module private access without changing the _PROVIDER_MAP structure.

🔬 Codegraph: connected (49514 nodes)


💡 Write /code-review in a comment to re-run this review.

Comment thread src/fides/api/v1/endpoints/messaging_endpoints.py
Comment thread src/fides/service/messaging/messaging_service.py
JadeCara and others added 4 commits May 7, 2026 17:29
When secrets are passed inline during config creation, the
validate_on_save result was silently discarded since the response
type is MessagingConfigResponse (no failure_reason field). Now logs
a warning so the validation failure is visible server-side.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant