Event hooks for downstream consumers.
Dispatch tiers based on latency requirements:
- Sync tier (
notify_sync/3, the redirect path's:link_click): each callback runs viaTask.Supervisor.async_nolinkwith a 50ms timeout. Crash or timeout never blocks the caller. Use it for fast hooks whose result the caller needs in-band (e.g. cookie directives). - Async opt-in tier (
notify_detached/3): callbacks registered withasync: trueare skipped by the sync tier and dispatched here fire-and-forget, with no time budget. Use it for slow, side-effecting hooks (e.g. a DB-bound subscriber identify) that must not run under the 50ms redirect budget. - Broadcast tier (
notify_async/3, every non-click event): broadcast viaPhoenix.PubSubafter the enclosing transaction commits.
The link redirect pairs the first two: notify_sync/3 for the bounded,
cookie-setting hooks and notify_detached/3 for the async-tier side effects.
Registration
GoodAnalytics.Hooks.register(:sale, fn event, visitor ->
# handle sale event
:ok
end)
GoodAnalytics.Hooks.register(:link_click, {MyApp.ClickHandler, :handle})
# Slow side-effect hook — runs off the 50ms redirect budget.
GoodAnalytics.Hooks.register(:link_click, {MyApp.Identify, :call}, async: true)
Summary
Functions
Returns a specification to start this module under a supervisor.
Async dispatch — broadcasts via Phoenix.PubSub after transaction commit.
Detached dispatch — runs only the async-tier callbacks (registered with
async: true) for event_type, each in a supervised task with no time
budget and no reply. Sync-tier callbacks are ignored, and nothing is
broadcast over PubSub.
Sync dispatch — used only for :link_click hooks on the redirect path.
Registers a callback for the given event type.
Types
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
Async dispatch — broadcasts via Phoenix.PubSub after transaction commit.
Used for all non-click hooks.
Detached dispatch — runs only the async-tier callbacks (registered with
async: true) for event_type, each in a supervised task with no time
budget and no reply. Sync-tier callbacks are ignored, and nothing is
broadcast over PubSub.
Pair this with notify_sync/3 on latency-sensitive paths (the link redirect):
notify_sync/3 awaits the bounded, cookie-setting hooks, while this lets slow
side-effect hooks run to completion off the request's critical path.
Sync dispatch — used only for :link_click hooks on the redirect path.
Each callback runs in a supervised task with a 50ms timeout.
Crashed or timed-out hooks return :error and are excluded from results.
Registers a callback for the given event type.
Options:
:async(boolean, defaultfalse) — whentrue, the callback joins the async tier: it is skipped bynotify_sync/3and instead dispatched fire-and-forget bynotify_detached/3, with no time budget. Use it for slow, side-effecting hooks (e.g. a DB-bound subscriber identify) that must not run under the 50ms sync redirect budget.falsekeeps the legacy sync tier behaviour (bounded, reply-carrying, cookie-capable).