defmodule JSONRPC2.Spec.Batch do @moduledoc """ `JSONRPC2.Spec.Batch` allows you to pack operations (function calls and notification sending) that can later be executed into a single request. Examples: iex> alias JSONRPC2.Spec.Batch iex> Batch.notify("event_name", ["arg1", "arg2"]) |> Batch.call("func_name", ["arg1", "arg2"], 1) %JSONRPC2.Spec.Batch{ calls: %{ 1 => %JSONRPC2.Spec.Request{ id: 1, method: "func_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } }, notifies: [ %JSONRPC2.Spec.Request{ id: nil, method: "event_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } ] } """ @type t :: %__MODULE__{ calls: map(), notifies: [map()] } alias JSONRPC2.Spec.Request alias JSONRPC2.Spec defstruct [calls: %{}, notifies: []] @doc """ Prepare data to send notification. The `params` could be either map or list. Examples: iex> alias JSONRPC2.Spec.Batch iex> Batch.notify("name", ["arg1", "arg2"]) %JSONRPC2.Spec.Batch{ calls: %{}, notifies: [ %JSONRPC2.Spec.Request{ id: nil, method: "name", params: ["arg1", "arg2"], jsonrpc: "2.0" } ] } Functions can be piped: iex> Batch.notify("event_name", ["arg1", "arg2"]) |> Batch.call("func_name", ["arg1", "arg2"], 1) %JSONRPC2.Spec.Batch{ calls: %{ 1 => %JSONRPC2.Spec.Request{ id: 1, method: "func_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } }, notifies: [ %JSONRPC2.Spec.Request{ id: nil, method: "event_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } ] } """ @spec notify(Spec.method(), Spec.params()) :: t() def notify(method, params) do notify(%__MODULE__{}, method, params) end @spec notify(t(), Spec.method(), Spec.params()) :: t() def notify(%__MODULE__{notifies: notifies} = req, method, params) when is_binary(method) do %__MODULE__{req | notifies: notifies ++ [Request.new(method, params, nil)]} end @doc """ Prepare data to call function. The `params` could be either map or list. The `id` must be unique within `Batch`. Examples: iex> alias JSONRPC2.Spec.Batch iex> Batch.call("name", ["arg1", "arg2"], 1) %JSONRPC2.Spec.Batch{ calls: %{ 1 => %JSONRPC2.Spec.Request{ id: 1, method: "name", params: ["arg1", "arg2"], jsonrpc: "2.0" } }, notifies: [] } Functions can be piped: iex> Batch.notify("event_name", ["arg1", "arg2"]) |> Batch.call("func_name", ["arg1", "arg2"], 1) %JSONRPC2.Spec.Batch{ calls: %{ 1 => %JSONRPC2.Spec.Request{ id: 1, method: "func_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } }, notifies: [ %JSONRPC2.Spec.Request{ id: nil, method: "event_name", params: ["arg1", "arg2"], jsonrpc: "2.0" } ] } """ @spec call(Spec.method(), Spec.params(), Spec.id()) :: t() def call(method, params, id) do call(%__MODULE__{}, method, params, id) end @spec call(t(), Spec.method(), Spec.params(), Spec.id()) :: t() def call(%__MODULE__{calls: calls} = req, method, params, id) when is_binary(method) do %__MODULE__{req | calls: Map.put(calls, id, Request.new(method, params, id))} end end