Packages

Reprise reloads your modules after they've been recompiled. It is thought as a companion to inotify tools. It scans for changes in beam files belonging to youyr project. Doesn't recompile stuff by itself.

Current section

Files

Jump to
reprise lib server.ex
Raw

lib/server.ex

defmodule Reprise.Server do
use GenServer
alias Reprise.Runner
@moduledoc """
Server scanning project beam files for changes and reloading them.
The server is just repeatedly firing messages in a given time interval
and then delegating the actual work to `Reprise.Runner`.
"""
@doc """
Starts the server passing a keyword list of arguments.
Currently valid and required arguments are:
`[interval: millis]`
"""
@spec start_link(Keyword.t) :: any
def start_link(args) do
GenServer.start_link(__MODULE__, args, name: Reprise)
end
@doc """
Reads or sets the current interval
between scans for module changes.
When called without argument, returns the current interval.
When called with argument, sets the interval (in milliseconds)
and returns previous one.
## Examples
iex> Reprise.Server.interval
1000
iex> Reprise.Server.interval(2000)
{:ok, [prev: 1000]}
"""
@spec interval() :: non_neg_integer
@spec interval(integer | nil) :: non_neg_integer | {:ok, Keyword.t}
def interval(millis \\ nil), do:
GenServer.call(Reprise, {:interval, millis})
# callbacks
def init(kw) do
interval = kw[:interval]
cond do
!interval -> {:stop, "pass interval arg"}
:ok ->
wait(interval)
{:ok, {now(), interval}}
end
end
def handle_info(:wake, {last, interval}) do
timestamp = now()
Runner.go(last, timestamp)
wait(interval)
{:noreply, {timestamp, interval}}
end
def handle_call({:interval, nil}, _from, st={_, interval}) do
{:reply, interval, st}
end
def handle_call({:interval, new_interval}, _from, {last, interval}) do
{:reply, {:ok, [prev: interval]}, {last, new_interval}}
end
# helpers
@spec wait(non_neg_integer) :: reference
defp wait(interval), do: Process.send_after(self(), :wake, interval)
@spec now() :: Runner.time
defp now(), do: :erlang.localtime
end