RpcElixir.Dispatcher (elixir_ts_rpc v0.0.1)

Copy Markdown View Source

Core dispatch pipeline: lookup → middleware → validate input → invoke handler → validate output → serialize.

Every transport (HTTP Plug, in-process caller) funnels through dispatch/4, which threads a %RpcElixir.Resolution{} through the procedure's middleware chain and the inner pipeline. The returned resolution carries the final outcome on its :result field, so middleware that wraps dispatch/4 can observe and transform results uniformly.

Typed handler errors

When a handler returns {:error, reason}, the dispatcher promotes reason to a top-level %RpcError{}:

  • reason is an atom: code = reason, message = Atom.to_string(reason), details = nil. HTTP status is derived by the transport from RpcElixir.RpcError's framework status map (falling back to a generic status).
  • reason is a plain map (not a struct) with :code (atom): code = reason.code, message = reason[:message] || Atom.to_string(code), details = reason minus :code and :message (or nil if empty). HTTP status is derived by the transport from RpcElixir.RpcError's framework status map (falling back to a generic status).
  • reason is already an %RpcError{} with a non-nil :source: passed through unchanged. If :source is nil, it is stamped with source: :domain before being returned.
  • Anything else (structs, tuples, keyword lists, lists, …): wrapped as %RpcError{code: :handler_error, details: %{kind: :error, reason: inspect(reason)}} with status 500 (the default status for :handler_error in RpcElixir.RpcError.framework_errors/0). These are framework-level "handler returned something unexpected" cases.

This contract matches the JS Error shape on the TypeScript client: err.code, err.message, and err.details are all populated for typed errors, and err.message shows up in stack traces and console.error.

Summary

Types

Final result populated on Resolution.result after dispatch.

Functions

Dispatches a procedure call against router, returning the resolution with :result populated.

Types

result()

@type result() :: {:ok, term()} | {:error, RpcElixir.RpcError.t()}

Final result populated on Resolution.result after dispatch.

Functions

dispatch(router, path, raw_input, resolution)

Dispatches a procedure call against router, returning the resolution with :result populated.

  • If the input resolution is already halted, it is returned as-is.
  • If the procedure path is unknown, the result is set to a :procedure_not_found RpcError without invoking middleware.
  • Otherwise, the procedure's middleware chain runs around the inner pipeline. Any middleware may halt the resolution to short-circuit.