I'm not familiar with the crates involved, but looked at the API docs a bit. It looks like warp::Filter::map
expects a closure that is going to be executed in a multi-threaded environment, hence the need for Fn
instead of FnMut
.
For multi-threaded use, redis seems to offer MultiplexedConnection
, or ConnectionManager
. (I don't actually know how to properly construct the former.)
You will most likely need to add move
to your closure anyways in order to support a 'static
bound for warp::serve
. I.e. .map(move || { ... })
. Inside of the closure, you make sure it stays a Fn
by cloning the captured MultiplexedConnection
/ConnectionManager
and then working with that clone. If you want to do a query in the .map
, it might make sense to use .then
instead of .map
, and AsyncCommands
in order to write async code.
To give some more details to how the above relates to Fn
/FnMut
:
A closure that implements Fn
is a closure that can be called with shared (&self
) access to the closure, a closure that only implements FnMut
but not Fn
can only be called with exclusive mutable (&mut self
) access to the closure. This means that via FnMut
the closure cannot be called multiple times in parallel, e.g. on multiple threads, because &mut _
references are always exclusive; but in turn, FnMut
allows for mutable access to captured variables.
Your closure calls a &mut self
method on a captured variable, that is: it calls rediscon.set(...)
, which means it can implement FnMut
, but Fn
is no longer possible.
If, as I described above, you were to use e.g. a ConnectionsManager
, and called let my_manager = manager.clone();
, then that manager.clone()
call would be a &self
method on the captured managers
variable; further down in the closure, &mut
-methods on the variable my_manager
would still be allowed as that would be a variable that's local to the closure.
Regarding the concrete solution of using MultiplexedConnection
/ConnectionManager
, feel free to alternatively consider following different advice from anyone more knowledgeable than me about what the best practical solution here would be; as mentioned, I've just briefly looked at the API, so I cannot answer and questions about what the best trade-off would be.