generated from mattbrictson/gem
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rebuild
--watch
event loop to simplify; fix concurrency issues (#40)
* Rebuild `--watch` event loop to simplify, fix concurrency issues Before, the watcher event loop relied on multiple threads and raised an exception to interrupt the main thread whenever a file system change event happened. This was messy and resulted in zombie processes and other weird behavior when a file system change was detected in the middle of running tests. This commit refactors the implementation to use a new `EventQueue` class. It leverages the buffering inherent in stdin, plus uses a thread-safe queue for placing file system change events, and then "pops" the next of these in each iteration of the event loop. To avoid starting a separate thread for reading key presses, the "pop" operation takes turns polling stdin (peeking at its buffer to see if a key press happened) and blocking for short period waiting for file system events. The result is cleaner, easier to test, and not prone to the zombie process bug. * Require io/wait for older Ruby versions * Add workaround for Ruby 3.1
- Loading branch information
1 parent
5175211
commit 5bd7ef0
Showing
5 changed files
with
185 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
require "io/console" | ||
|
||
module MightyTest | ||
class Watcher | ||
class EventQueue | ||
def initialize(console: Console.new, file_system: FileSystem.new) | ||
@console = console | ||
@file_system = file_system | ||
@file_system_queue = Thread::Queue.new | ||
end | ||
|
||
def pop | ||
console.with_raw_input do | ||
until stopped? | ||
if (key = console.read_keypress_nonblock) | ||
return [:keypress, key] | ||
end | ||
if (paths = pop_files_changed) | ||
return [:file_system_changed, paths] | ||
end | ||
end | ||
end | ||
end | ||
|
||
def start | ||
raise "Already started" unless stopped? | ||
|
||
@file_system_listener = file_system.listen do |modified, added, _removed| | ||
paths = [*modified, *added].uniq | ||
file_system_queue.push(paths) unless paths.empty? | ||
end | ||
true | ||
end | ||
|
||
def restart | ||
stop | ||
start | ||
end | ||
|
||
def stop | ||
file_system_listener&.stop | ||
@file_system_listener = nil | ||
end | ||
|
||
def stopped? | ||
!file_system_listener | ||
end | ||
|
||
private | ||
|
||
attr_reader :console, :file_system, :file_system_listener, :file_system_queue | ||
|
||
def pop_files_changed | ||
paths = try_file_system_pop(timeout: 0.2) | ||
return if paths.nil? | ||
|
||
paths += file_system_queue.pop until file_system_queue.empty? | ||
paths.uniq | ||
end | ||
|
||
if RUBY_VERSION.start_with?("3.1.") | ||
# TODO: Remove once we drop support for Ruby 3.1 | ||
require "timeout" | ||
def try_file_system_pop(timeout:) | ||
Timeout.timeout(timeout) do | ||
file_system_queue.pop | ||
end | ||
rescue Timeout::Error | ||
nil | ||
end | ||
else | ||
def try_file_system_pop(timeout:) | ||
file_system_queue.pop(timeout:) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.