-
-
Notifications
You must be signed in to change notification settings - Fork 12
Permit recovery of failed transaction commit or rollback #56
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I think that is a conception case. If user want's the recovery possibility, they need use the What is your opinion @jairinhohw ? |
I think the only reason a commit or rollback would fail is a connection error (as stated in the issues linked), so this might have been a problem in the < 3.0 versions of the firebird, but for 3.0 and above, the connection is encrypted, so a network error makes the whole connection invalid, as the encryption state gets de-synchronized, so i don't this this is a problem in most of the cases, as recovery of the transaction is impossible. |
I do think for it's appropriate to consume the transaction in both cases, since otherwise the user has to always think about whether But I also do think there should be a 'standard' way (ie in the high-level crate) to say "I want to do a commit/rollback without retaining, but I want to hold on to the transaction or get it back if there's a problem", with documentation warnings about trying to reuse closed handles. Maybe a more interesting reason why this could matter is that, semantically there is (or, there can be) a difference: choosing whether to borrow or consume gives more fine grained possibilities to an implementer of Regarding the previous comment about versions: actually I work with an old Firebird version (< 2.5 is all I will say here) from a very old corporate Delphi codebase. Some of my interest in this crate comes from the ease of using Rust's C ffi to talk with Delphi with little to no overhead. For those reasons I still propose to add some way to either keep the transaction, or else get back the transaction with an error. The simplest I could think of would be separate borrowing methods, one for commit and one for rollback. |
Ok, its a nice point. Maybe we can make two versions of transaction implementation commit/rollback methods using cargo features. The default still the consume way. |
I propose to create a new function like this (one for commit, and other for rollback): /// Rollback the current transaction changes, returning the transaction on error
pub fn rollback_recoverable(mut self) -> Result<(), (FbError, Self)> {
if let Err(e) = self.data.rollback(self.conn) {
return Err((e, self));
}
ManuallyDrop::new(self);
Ok(())
} This will allow to recover the transaction on failure, and avoid allowing the user to call commit / rollback more than once |
Good idea. This will be part of default feature or only available with a special cargo feature? |
I don't see a reason to add a cargo feature to enable this, as it will not replace the existing commit and rollback. |
I'd like to leave this issue open for a little bit to explore other ideas. If you want to make a PR and just get something working now I think that would be okay. Some further thoughts on this: If we had something like that we could have a very elegant way like for example I wonder if there's a way to emulate this with not too much overhead. Maybe similar to what another complicated solution, but one which provides a whole different way of looking at sequential operations, is to only allow access to transactions after failure using closures, either in the function arguments ( |
@fernandobatels @jairinhohw I think i found the solution I was looking for to this and to #61 Please try to see if you can figure out a way to call advantages:
You can think of this like a compile-time verified Finite State Machine using the type system. This is possible in Rust only because it has a concept of 'moves' which here are used to statically disallow reuse of the edit: btw this kind of approach is called the TypeState Pattern (edit:different article) |
While i have some concerns about the error handling part, we can work on it when trying to implement, however there is a bigger problem. The existing Also the existing |
Yes, this would require to make Anyways I won't be pushy if it's too far from |
I like the idea of having only the connection create and manage the transactions, as i wanted to have just one transaction per connection that is reused by default. I don't know for sure, but i think it would be better to add the marker to the |
Very nice article |
So, I think we can keep idea of implement the '_retaining' methods for now. This is a more simple approach. |
At present,
Transaction::commit
andTransaction::rollback
have signaturespub fn commit (mut self) -> Result<(), FbError>
andpub fn rollback(mut self) -> Result<(), FbError>
Can these ever fail without actually releasing resources? I found this and this which indicate that it's been a problem in the past.
If this does happen, the caller can't even attempt to recover straightforwardly because these methods consume the transaction.
The text was updated successfully, but these errors were encountered: