Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First attempt at basic axum-style state management (#138)
* First attempt at basic axum-style state management Empty service/handler impl I'm starting to understand the basis of Tower's service model. However, that does not make this attempt good. This only covers the case of a function that takes no arguments (and that is on purpose). In order to take more arguments, I will need to create a trait which can handle them, think something like Axum's `FromRequest`. We will need an adapted form of this, since we actually will want it for `FromEvent`. You might be wondering why we don't just use `From<Event>`, but that is annoyingly problematic, since you will get conflicting implementations because "downstream crates may implement this for ..."; as far as I can tell, this will require a custom trait. I have not yet found a way around this. Add Handler impl for up to 3 args Ah ha! I found the secret! So it's true that you can not just take in any argument for the first one. That's essentially special-cased. But, assuming that most functions' first argument would be the event itself (atspi::Event = Request), then we can make that the first argument, followed by N arguments that implement `From<State>` (roughly). This will allow us to implement `From<State>` for various types, which will be wrappers of more widely available types, for example: - Current/LastFocusedItem(CacheItem) - Current/LastCursorPos(CacheItem, u32) - EventItem(CacheItem) - etc. Add generic first parameter for Handler This allows the first parameter to be any type that implements `TryFrom<atspi::Event>`. It currently requires an unwrap due to the possibility of it being the wrong event type. This should be converted into its own Layer type, which can easily wrap the inner service, instead of manually implementing the conversion within the `Service` impl for `Handler<_>` types. * Implement generic first parameters for Handler Combined with the new atspi_event_handler function, automatically convert a HandlerService for a specific event type, into a generic event handler, which checks if the event type matches before passing it into the inner event handler. It will either: transform the event into its specific type, or abort the calling of the service with an `OdiliaError::AtspiError(AtspiError::Conversion(...))` * [WIP] attempt service-based event extractors * [WIP] Use layers to compose services instead of chaining services with combinators * You can now add boxed event handlers to the handler list * [WIP] remove Filter functions * [WIP] tower reader * [WIP] run all events handlers bound to a particular event * [WIP] first use of tower-based Odilia * [WIP] update SSIP, add speech to certain events * [WIP] return set of commands, instead of unit * [WIP] await all futures for an ev type in serial This is done to help with ordering caching handlers. It is important that caching is done first. * [WIP] Add commands enum * Make Handler trait generic over response type * Add command handler implementations * [WIP] finished and implemented serial futures, MultiService * [WIP] remove multiservice * [WIP] SerialHandlers use concrete type * [WIP] handle sequential futures better * [WIP] using boxes, get further ahead * Update interfaces in accordance with new atspi version * Use event introspection Some cleanup * Fix loop that never terminates; clone for now * Expand command handler impls to 3 params * Add new command introspection path * Add command_handlers function * Use discriminants instead of random strings * Add SendError type from tokio; you need the 'tokio' feature enabled to get the conversions * Change trait bounds to allow any Command: TryInto<C> * Remove unused deps that are now in common * Use the tokio feature for common so that we can access extra error types. * Create one and exactly one handler function for the command speak * Pass commands from handlers to command handlers with error handling; it currently works! * Remove Speech var from doc_loaded func * Add IntoCommands trait, and implement it for a tuple up to three * Use IntoCommands trait to bound response types * Add IntoCommands impl for Results which contain other Into<Command> items * Use R instead of Response alias * Add From<&str> for OdiliaCommand * Add change_priority to command handlers * Add TryIntoCommands * Rework trait bounds for additional flexibility * Use IntoCommands recursively * Use 'impl TryIntoCommand' for return type of event processor :) * Add more specific timing to logs * Add microsecond logtime * Add Speech(SsipClientAsync) AsyncTryFrom impl for state - One, we set up a few new traits: - AsyncTryFrom/AsyncTryInto - FromState - Second, we use those traits instead of `From<S>` to get arguments to handler functions. This allows us (in theory) to get cached items of various kinds. - Third, this removes some old test code. - Fourth, this adds new trait bounds using feature flags to make this work. - `try_trait_v2` for `FromResidual` - `impl_trait_in_assoc_type` (ITIAT), which is at least already has its stabalization PR opened * Remove failure case for AccessiblePrimitive::from_event * Remove use of ? in now infallible from_event and state * Update benchmarks to work on latest atspi * Fix structure of caching fns * Adjust to new cache fn style * Add caching, AsyncTryInto layer - Add new CacheLayer that injects Arc<Cache> as a second parameter of the inner Service. - Add new AsyncTryInto layer to generically convert from one type to another, then call the inner service once that has been done. - Makes sure to follow advice to use `std::mem::replace` instead of just plain copying. - Drop some trait bounds when unneeded. - Wrap all end-user events in EventItem<E> where E is a specific event type from `atspi` that implements `EventProperties`. - The complexity is overwhelming :(, hoping to crate this out, use less `impl Future` in trait (since it isn't stable, maybe just Box<dyn> for now?) - Also uses unstable trait `FromResidual` * Use dbus if no cache available for relation * Macroify the complex trait definitions - impl_handler - impl_from_state Both are generic over a variable number of parameters and error types, assuming the errors implement `Into<OdiliaError>` and the types implement various underlying traits. * Use more flexible join! macro instead of join*() * Update tower sub-module and split into various files * Bring TryIntoLayer/Service into its own file * Further split Handler trait and impl from Handlers struct * [WIP] rethinking the handler trait * [WIP] add desired layer layout * Rework Handler function to be much more generic * More generic-aware AsyncTry, auto impl for TryFromState * Genericise from_state, clone all over; remove macro for now * Genericize state service * Use new, less strict traits: require more trait bounds on *_listener functions * Add TryFromState impls, Command<C> type * Use new types in handlers, import new traits * Remove unbounded channels * Remove source of possible deadlock? * Remove .await where it is no longer needed * Add futures-concurrency crate * Remove cache layer * Remove CacheProvider trait * Remove FromState in favour of TryFromState * Add IterService and ServiceSet - IterService provides a way to stack two services together, where one take the iterated output of the other - ServiceSet provides a way to run sets of identically-typed services in series, much like SerialFutures did for Futures, but for Services. - Both take advantage of `type Future = impl Future<...>`, relying on a full Rust 2024 compiler which is not here yet. * Remove serial_fut module * DO NOT PRINT THE CACHE! * Instead of not printing the cache, just make the debug output not so long * Do not debug param of function that uses zbus::Connection * Modify ServiceSet in accordance with real-world usage * Remove unused function, use new ServiceSet for event handlers * User ServiceSet * Add ChoiceService * Add ServiceNotFound error type * fmt * Use more convenience functions * Update deps to latest zbus, seems to fix a deadlock issue * Add tokio-console capability, add script for conveneicne * Add tokio-console feature to main odilia binary * Cleanups and new inner services - Remove unused deps - Use if let ... on loop { ... } instead of while let Some(...) - Switch to using the ChoiceService model - Remove attempt at "generic handlers"; handled by ChoiceService * Move to mutli-threaded runtime; add channel indirection on zbus messages * Add comments explaining channel redirection * Create CacheEvent from state + E (event) * Add clone for choice service * public new function in IterService * Use command sub-service to layer atspi responses * Use futures-concurrency as workspace package, add rt-multi-thread feature to tokio Move futures-concurrency to workspace * Stop using channels to communicate commands Stop using channels to communicate commands * Add instrumenting on try_from_state * Add caret_moved handler (which does not work due to no focus being recorded) * Various improvements to common - Move `AccessiblePrimitive` to common from cache - Add `CaretPos` and `Focus` variants to `Command` * Remove AccessiblePrimitive from cache * Add tracing option to common, make atspi-proxies a dep * Update AccessiblePrimitive location * Add AccessibleHistory and CurrentCaretPos state structs * Add focus changed and caret pos updater handlers * Update cargo lock * Speak entire item upon focus * Add ability to unwrap Infallible values, then map them * Add new ServiceExt API for DX * Use new Odilia-specific ServiceExt * Remove return type generic on HandlerService * Add iter_into combinator * Add static version of Chooser trait * Use ChooserStatic trait, iter_into combinator * Use boxed_clone combinator * Fix docs * Add nightly to CI temporarily * Use dtolnay instead of actions-rs actions * Adjust clippy lints * Fix some other CI issues with old versions of actions-rs * Fix notify private documentation * Fix type in CI * Add clippy component for clippy job * Make sure llvm-tools are installed for the coverage components * Setup nightly MSRV * Fix yaml error * Add StateChanged newtype with predicate trait implementations * Add new error for predicate failure * Add the refinement crate for additional types, and derived-deref for convenience * Add state_changed crate to tower subcrate * Add TODO on error variant * Add focused/unfocused handlers using new StateChanged<S, E> type * Update lock file * Use latest atspi branch in object handlers * Fix bench imports * Update dashmap and use inlining for about a 10% speed improvement; tested by running benchmarks * Add more type aliases for simplicity * Use enabled field as bool * Use bool as predicate for state changed instead of i32 * Rename predicates * Use deref on CacheEvent * Use specific Focused/Unfocused types * Move CacheEvent into its own file; move Choice impls into choice * Add CacheEvent<E> types * Remove TryFromState for CacheEvent<E> from state * Use main atspi * Only speak 'doc loaded' on focused applications * Add specific nightly toolchain (for now)
- Loading branch information