vans163 / rebar3_auto

Rebar3 plugin to auto compile and reload on file change.
Other
55 stars 14 forks source link

compilation is non-blocking #25

Open brigadier opened 7 months ago

brigadier commented 7 months ago

Sometimes it takes several seconds to compile changed modules. This compilation is asynchronous so it won't lock console prompt thus it is possible to call a function which still would use code from the old version of a module, opaque to the user. There's even no indication whether the process of compilation and changing of code has been completed or not. Is it possible to make compilation synchronous and lock the console until the compilation process is completed?

vans163 commented 7 months ago

Recompiling this way BTW is considered debug behaviour and should not be used in production, does this happen so often it throws your debug/local environment out of sync each time? Because if it happens 1/3 or 1/10 times, thats OK for something not meant to be used in production. The correct way to hotload in production so everything stays in sync is to use releases.

Adding this would be complex but something using https://www.erlang.org/doc/man/erlang.html#suspend_process-2 could work. Figure out which processes are critical to not suspend, spawn a "suspender" process, suspend all, recompile, resume. I think you could even code this yourself in minimal time

:erlang.spawn(fn()->
  me = self()
  pids = :erlang.processes() -- [me]

  pids |> Enum.each(& :erlang.suspend_process(&1))
  recompile
  pids |> Enum.each(& :erlang.resume_process(&1))
end)
brigadier commented 7 months ago

Yes, it's debug so it is not a big problem, but it happens often as I run some code over a big chunk of semistructured data using different rules and to do this I run the same function with just [Arrow up - Enter] in the console, so it is almost always faster than compilation. Maybe not suspend but at least some indication that compilation process is completed would help a lot.

vans163 commented 7 months ago

If you issue a r3:do(compile) in the console (instead of just saving the file), does it return only once the project is fully recompiled?

Also what about rebar_agent:do(compile) instead as well?

brigadier commented 7 months ago

r3:do returns only after the project is recompiled, tested it with r3:do(compile), mymodule:run(). after changing the run function. rebar_agent:do(compile) same, it locks the console prompt until everything is compiled.

brigadier commented 7 months ago

looks like something like this does the job

Me = self(),
 F = fun() -> 
  erlang:display(start), 
  Pid = shell:whereis(), 
  erlang:suspend_process(Pid), 
  try
    rebar_agent:do(compile)
  after
    erlang:resume_process(Pid)
  end,
  erlang:display('end'),
  Me ! done 
end,
spawn(F),
receive
  done -> ok
end.