defmodule Pi.Plugin.Event do
@moduledoc "Pi-side events delivered to BEAM plugins."
use GenServer
alias Pi.Protocol.PluginEvent
alias Pi.Transport.Stdio
def start_link(opts \\ []), do: GenServer.start_link(__MODULE__, opts, name: __MODULE__)
def install do
case Process.whereis(__MODULE__) do
nil -> start_link([])
_pid -> :ok
end
end
def push(event) when is_map(event) do
install()
GenServer.cast(__MODULE__, {:event, event})
end
def emit(name, data \\ %{}) when is_binary(name) and is_map(data) do
Stdio.emit(%PluginEvent{type: :event, name: name, data: data})
end
def recent(n \\ 50), do: GenServer.call(__MODULE__, {:recent, n})
def clear, do: GenServer.call(__MODULE__, :clear)
@impl true
def init(_opts), do: {:ok, :queue.new()}
@impl true
def handle_cast({:event, event}, events) do
events = :queue.in(event, events)
events = if :queue.len(events) > 256, do: elem(:queue.out(events), 1), else: events
{:noreply, events}
end
@impl true
def handle_call({:recent, n}, _from, events) do
{:reply, events |> :queue.to_list() |> Enum.take(-n), events}
end
def handle_call(:clear, _from, _events), do: {:reply, :ok, :queue.new()}
end