Skip to content

feat: template registry + queued variant for datamachine/send-email#2068

Open
chubes4 wants to merge 5 commits into
mainfrom
feat-send-email-templates
Open

feat: template registry + queued variant for datamachine/send-email#2068
chubes4 wants to merge 5 commits into
mainfrom
feat-send-email-templates

Conversation

@chubes4
Copy link
Copy Markdown
Member

@chubes4 chubes4 commented May 18, 2026

Closes #2064

Summary

  • Extends datamachine/send-email with optional template + context inputs backed by new datamachine_email_templates filter ([ template_id => callable( array $context ): string ]). Template render runs before placeholder replacement so templates may emit {site_name}, {date}, etc.
  • Adds new datamachine/send-email-queued ability backed by Action Scheduler. Same input as datamachine/send-email plus optional send_at (ISO 8601 or unix ts) and priority (default 10). Async dispatch via as_enqueue_async_action when send_at is omitted, scheduled via as_schedule_single_action otherwise.
  • Worker datamachine_send_email_worker (registered on init) calls the synchronous ability, logs the structured result, and re-enqueues with exponential backoff (60s, 300s, 1500s). Hard cap of 3 total attempts. _attempt rides in the worker payload and is not part of the public input schema.
  • Adds wp datamachine email send-queued CLI subcommand mirroring send plus --template, --context, --send-at, --priority.
  • Adds smoke test exercising template render + placeholder ordering, unknown-template error, raw-body backwards compat, both queued dispatch paths, worker success path, and exponential-backoff retry up to MAX_ATTEMPTS.

Backwards compatibility

  • Existing datamachine/send-email callers omitting template see no behavior change. The schema now requires only to and subject; execute() enforces that one of body or template is provided.
  • Existing wp datamachine email send CLI is unchanged.
  • Existing REST shim at inc/Api/Email.php is unchanged (the new fields are optional).
  • The existing extrachill-eventsQualifyDigestAbilities consumer continues to work unmodified (raw body path).

Layer purity

Vendor-name grep clean: grep -riE 'extrachill|sendy|easy.wp.smtp|kimaki|cc-connect|telegram|slack|whatsapp' inc/ returns 35 matches — identical to baseline; zero new matches in the modified or added files (inc/Abilities/Publish/SendEmailAbility.php, inc/Abilities/Publish/SendEmailQueuedAbility.php, inc/Cli/Commands/EmailCommand.php).

How to verify

php tests/email-template-and-queued-smoke.php

All 44 assertions pass.

See issue #2064 for full acceptance criteria.

homeboy-ci Bot added 4 commits May 18, 2026 00:31
…es filter

Adds optional 'template' and 'context' inputs to datamachine/send-email.
When 'template' is set, the body is resolved via the datamachine_email_templates
filter ([ template_id => callable( array $context ): string ]); the rendered
string is then run through the existing placeholder replacement so templates
may emit {site_name}, {date}, etc. Unknown template ids return a structured
error with a log entry.

Backwards compatible: omitting 'template' preserves verbatim 'body' behavior.
The schema now requires only 'to' and 'subject'; execute() enforces that one
of 'body' or 'template' is provided.
…er worker

Adds datamachine/send-email-queued ability that defers delivery to Action
Scheduler under the datamachine-email group. Same input schema as
datamachine/send-email plus optional send_at (ISO 8601 or unix ts) and
priority (default 10).

- Omitting send_at uses as_enqueue_async_action for immediate async dispatch.
- Providing send_at uses as_schedule_single_action at that timestamp.
- Worker hook 'datamachine_send_email_worker' is registered on init so
  Action Scheduler can dispatch it outside the originating request.
- Worker calls the synchronous datamachine/send-email ability, logs the
  structured result, and re-enqueues itself with exponential backoff
  (60s, 300s, 1500s) up to 3 total attempts on failure.
- Internal _attempt counter rides in the worker payload and is not part
  of the public input_schema.

Output: { success, action_id, scheduled_for, error, logs }.

Wired up in data-machine.php alongside SendEmailAbility.
Mirrors the existing 'wp datamachine email send' flag surface and adds:
- --template / --context for template-rendered bodies
- --send-at for one-shot scheduled delivery (ISO 8601 or @unix)
- --priority for Action Scheduler priority hint

Delegates to datamachine/send-email-queued ability and reports the
returned action id + scheduled time.
Covers:
- Template render runs before placeholder replacement (template-emitted
  {site_name} and {date} are resolved on the post-render pass)
- Unknown template id returns structured error with no wp_mail() call
- Missing body AND missing template returns structured error
- Backwards-compat: raw body path still works with placeholder resolution
- Queued send-now uses as_enqueue_async_action under the datamachine-email
  group with _attempt=1 payload (send_at/priority stripped)
- Queued with send_at uses as_schedule_single_action at the resolved ts
- Worker invokes synchronous datamachine/send-email and does not retry on
  success
- Worker reschedules with exponential backoff (60s baseline) on failure
  and caps at MAX_ATTEMPTS total attempts

Adds a small PermissionHelper stub fixture so the abilities autoload
cleanly outside the full plugin bootstrap.

Run with: php tests/email-template-and-queued-smoke.php
@homeboy-ci
Copy link
Copy Markdown
Contributor

homeboy-ci Bot commented May 18, 2026

Homeboy Results — data-machine

Lint

lint — failed

  • formatting — 5 finding(s)
  • other — 1 finding(s)
  • Total: 6 finding(s)

ℹ️ Auto-fix: homeboy lint data-machine --path /home/runner/work/data-machine/data-machine --changed-since f7c7e25 --fix (or homeboy refactor data-machine --path /home/runner/work/data-machine/data-machine --changed-since f7c7e25 --from lint --write)
ℹ️ Some issues may require manual fixes
ℹ️ Full options: homeboy docs commands/lint
Deep dive: homeboy lint data-machine --changed-since f7c7e25

Test

test — passed

  • 597 passed
  • 3 skipped

ℹ️ Auto-fix lint issues: homeboy refactor data-machine --from lint --write
ℹ️ Collect coverage: homeboy test data-machine --coverage
ℹ️ Save test baseline: homeboy test data-machine --baseline
ℹ️ Pass args to test runner: homeboy test -- [args]
ℹ️ Full options: homeboy docs commands/test
Deep dive: homeboy test data-machine --changed-since f7c7e25

Audit

audit — passed

  • requested_detectors — 31 finding(s)
  • dead_code — 10 finding(s)
  • parallel-implementation — 7 finding(s)
  • dead_guard — 3 finding(s)
  • test_coverage — 3 finding(s)
  • Publish — 2 finding(s)
  • intra-method-duplication — 1 finding(s)
  • Total: 57 finding(s)

Deep dive: homeboy audit data-machine --changed-since f7c7e25

Tooling versions
  • Homeboy CLI: homeboy 0.182.0+3dcca1ea
  • Extension: wordpress from https://github.com/Extra-Chill/homeboy-extensions
  • Extension revision: dd47f26a
  • Action: unknown@unknown

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.

feat: extend datamachine/send-email with template registry + queued variant

1 participant