Generics, Traits, and Erased Hooks
The reusable library exposes concrete orchestration types—Watchexec,
Config, ActionHandler, Event, Job, Command, Signal, Priority—and a
small number of extension contracts.
Filterer is a trait object because applications select filtering policy at
runtime. ChangeableFn<T, U> stores Arc<dyn Fn(T) -> U + Send + Sync> so
handlers can be replaced while the runtime is alive. Async action handlers
return boxed futures because each closure’s anonymous future type must fit that
replaceable slot. Notify watchers are boxed for the same native-versus-polling
choice.
Generics remain where one implementation is known locally: channel payloads,
JoinSet tasks, helper futures, and callback construction. Process hooks use
trait objects at the user-extensible boundary; CommandState stays a concrete
enum in the hot ownership loop.
Watchexec is a useful counterpoint to Apalis and Axum: dynamic configuration is a product feature here, so more type erasure is appropriate than in a pipeline fully assembled at compile time.