Dispatch

Build Status

A distributed service registry built on top of phoenix_pubsub.

Requests are dispatched to one or more services based on hashed keys.

Installation

  1. Add dispatch to your list of dependencies in mix.exs:
        def deps do
          [{:dispatch, "~> 0.1.0"}]
        end
  1. Ensure dispatch is started before your application:
        def application do
          [applications: [:dispatch]]
        end

Usage

Configuration

Configure the registry:

config :dispatch,
  pubsub: [name: Phoenix.PubSub.Test.PubSub, 
           adapter: Phoenix.PubSub.PG2,
           opts: [pool_size: 1]]

When the application is started, a supervisor with be started supervising a pubsub adapter with the name and options specified.

Register a service

iex> {:ok, service_pid} = Agent.start_link(fn _ -> 1 end) # Use your real service here
iex> Dispatch.Registry.add_service(:uploader, service_pid)
{:ok, "g20AAAAI9+IQ28ngDfM="}

In this example, :uploaderis the type of the service. ### Retrieve all services for a service type ```elixir iex> Dispatch.Registry.get_services(:uploader) [{#PID<0.166.0>, %{node: :"slave2@127.0.0.1", phx_ref: "g20AAAAIHAHuxydO084=", phx_ref_prev: "g20AAAAI4oU3ICYcsoQ=", state: :online}}] ``` This retrieves all of the services info. ### Finding a service for a key ```elixir iex> Dispatch.Registry.find_service(:uploader, "file.png") {:ok, :"slave1@127.0.0.1", #PID<0.153.0>} ``` Usingfindservice/2returns a tuple in the formwherenodeis the node that owns the servicepid. If no service can be found thenis returned. ### Finding a list ofcountservice instances for a particularkey```elixir iex> Dispatch.Registry.find_multi_service(2, :uploader, "file.png") [{:ok, :"slave1@127.0.0.1", #PID<0.153.0>}, {:ok, :"slave2@127.0.0.1", #PID<0.145.0>}] ``` ## Convenience API TheServicemodule can be used to automatically handle registration of a service based on aGenServer. CallService.initwithin your GenServer'sinit` function. ```elixir def init() do :ok = Dispatch.Service.init(type: :uploader) {:ok, %{}} end This will use the type provided to attach a service to the configured registry pid. Use `Dispatch.Service.cast` and `Dispatch.Service.call` to route the GenServer `cast` or `call` to the appropriate service based on the `key` provided. Use `Dispatch.Service.multi_cast` to send cast messages to several service instances at once. `Dispatch.Service.multi_call` calls several service instances and waits for all the responses before returning.elixir # File is a map with the format %{name: "file.png", contents: "test file"} def upload(file) Dispatch.Service.cast(:uploader, file.name, {:upload, file}) end def download(file) Dispatch.Service.call(:uploader, file.name, {:download, file}) end def handle_cast({:upload, file}, state) do Logger.info("Uploading #{file.name}") {:noreply, Map.put(state, file.name, file.contents)} end def handle_call({:download, %{name: name}}, from, state) do Logger.info("Downloading #{name}") {:reply, {:ok, Map.get(state, name}}, state} end ```