-
Notifications
You must be signed in to change notification settings - Fork 100
PERL-875 - Transaction Support #163
Conversation
xdg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I haven't gone in detail through the test file, but there's enough for you to start working on changes while I get to that. :-)
Also, please note that server selection is suppose to attach TransientTransactionError or UnknownTransactionCommitResult labels, so you'll need to wrap selection and have some logic to possibly put one or the other error on. It's a little janky, but I think you could toggle the label type depending on the "force" option to send_retryable -- as only commit and abort get forced so those you can set the UnknownTransactionCommitResult label (and then abort throws away any errors).
lib/MongoDB/ClientSession.pm
Outdated
| # applied after to not override the clone with the original | ||
| defaultTransactionOptions => { | ||
| defined( $_[0] ) | ||
| && ref( $_[0] ) eq 'HASH' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These guards are necessary for line 96, too, so maybe move up for the whole sub?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah oops thought isa fired before coerce, knew it was one way or the other... heh
lib/MongoDB/ClientSession.pm
Outdated
| %{ $_[0] } | ||
| %{ $_[0] }, | ||
| # applied after to not override the clone with the original | ||
| defaultTransactionOptions => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be clearer if you cloned the default transaction options in a separate operation rather than nesting it in with the other cloning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, have done that before building this hash, along with sorting out the guards mentioned below
lib/MongoDB/ClientSession.pm
Outdated
| has _current_transaction_settings => ( | ||
| is => 'rwp', | ||
| isa => HashRef, | ||
| init_arg => undef, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs 'init_arg'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, as well as the clearer which I think I was using earlier but became redundant because we just set it completely later.
| ); | ||
|
|
||
| # Flag used to say we are still in a transaction | ||
| has _active_transaction => ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this not redundant with _transaction_state? Can it just be a method that computes a boolean based on _transaction_state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem is that theres no easy logic for whether we are in an active transaction - the state must be changed for committed or aborted before the command is sent (so that on error we are in the correct state), but if we are in one of those states and not in a transaction we need to reset the session state back to none - which would mean needing a flag notifying if we are in an actual commit or abort command - and the active transaction flag seems a lot more useful and can be set correctly in the right spots. Also means that setting the transaction state back to 'none' is an easy logic check!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. Keep it, but I'll look closer after the GA release and see what can be done about it.
|
|
||
| # Flag used to say whether any operations have been performed on the | ||
| # transaction | ||
| has _has_transaction_operations => ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this not also something we can derive from _transaction_state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not fully - the biggest problem is being able to call commit multiple times. Its easy if you are coming from starting or in_progress states, but after that you are in the committed state - at which point, its unknown what state you were in before. I thought about tracking previous state as well, but if you then call commit more than twice (which is allowed AFAICT) it would break - so find just setting a boolean more useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok.
| UnknownReplWriteConcern | ||
| NoSuchTransaction | ||
| / ) { | ||
| push @{ $err->error_labels }, 'UnknownTransactionCommitResult'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This label also needs to be applied to server selection errors, network errors, network timeout errors, and retryable write errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, those are the only occurances for it not being applied - in the latest version have had to put int he actual error code numbers in as some of the spec tests dont actually set the codeName... (error-labels.json in the last two omit tests)
| my $server_version = server_version($conn); | ||
| my $server_type = server_type($conn); | ||
|
|
||
| plan skip_all => "Requires MongoDB 4.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the 3.6 tests, I added a test helper function for "skip_unless_sessions". Please make a similar one for "skip_unless _transactions" here.
t/transactions-spec.t
Outdated
| ); | ||
|
|
||
| my $dir = path("t/data/transactions"); | ||
| my $iterator = $dir->iterator; my $index = 0; # TBSLIVER |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to remove this
t/transactions-spec.t
Outdated
|
|
||
| subtest $path => sub { | ||
|
|
||
| for my $test ( @{ $plan->{tests} } ) { # TBSLIVER run specific subtest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
t/transactions-spec.t
Outdated
| # a seperate step. | ||
| $test_db->run_command([ create => $test_coll_name ]); | ||
|
|
||
| my $test_coll = $test_db->get_collection( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Redundant. Just save the first one at line 121 before you call 'drop' on it.
xdg
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks really close. Please make these changes and then get started on rebasing and integrating with PERL-918 work.
lib/MongoDB/ClientSession.pm
Outdated
| }; | ||
| # Will cause the isa requirement to fire | ||
| return unless defined( $_[0] ) && ref( $_[0] ) eq 'HASH'; | ||
| my $dto = $_[0]->{defaultTransactionOptions}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be making a clone as well?
lib/MongoDB/ClientSession.pm
Outdated
| $dto ||= {}; | ||
| $_[0] = { | ||
| causalConsistency => 1, | ||
| %{ $_[0] }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this confusing because there are only two available options right now and both are also listed in the clone. Maybe just assign directly to the copies?
{ causalConsistency => $_[0]->{causalConsistency}, defaultTransactionOptions => { %{$_[0]->{defaultTransactionOptions} || {} }}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mm... premature optimisation I think I did there, had mis-remembered the session spec whcih just says 'in a backwards compatible way' for storing sessionOptions. Have changed it to direct assignment anyway.
|
|
||
| # increment transaction id before write, but otherwise is the same for both attempts | ||
| $op->session->_server_session->_increment_transaction_id; | ||
| $op->session->_increment_transaction_id; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
lib/MongoDB/_TransactionOptions.pm
Outdated
| ); | ||
| use namespace::clean -except => 'meta'; | ||
|
|
||
| # Options provided during strart transaction |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo. :-)
3e9d68a to
075d97f
Compare
one requires PERL-918 to be finished, the other needs some thought
2702d1f to
d8bd31f
Compare
|
that should be everything, Have had to update the dependency on Safe::Isa for the $_call_if_can usage - although that could be downgraded again if that code is modified to not use that function. |
|
Rebased, squashed and merged as 9162d1d |
First pass of Transaction Support for MongoDB 4.0
Currently the test (
t/transactions-spec.t) has several TODO parts in the test - the majority of these require PERL-918 ticket to be completed, however they should all start working after that point.The run-command test
run command fails with explicit secondary read preferencealso has a TODO on it. The test yml looks like this:the issue here is, the spec specifically states
The transaction's read preference MUST override all other user configurable read preferences. This is obvious for a client, database, or collection level read preference configuration (and is how it is normally inherited), and is arguable that an explicit run_command with a read preference would also count as user configurable. As well as that, there is no way to determine at the op level, without adding a large amount of extra logic, that the read preference was set explicitly instead of inherited - and this seems to also be the only case or way for a read preference to be set outside of a normal config option.Either way this is now passed forward for initial code review, pending any changes to the spec in the meantime.