Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Axum-style State Management #133

Closed
TTWNO opened this issue Mar 4, 2024 · 1 comment · Fixed by #138
Closed

Use Axum-style State Management #133

TTWNO opened this issue Mar 4, 2024 · 1 comment · Fixed by #138

Comments

@TTWNO
Copy link
Member

TTWNO commented Mar 4, 2024

State management is an extremely difficult problem for screen readers. Axum's method of handling state is somehow quite ingenious. Especially since we could run multiple handlers concurrently (or in parallel) and lock with sync primitives.

I'd like to implement something similar. I think this would be a great step for Odilia in terms of maintainability. And, it avoids (kind of) having global state. It at least allows me to capture partial state when needed :)

In a previous attempt at handling state, I came up with #120 , which did solve the state management issue, but it introduced an entire set of its own problems. The primary one being that it is extremely rigid, and requires adding structure members just to change what is accepted by each event handler. I got a lot of pushback for this idea, since, although it does kind of work... it introduces a significant barrier in development not likely to be cleaned up quickly. This is objectively a better system, if I can somehow figure out how to implement it.

@TTWNO TTWNO changed the title Use Axum's State Management Use Tower's State Management Mar 7, 2024
@TTWNO TTWNO changed the title Use Tower's State Management Use Axum-style State Management Mar 7, 2024
@TTWNO
Copy link
Member Author

TTWNO commented Mar 7, 2024

Tower

Tower is a Rust crate which is centred around the following signature (all three types are generic):

async fn(Request) -> Result<Response, Error>

This signature is the primary reason for having a Service trait. This trait is what the rest of Tower is built on. It allows and "Request" to be responded to, possibly with some kind of error involved. How you handle this, what traits your types implement, and if it works across thread/concurrency boundaries is left up to the user (us, Odilia developers).

Tower Layer

Layers are a way to "wrap" services, and add functionality outside of the service itself. For example, suppose I wanted to log all "Request"s of some type. Note: I can either pass the request through as suggested, or, modify it before passing it to the next layer/service.

This emulates what I was trying to do with #122 , wherein I wrote a diagram like this:

  1. Event + State -> ReadOnlyStateView
  2. ReadOnlyStateView + Event -> Vec<Command>
  3. Command + State -> MutableStateView
  4. MutableStateView + Command -> executes the change of state

I have since understood that this can be done in Tower terms (without state) like so:

  1. Event -> Request::Event(e)
  2. Request::Event(e) -> Vec<Request>
  3. e.g., Request::Speech(SSIPRequest) -> SSIP::Response
  4. e.g., Request::AddToCache(CacheItem) -> CacheResponse (maybe it failed?)

Want to add logging? Cool, just define your Layer one level up (or down, as it may be) from one of the other layers, like the one that converts events to actionable requests of the screen reader.

I hope I'm making sense. Everything becomes a layer, service, extension, piece of state, etc.

State is not handled inherently by tower so we'll likely need to create some state handling mechanisms upstream from that. But this system is: a) based on a well-known and understood model, b) used in axum as part of its state management already (i.e., we can easily adapt code), and c) is very versatile in allowing extensions and plugins to work together with the system.

Starting to formulate what we'll need for good state management here, as I suspect that will be its own Layer(?) or something like that? Still working on it.

@TTWNO TTWNO linked a pull request Mar 16, 2024 that will close this issue
10 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant