в middleware в actix_web транзакцию и закоммитить ее после того, того, как возвращается response. Я создаю транзакцию и прокидываю ее в request container, а потом делаю коммит. Проблема в том, что я не могу транзакцию обернуть в Arc, так как метод commit (self) поглощает транзакцию и я не могу "move out of transaction". Поэтому я решил прокидывать указатель и разыменовывать его, но это уже unsafe код, которого хотелось бы избежать. Может есть какие-то другие варианты решения этой проблемы?
let transaction = get_transaction(...);
req.extensions_mut().insert(&transaction as *const _);
let res = service.call(req).await?; // moves req
transaction.commit().await.unwrap(); // moves transaction
Ok(res)
тогда у тебя твой код не является валидным потому что в нем подразумевается, что req после вызова service.call не будет никому доступен, а значит, можно спокойно использовать transaction и вызывать у нее commit но если это действительно соблюдается, то и копий Arc других не останется, а значит, у тебя всегда будет try_unwrap = Ok
Ну впринципе да, я согласен, но если это только мой код и я точно знаю, что никто больше request дергать не будет, а тем более вызывать у него транзакции, то я все ровно обречен на использование unsafe или есть какие-то еще техники для этого рода случаев?
ну как я и сказал, раз ты поднял тему Arc, то ты можешь его спокойно использовать и после вызова service.call(req) использовать Arc::try_unwrap можно еще какую-то структуру иметь, что ты можешь передавать, и иметь у нее impl Drop, и у тебя будет гарантия, что при дропе объекта произойдет коммит транзакции типа struct SomeStruct { tx: Option<Transaction>, } impl Drop for SomeStruct { fn drop(&mut self) { if let Some(tx) = self.tx.take() { tx.commit(): } } }
Обсуждают сегодня