Dispatch resolution for DoubleDown contracts.
Three dispatch paths are available, selected at compile time by the
:test_dispatch? and :static_dispatch? options on
use DoubleDown.ContractFacade:
call/4 — test-aware dispatch (default in non-prod)
- Test handler — process-scoped via
NimbleOwnership(only checked if the ownership server is running) - Application config —
Application.get_env(otp_app, contract)[:impl] - Raise — no handler configured
call_config/4 — config-only dispatch
- Application config —
Application.get_env(otp_app, contract)[:impl] - Raise — no handler configured
No NimbleOwnership code is referenced in the generated facade
functions, eliminating the GenServer.whereis lookup entirely.
Static dispatch (default in prod when config available)
The implementation module is resolved at compile time and the
generated facade calls it directly — no NimbleOwnership, no
Application.get_env. Zero dispatch overhead. Falls back to
call_config/4 if the config is not available at compile time.
Summary
Functions
Dispatch a port operation to the resolved implementation.
Dispatch a port operation directly from application config.
Read the current stateful handler state for a contract.
Check whether the calling process has a test handler installed for the given contract.
Build a canonical key for test stub matching.
Restore a single contract's stateful handler state.
Functions
Dispatch a port operation to the resolved implementation.
Called by generated facade functions when test_dispatch?: true
(the default in non-production environments). Checks for a
process-scoped test handler via NimbleOwnership before falling
back to application config.
Dispatch a port operation directly from application config.
Called by generated facade functions when test_dispatch?: false
(the default in production). Skips the NimbleOwnership test
handler lookup entirely — zero overhead beyond Application.get_env.
Read the current stateful handler state for a contract.
Returns the domain state — for Double-managed handlers this is
the fallback_state field; for raw stateful handlers this is
the entire state value. Used to snapshot state before a transaction.
Check whether the calling process has a test handler installed for the given contract.
Returns true when a handler is active (via DoubleDown.Double.fake/2,
expect/3, etc.), false otherwise. Useful for test infrastructure that
needs to skip real-DB side-effects (e.g. setting Postgres session variables)
when an in-memory handler is intercepting Repo calls.
Respects the $callers chain, so handlers installed in a parent process
are visible to spawned children.
Build a canonical key for test stub matching.
Keys are normalized so that map/keyword argument order doesn't affect matching.
Restore a single contract's stateful handler state.
Replaces the state for the given contract in NimbleOwnership, leaving the handler function and all other contracts' state untouched. Used by transaction rollback to restore the pre- transaction snapshot.
Handles both Double-managed handlers (restores the fallback_state
field within the Double's internal map) and raw stateful handlers
installed via set_stateful_handler (replaces the entire state).