-
Notifications
You must be signed in to change notification settings - Fork 321
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
feat: allow Middleware to be added at any time #747
base: main
Are you sure you want to change the base?
Conversation
`Arc` has thing kind-of-magic method called `make_mut` which can do an interior clone if there are immutable references. This uses that to allow middleware to be registered on a server while it is already listening, without interfering with existing requests.
@Fishrock123 I don't believe this will work: this will create "unique ownership" which means that when new middleware is pushed, it's pushed onto a different middleware stack than the one that's used, and it effectively does nothing. In order to enable middleware to be pushed after the server has started, we should use an But those changes have significant performance implications. So I'd like to get a good sense what's motivating this change first. |
I would have thought that too, but that's not what the std lib examples shows: use std::sync::Arc;
let mut data = Arc::new(5);
*Arc::make_mut(&mut data) += 1; // Won't clone anything
let mut other_data = Arc::clone(&data); // Won't clone inner data
*Arc::make_mut(&mut data) += 1; // Clones inner data
*Arc::make_mut(&mut data) += 1; // Won't clone anything
*Arc::make_mut(&mut other_data) *= 2; // Won't clone anything
// Now `data` and `other_data` point to different allocations.
assert_eq!(*data, 8);
assert_eq!(*other_data, 12); |
@Fishrock123 that example shows that *Arc::make_mut(&mut data) += 1; // Clones inner data which is what brings the middleware out of sync. Pushing onto this would require a clone, and then push -- which creates a separate middleware stack. For shared ownership to work this would need to be an |
I think that would be a feature though? Inserting a middleware when a request is potentially on the way out is a good way to cause indecipherable timing errors. This would copy the stack if necessary if a middleware was added late, and then all future requests would use that without interfering with existing requests. That said I'm still not really convinced it's a fundamentally good idea, but this shows it can be done like this. |
Arc
has thing kind-of-magic method calledmake_mut
which can do an interior clone if there are immutable references.This uses that to allow middleware to be registered on a server while it is already listening, without interfering with existing requests.
To be fair, I'm not 100% sure we should actually do this since supporting this use-case seems a bit questionable but if anyone finds it useful we can totally do it...
Edit: note that this does not cover doing the same for routes, which would require
Router
to beClone
.