Skip to content

Feature: route-level side-effect hooks (pre-dispatch) #155

@warren-t-c

Description

@warren-t-c

Problem

When an event matches a route, we sometimes want to fire side effects (HTTP calls, API reactions, logging) before the event is dispatched to the target actor. Currently the only extension point is transforms, which are semantically about event mutation/filtering — not side effects.

Current Workaround

We're using script transforms as pass-through wrappers with background side effects:

#!/usr/bin/env bash
event=$(cat)
echo "$event"  # pass-through
(do_side_effect "$event") &  # fire-and-forget
exit 0

This works but is a semantic abuse of the transform abstraction — transforms should transform, not produce side effects.

Proposed Solution

Add a hooks or side_effects section to route config that runs fire-and-forget actions when a route matches, independent of the transform pipeline:

routes:
  - name: my-route
    when: ...
    transforms: ...
    hooks:
      - type: script
        script: ./scripts/github-ack.sh
        timeout_ms: 5000
        on_error: ignore  # always ignore — never block dispatch
      - type: http
        url: https://slack.com/api/reactions.add
        method: POST
        headers:
          Authorization: "Bearer ${SLACK_BOT_TOKEN}"
        body_template: '{"channel": "{{payload.channel}}", ...}'
    then:
      actor: ...

Key properties:

  • Fire-and-forget: hooks never block dispatch or affect the event
  • Fail-open by default: errors are logged but never prevent routing
  • Run after transforms: hooks see the final (possibly mutated) event
  • Script + HTTP types: script hooks follow the same contract as script transforms; HTTP hooks are declarative

Use Case

We add 👀 emoji reactions to GitHub issues/PRs when our pipeline routes match — instant acknowledgment that the system received the event and is processing it. Currently implemented as a script transform that passes through unchanged. Would be cleaner as a dedicated hook.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions