philbooth · GitHub

Variation on the above, this time the helper method takes an FnOnce for running the action code before db_handles goes out of scope:

impl DBExecutor {
    fn lock<R>(&self, user_id: &str, action: &FnOnce(MutexGuard<DBManager>) -> Result<R, Error>) -> Result<R, Error> {
        self
            .db_handles
            .read()
            .map_err(|error| Error::new(ErrorKind::Other, "db handles lock error"))
            .and_then(|db_handles| {
                db_handles
                    .get(user_id)
                    .ok_or_else(|| Error::new(ErrorKind::NotFound, "unknown user"))
                    .and_then(|mutex| {
                        mutex
                            .lock()
                            .map_err(|error| Error::new(ErrorKind::Other, "db manager mutex error"))
                            .and_then(action)
                    })
            })
    }
}
error[E0277]: the trait bound `for<'r> std::ops::FnOnce(std::sync::MutexGuard<'r, db::models::DBManager>) -> std::result::Result<R, std::io::Error>: std::ops::Fn<(std::sync::MutexGuard<'_, db::models::DBManager>,)>` is not satisfied
  --> src/dispatcher.rs:66:30
   |
66 |                             .and_then(action)
   |                              ^^^^^^^^ the trait `std::ops::Fn<(std::sync::MutexGuard<'_, db::models::DBManager>,)>` is not implemented for `for<'r> std::ops::FnOnce(std::sync::MutexGuard<'r, db::models::DBManager>) -> std::result::Result<R, std::io::Error>`
   |
   = note: required because of the requirements on the impl of `std::ops::FnOnce<(std::sync::MutexGuard<'_, db::models::DBManager>,)>` for `&for<'r> std::ops::FnOnce(std::sync::MutexGuard<'r, db::models::DBManager>) -> std::result::Result<R, std::io::Error>`

Read the original on github.com ↗