Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
Unreleased
==========

* feat: File throttling to prevent files being compiled multiple times in quick succession and tests being run multiple times due to one "change".

0.5.0 / 2018-05-01
==================
Expand Down
34 changes: 32 additions & 2 deletions lib/cortex/file_watcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ defmodule Cortex.FileWatcher do
use GenServer

@watched_dirs ["lib/", "test/", "apps/"]
@throttle_timeout_ms 100

defmodule State do
defstruct [:watcher_pid, :file_events, :throttle_timer]
end

##########################################
# Public API
Expand All @@ -26,14 +31,17 @@ defmodule Cortex.FileWatcher do

FileSystem.subscribe(watcher_pid)

{:ok, %{watcher_pid: watcher_pid}}
{:ok, %State{watcher_pid: watcher_pid, throttle_timer: nil, file_events: %{}}}
end

def handle_info(
{:file_event, watcher_pid, {path, _events}},
%{watcher_pid: watcher_pid} = state
) do
GenServer.cast(Controller, {:file_changed, file_type(path), path})
state =
state
|> maybe_update_throttle_timer()
|> track_file_events(path)

{:noreply, state}
end
Expand All @@ -44,6 +52,16 @@ defmodule Cortex.FileWatcher do
{:noreply, state}
end

def handle_info(:throttle_timer_complete, state) do
%State{file_events: file_events} = state

Enum.each(file_events, fn {path, file_type} ->
GenServer.cast(Controller, {:file_changed, file_type, path})
end)

{:noreply, %State{state | file_events: %{}, throttle_timer: nil}}
end

def handle_info(data, state) do
Logger.info("Get unexcepted message #{inspect(data)}, ignore...")

Expand All @@ -54,6 +72,18 @@ defmodule Cortex.FileWatcher do
# Private Helpers
##########################################

defp maybe_update_throttle_timer(%State{throttle_timer: nil} = state) do
throttle_timer = Process.send_after(self(), :throttle_timer_complete, @throttle_timeout_ms)
%State{state | throttle_timer: throttle_timer}
end

defp maybe_update_throttle_timer(state), do: state

defp track_file_events(%State{file_events: file_events} = state, path) do
file_events = Map.put(file_events, path, file_type(path))
%State{state | file_events: file_events}
end

# public only because it is tested
@spec file_type(Path.t()) :: :lib | :test | :unknown
def file_type(path) do
Expand Down