Class: Quonfig::DatadirWatcher
- Inherits:
-
Object
- Object
- Quonfig::DatadirWatcher
- Defined in:
- lib/quonfig/datadir_watcher.rb
Overview
Watches a datadir for changes and fires on_change once per debounced burst. Wraps the ‘listen` gem (github.com/guard/listen), which uses platform-native backends (FSEvents on macOS, inotify on Linux, polling fallback on Windows).
The caller owns parse-then-swap: this class only fires the trigger. Registration failures (read-only fs, immutable container, native backend missing) are surfaced via on_error; in that case start returns false and no listener is held.
Mirrors sdk-node/src/datadirWatcher.ts (qfg-mol-0kr) modulo Ruby idioms: listen does not have an equivalent to Node’s ‘fs.watch(recursive:true)`, but it watches recursively by default.
Constant Summary collapse
- LISTEN_FACTORY =
Indirection seam for tests. Production code uses ::Listen; tests can swap in a class that raises from ‘.to` to exercise the registration- failure path without needing a read-only filesystem.
nil
Instance Method Summary collapse
-
#initialize(datadir:, debounce_ms:, on_change:, on_error:) ⇒ DatadirWatcher
constructor
resolved lazily so the gem can be required late.
-
#start ⇒ Object
Start the underlying file watcher.
-
#stop ⇒ Object
Stop the watcher and cancel any pending debounce.
Constructor Details
#initialize(datadir:, debounce_ms:, on_change:, on_error:) ⇒ DatadirWatcher
resolved lazily so the gem can be required late
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/quonfig/datadir_watcher.rb', line 25 def initialize(datadir:, debounce_ms:, on_change:, on_error:) @datadir = datadir @debounce_seconds = debounce_ms.to_f / 1000.0 @on_change = on_change @on_error = on_error @mutex = Mutex.new @scheduled_task = nil @listener = nil @closed = false end |
Instance Method Details
#start ⇒ Object
Start the underlying file watcher. Returns true on success, false if registration failed (in which case on_error has already been called and the caller should continue without auto-reload).
Blocks until the listener is in its :processing_events state (or a short safety timeout elapses) so a customer writing to the datadir immediately after the Client constructor returns is detected, rather than racing the listen backend’s async setup.
44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/quonfig/datadir_watcher.rb', line 44 def start resolved = File.realpath(@datadir) factory = self.class::LISTEN_FACTORY || ::Listen @listener = factory.to(resolved) do |_modified, _added, _removed| schedule_reload end @listener.start wait_for_listener_ready true rescue StandardError => e @on_error.call(e) false end |
#stop ⇒ Object
Stop the watcher and cancel any pending debounce. Idempotent.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/quonfig/datadir_watcher.rb', line 59 def stop task, listener = @mutex.synchronize do @closed = true t = @scheduled_task l = @listener @scheduled_task = nil @listener = nil [t, l] end begin task&.cancel rescue StandardError # best-effort; caller already in shutdown end begin listener&.stop rescue StandardError # best-effort end end |