Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- defmodule Percussion.Dispatcher do
- @moduledoc """
- TODO: write documentation.
- """
- alias Percussion.Dispatcher
- alias Percussion.Pipeline
- alias Percussion.Request
- @typedoc "Function which will be called from this dispatcher."
- @type call :: Request.transform()
- @typedoc "List of match that this dispatcher matches on."
- @type match :: [String.t()]
- @typedoc "Preprocessing steps before calling the dispatcher call."
- @type pipe :: [Request.transform()]
- @type t :: %Dispatcher{
- call: call,
- match: match,
- pipe: pipe
- }
- defstruct [:match, :call, pipe: []]
- @doc """
- Creates a `t:Percussion.Dispatcher.t/0` specification for the given command.
- """
- @spec command(Request.transform(), Keyword.t()) :: t
- def command(call, options \\ []) do
- %Dispatcher{
- call: call,
- match: options[:match] || [],
- pipe: options[:pipe] || []
- }
- end
- @doc """
- Creates a `t:Percussion.Dispatcher.t/0` specification for the given router.
- """
- @spec router([t], [Request.transform()]) :: t
- def router(routes, pipe \\ []) do
- table = routing_table(routes)
- dispatch = fn request ->
- dispatch(table[request.invoked_with], request)
- end
- %Dispatcher{
- call: dispatch,
- match: Map.keys(table),
- pipe: pipe
- }
- end
- defp routing_table(routes) do
- for dispatcher <- routes do
- Enum.map(dispatcher.match, fn match -> {match, dispatcher} end)
- end
- |> Enum.concat()
- |> Enum.into(%{})
- end
- @doc """
- Dispatches.
- """
- @spec dispatch(t, Request.t()) :: Request.t()
- def dispatch(%Dispatcher{pipe: pipe, call: call}, request) do
- pipe
- |> Pipeline.fold(request)
- |> Request.map(call)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement