zng_ext_fs_watcher

Struct WATCHER

source
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

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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.

source

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§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
source§

impl<T> StateValue for T
where T: Any + Send + Sync,