-
Notifications
You must be signed in to change notification settings - Fork 249
Description
Rails 5 is now using an evented file system listener. We were seeing a bug where controller code would not be reloaded in development. I eventually tracked it down rails/rails#24990 (comment)
What I think is happening is that the listen code is initialized in a process, let's call it PID 1. Then our two puma workers boot and fork to make PID 2 and PID 3. When a file is changed the callback gets triggered inside of PID 1 but since variable changes aren't persisted across other processes PID 2 and PID 3 never know that the file was updated and they need to reload code.
Initially I thought we could re-invoke the listen code on each process to get a notification on that process. However this doesn't work:
$stdout.sync = true
require 'fileutils'
require 'listen'
FileUtils.mkdir_p("/tmp/listen")
def change_callback(modified, added, removed)
puts " Changed registered in: #{ Process.pid }"
end
def boot!
puts "Listening on process: #{ Process.pid }"
Listen.to("/tmp/listen", &method(:change_callback)).start
end
boot!
Thread.new do
sleep 5
FileUtils.touch("/tmp/listen/foo")
end
fork do
boot!
end
fork do
boot!
end
sleep 10
I would expect to see something like:
Listening on process: 68158
Listening on process: 68160
Listening on process: 68161
Changed registered in: 68158
Changed registered in: 68160
Changed registered in: 68161
However this is the output that I get
Listening on process: 68158
Listening on process: 68160
Listening on process: 68161
Changed registered in: 68158
Only the parent process is notified even though we've "booted" a Listen instance on each fork.
So my question is this: are there any good practices with using Listen with multiple processes?