zf

zenflows testing
git clone https://s.sonu.ch/~srfsh/zf.git
Log | Files | Refs | Submodules | README | LICENSE

beam_monitor.ex (2211B)


      1 require Logger
      2 
      3 defmodule ExSync.BeamMonitor do
      4   def start_link(opts \\ []) do
      5     GenServer.start_link(__MODULE__, opts)
      6   end
      7 
      8   def init(opts) when is_list(opts) do
      9     {:ok, watcher_pid} = FileSystem.start_link(dirs: ExSync.Config.beam_dirs())
     10     FileSystem.subscribe(watcher_pid)
     11 
     12     {:ok, %{watcher_pid: watcher_pid, finished_reloading_timer: false}}
     13   end
     14 
     15   def handle_info({:file_event, _watcher_pid, {path, events}}, state) do
     16     %{finished_reloading_timer: finished_reloading_timer} = state
     17 
     18     if finished_reloading_timer do
     19       Process.cancel_timer(finished_reloading_timer)
     20     end
     21 
     22     if Path.extname(path) in [".beam"] do
     23       {:created in events, :removed in events, :modified in events, File.exists?(path)}
     24       |> case do
     25         # update
     26         {_, _, true, true} ->
     27           # At least on linux platform, we're seeing a :modified event followed by a
     28           # :modified, closed event.  By ensuring the modified event arrives on its own,
     29           # we should be ablle to ensure we reload only once in a cross-platorm friendly way.
     30           # Note: TODO I don't have a Mac or Windows env to verify this!
     31           if :modified in events do
     32             Logger.debug "reload module #{Path.basename(path, ".beam")}"
     33             ExSync.Utils.reload path
     34           end
     35 
     36         # temp file
     37         {true, true, _, false} ->
     38           nil
     39 
     40         # remove
     41         {_, true, _, false} ->
     42           Logger.debug("unload module #{Path.basename(path, ".beam")}")
     43           ExSync.Utils.unload(path)
     44 
     45         # create
     46         _ ->
     47           nil
     48       end
     49     end
     50 
     51     reload_timeout = ExSync.Config.reload_timeout()
     52     timer_ref = Process.send_after(self(), :reload_complete, reload_timeout)
     53 
     54     {:noreply, %{state | finished_reloading_timer: timer_ref}}
     55   end
     56 
     57   def handle_info({:file_event, watcher_pid, :stop}, %{watcher_pid: watcher_pid} = state) do
     58     Logger.debug("ExSync beam monitor stopped.")
     59     {:noreply, state}
     60   end
     61 
     62   def handle_info(:reload_complete, state) do
     63     Logger.debug("ExSync reload complete!")
     64     if callback = ExSync.Config.reload_callback() do
     65       {mod, fun, args} = callback
     66       Task.start(mod, fun, args)
     67     end
     68 
     69     {:noreply, state}
     70   end
     71 end