Skip to content

feat(workflow): add WorkflowListener with per-event helpers#32

Open
mpge wants to merge 1 commit intofeat/workflow-runnerfrom
feat/workflow-listener
Open

feat(workflow): add WorkflowListener with per-event helpers#32
mpge wants to merge 1 commit intofeat/workflow-runnerfrom
feat/workflow-listener

Conversation

@mpge
Copy link
Copy Markdown
Member

@mpge mpge commented Apr 24, 2026

Summary

Final piece of the workflow stack for Phoenix. Provides a thin wrapper (WorkflowListener) that bridges domain events into WorkflowRunner.run_for_event/2.

Each helper maps an event to a canonical workflow trigger name (matching the 12-event set in WorkflowEngine.trigger_events/0) and fires the runner in a supervised Task so a slow workflow never blocks the mutation that fired it.

Opt-in wire-up

Phoenix doesn't auto-emit ApplicationEvents the way Spring or EventEmitter2 do, so host apps opt in by calling these helpers from their TicketService wrappers or post-write PubSub / Oban handlers:

# After creating a ticket
WorkflowListener.ticket_created(ticket)

# After a reply
WorkflowListener.reply_created(reply)

Per-event helpers

ticket_created/1, ticket_updated/1, ticket_status_changed/1, ticket_priority_changed/1, ticket_assigned/1, ticket_reopened/1, ticket_tagged/1, ticket_department_changed/1, reply_created/1, sla_breached/1, sla_warning/1.

Failure semantics

Runner failures are caught inside the spawned task and emitted via Logger.error/1. They never propagate back to the caller — matches the "one bad workflow never blocks the mutation" rule applied everywhere else in this stack.

Complete chain

TicketService mutation
  → WorkflowListener.<event>(ticket)
  → Task / Task.Supervisor
  → WorkflowRunner.run_for_event
  → WorkflowEngine (conditions) + WorkflowExecutor (actions)
  → workflow_logs row

Dependencies

Test plan

  • 15 ExUnit tests covering fire/2 argument validation, reply_created/1 shape handling, and interface checks for every per-event helper
  • Integration with real Ecto repo covered once a test repo is configured in a follow-up

Final piece of the workflow stack for Phoenix. Provides a thin wrapper
that bridges domain events into WorkflowRunner.run_for_event/2.

Each helper maps an event to a canonical workflow trigger name
(matching the 12-event set in WorkflowEngine.trigger_events/0) and
fires the runner in a supervised Task so a slow workflow never blocks
the mutation that fired it.

Phoenix doesn't auto-emit ApplicationEvents the way Spring or
EventEmitter2 do, so host apps opt in by calling these helpers from
their TicketService wrappers or post-write PubSub / Oban handlers:

    # After creating a ticket:
    WorkflowListener.ticket_created(ticket)

    # After a reply:
    WorkflowListener.reply_created(reply)

Runner failures are caught inside the spawned task and Logger.error-ed;
they never propagate back to the caller.

With this commit the chain is complete end-to-end for Phoenix:
  TicketService mutation → WorkflowListener.<event>(ticket) →
  Task / Task.Supervisor → WorkflowRunner.run_for_event →
  WorkflowEngine (conditions) + WorkflowExecutor (actions) →
  workflow_logs row
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