pub struct WATCHER;
Expand description
File system watcher service.
This is mostly a wrapper around the notify
crate, integrating it with events and variables.
Implementations§
source§impl WATCHER
impl WATCHER
sourcepub fn debounce(&self) -> ArcVar<Duration>
pub fn debounce(&self) -> ArcVar<Duration>
Gets a read-write variable that defines interval awaited between each FS_CHANGES_EVENT
. If
a watched path is constantly changing an event will be emitted every elapse of this interval,
the event args will contain a list of all the changes observed during the interval.
Note that the first event notifies immediately, only subsequent events within this interval are debounced.
Is 100.ms()
by default.
sourcepub fn sync_debounce(&self) -> ArcVar<Duration>
pub fn sync_debounce(&self) -> ArcVar<Duration>
Gets a read-write variable that defines interval awaited between each sync
write.
Is 100.ms()
by default.
sourcepub fn poll_interval(&self) -> ArcVar<Duration>
pub fn poll_interval(&self) -> ArcVar<Duration>
Gets a read-write variable that defines the fallback poll watcher interval.
When an efficient watcher cannot be used a poll watcher fallback is used, the poll watcher reads the directory or path every elapse of this interval. The poll watcher is also used for paths that do not exist yet, that is also affected by this interval.
Is 1.secs()
by default.
sourcepub fn shutdown_timeout(&self) -> ArcVar<Duration>
pub fn shutdown_timeout(&self) -> ArcVar<Duration>
Maximum time the service keeps the process alive to process pending IO operations when the app shuts down.
Is 1 minute by default.
sourcepub fn watch(&self, file: impl Into<PathBuf>) -> WatcherHandle
pub fn watch(&self, file: impl Into<PathBuf>) -> WatcherHandle
Enable file change events for the file
.
Returns a handle that will stop the file watch when dropped, if there is no other active handler for the same file.
Note that this is implemented by actually watching the parent directory and filtering the events, this is done to ensure the watcher survives operations that remove the file and then move another file to the same path.
See watch_dir
for more details.
sourcepub fn watch_dir(
&self,
dir: impl Into<PathBuf>,
recursive: bool,
) -> WatcherHandle
pub fn watch_dir( &self, dir: impl Into<PathBuf>, recursive: bool, ) -> WatcherHandle
Enable file change events for files inside dir
, also include inner directories if recursive
is true
.
Returns a handle that will stop the dir watch when dropped, if there is no other active handler for the same directory.
The directory will be watched using an OS specific efficient watcher provided by the notify
crate. If there is
any error creating the watcher, such as if the directory does not exist yet a slower polling watcher will retry periodically
until the efficient watcher can be created or the handle is dropped.
sourcepub fn read<O: VarValue>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Option<O> + Send + 'static,
) -> ReadOnlyArcVar<O>
pub fn read<O: VarValue>( &self, file: impl Into<PathBuf>, init: O, read: impl FnMut(Result<WatchFile>) -> Option<O> + Send + 'static, ) -> ReadOnlyArcVar<O>
Read a file into a variable, the init
value will start the variable and the read
closure will be called
once immediately and every time the file changes, if the closure returns Some(O)
the variable updates with the new value.
Dropping the variable drops the read watch. The read
closure is non-blocking, it is called in a task::wait
background thread.
sourcepub fn read_status<O, S, E>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Result<Option<O>, E> + Send + 'static,
) -> (ReadOnlyArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherReadStatus<E>,
pub fn read_status<O, S, E>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Result<Option<O>, E> + Send + 'static,
) -> (ReadOnlyArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherReadStatus<E>,
Same operation as read
but also tracks the operation status in a second var.
The status variable is set to WatcherReadStatus::reading
as soon as read
starts and
is set to WatcherReadStatus::idle
when read returns. If read returns a value the status
only updates to idle when the new value is available on the var, or because read the same value.
sourcepub fn read_dir<O: VarValue>(
&self,
dir: impl Into<PathBuf>,
recursive: bool,
init: O,
read: impl FnMut(WalkDir) -> Option<O> + Send + 'static,
) -> ReadOnlyArcVar<O>
pub fn read_dir<O: VarValue>( &self, dir: impl Into<PathBuf>, recursive: bool, init: O, read: impl FnMut(WalkDir) -> Option<O> + Send + 'static, ) -> ReadOnlyArcVar<O>
Read a directory into a variable, the init
value will start the variable and the read
closure will be called
once immediately and every time any changes happen inside the dir, if the closure returns Some(O)
the variable updates with the new value.
The read
closure parameter is a directory walker from the walkdir
crate.
The directory walker is pre-configured to skip the dir
itself and to have a max-depth of 1 if not recursive
, these configs can.
Dropping the variable drops the read watch. The read
closure is non-blocking, it is called in a task::wait
background thread.
sourcepub fn read_dir_status<O, S, E>(
&self,
dir: impl Into<PathBuf>,
recursive: bool,
init: O,
read: impl FnMut(WalkDir) -> Result<Option<O>, E> + Send + 'static,
) -> (ReadOnlyArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherReadStatus<E>,
pub fn read_dir_status<O, S, E>(
&self,
dir: impl Into<PathBuf>,
recursive: bool,
init: O,
read: impl FnMut(WalkDir) -> Result<Option<O>, E> + Send + 'static,
) -> (ReadOnlyArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherReadStatus<E>,
Same operation as read_dir
but also tracks the operation status in a second var.
The status variable is set to WatcherReadStatus::reading
as soon as read
starts and
is set to WatcherReadStatus::idle
when read returns. If read returns a value the status
only updates to idle when the new value is available on the var, or because read the same value.
sourcepub fn sync<O: VarValue>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Option<O> + Send + 'static,
write: impl FnMut(O, Result<WriteFile>) + Send + 'static,
) -> ArcVar<O>
pub fn sync<O: VarValue>( &self, file: impl Into<PathBuf>, init: O, read: impl FnMut(Result<WatchFile>) -> Option<O> + Send + 'static, write: impl FnMut(O, Result<WriteFile>) + Send + 'static, ) -> ArcVar<O>
Bind a file with a variable, the file
will be read
when it changes and be write
when the variable changes,
writes are only applied on success and will not cause a read
on the same sync task. The init
value is used to
create the variable, if the file
exists it will be read
once at the beginning.
Dropping the variable drops the read watch. The read
and write
closures are non-blocking, they are called in a task::wait
background thread.
§Sync
The file synchronization ensures that the file is only actually modified when writing is finished by writing
to a temporary file and committing a replace only if the write succeeded. The file is write-locked for the duration
of write
call, but the contents are not touched until commit. See WriteFile
for more details.
The FsWatcherManager
blocks on app exit until all writes commit or cancel.
§Read Errors
Not-found errors are handled by the watcher by calling write
using the current variable value, other read errors
are passed to read
. If read
returns a value for an error the write
closure is called to override the file,
otherwise only the variable is set and this variable update does not cause a write
.
§Write Errors
If write
fails the file is not touched and the temporary file is removed, if the file path
does not exit all missing parent folders and the file will be created automatically before the write
call.
Note that WriteFile::commit
must be called to flush the temporary file and attempt to rename
it, if the file is dropped without commit it will cancel and log an error, you must call WriteFile::cancel
to correctly avoid writing.
If the cleanup after commit fails the error is logged and ignored.
If write fails to even create the file and/or acquire a write lock on it this error is the input for
the write
closure.
§Error Handling
You can call services or set other variables from inside the read
and write
closures, this can be
used to get a signal out that perhaps drops the sync var (to stop watching), alert the user that the
file is out of sync and initiate some sort of recovery routine.
If the file synchronization is not important you can just ignore it, the watcher will try again on the next variable or file update.
§Status
Note that read
and write
run in background task threads, so if you are tracking the operation
status in a separate variable you may end-up with synchronization bugs between th status variable
and the actual result variable, you can use sync_status
to implement racing-free status tracking.
sourcepub fn sync_status<O, S, ER, EW>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Result<Option<O>, ER> + Send + 'static,
write: impl FnMut(O, Result<WriteFile>) -> Result<(), EW> + Send + 'static,
) -> (ArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherSyncStatus<ER, EW>,
pub fn sync_status<O, S, ER, EW>(
&self,
file: impl Into<PathBuf>,
init: O,
read: impl FnMut(Result<WatchFile>) -> Result<Option<O>, ER> + Send + 'static,
write: impl FnMut(O, Result<WriteFile>) -> Result<(), EW> + Send + 'static,
) -> (ArcVar<O>, ReadOnlyArcVar<S>)where
O: VarValue,
S: WatcherSyncStatus<ER, EW>,
Same operation as sync
but also tracks the operation status in a second var.
The status variable is set to WatcherReadStatus::reading
as soon as read
starts and
is set to WatcherReadStatus::idle
when read returns. If read returns a value the status
only updates to idle when the new sync value is available, or because read the same value.
The status variable is set to WatcherSyncStatus::writing
as soon as it updates and
is set to WatcherReadStatus::idle
only when the new sync value is available, either
by update or because read the same value.
sourcepub fn on_file_changed(
&self,
file: impl Into<PathBuf>,
handler: impl AppHandler<FsChangesArgs>,
) -> EventHandle
pub fn on_file_changed( &self, file: impl Into<PathBuf>, handler: impl AppHandler<FsChangesArgs>, ) -> EventHandle
Watch file
and calls handler
every time it changes.
Note that the handler
is blocking, use async_app_hn!
and task::wait
to run IO without
blocking the app.
sourcepub fn on_dir_changed(
&self,
dir: impl Into<PathBuf>,
recursive: bool,
handler: impl AppHandler<FsChangesArgs>,
) -> EventHandle
pub fn on_dir_changed( &self, dir: impl Into<PathBuf>, recursive: bool, handler: impl AppHandler<FsChangesArgs>, ) -> EventHandle
Watch dir
and calls handler
every time something inside it changes.
Note that the handler
is blocking, use async_app_hn!
and task::wait
to run IO without
blocking the app.
sourcepub fn annotate(&self, note: Arc<dyn FsChangeNote>) -> FsChangeNoteHandle
pub fn annotate(&self, note: Arc<dyn FsChangeNote>) -> FsChangeNoteHandle
Push a note
that will be cloned on all subsequent change events until it the returned handle is dropped.
This can be used to tag all events that happened over a period of time, something you can’t do just by receiving the events due to async delays caused by debounce.
Note that the underlying system events the notify
crate uses are not guaranteed to be synchronous.
Auto Trait Implementations§
impl Freeze for WATCHER
impl RefUnwindSafe for WATCHER
impl Send for WATCHER
impl Sync for WATCHER
impl Unpin for WATCHER
impl UnwindSafe for WATCHER
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read more