Skip to content

Transactions #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 102 commits into
base: master
Choose a base branch
from
Open

Transactions #3

wants to merge 102 commits into from

Conversation

levon80999
Copy link
Owner

No description provided.

klinson and others added 30 commits January 8, 2020 17:20
…ployment replica sets or sharded clusters

transaction support create/insert,update,delete,etc operation
Supports infinite-level nested transactions, but outside transaction rollbacks do not affect the commit of inside transactions
```
DB::beginTransaction();
DB::collection('users')->where('name', 'klinson')->update(['age' => 18]);
DB::transaction(function () {
    DB::collection('users')->where('name', 'mongodb')->update(['age' => 30]);
});
DB::rollBack();
```
# Conflicts:
#	.travis.yml
#	README.md
# Conflicts:
#	tests/TestCase.php
@levon80999 levon80999 requested review from jmikola and alcaeus and removed request for jmikola and alcaeus October 20, 2022 11:24

echo setup.sh time now: `date +"%T" `
mongo --host ${mongodb1}:${port} <<EOF
var cfg = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't look like transactionLifetimeLimitSeconds was ever added to the configuration. I remember the three of us spoke about that in a meeting sometime after I left this comment, and @alcaeus agreed that it should be added.

Additionally, this entire mongosh command should be reduced to rs.initiate(), which is much more concise. If the replica set configuration is ever modified down the line, we can always change this later -- although it'd probably be easier to use rs.add() instead of writing a verbose configuration like we have here.

{
/**
* A list of transaction session.
* @var Session|null
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This annotation seems redundant in light of the property type below.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already removed

*/
public function getSession(): ?Session
{
return $this->session ?? null;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ?? null necessary? The property declaration already agrees with this method's return type.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, it is, as the typed property is not initialised (see https://3v4l.org/ct02o). This can be avoided by initialising the property with a null value in the declaration (see https://3v4l.org/NkjmT).

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

* To use transactions on MongoDB 4.2 deployments(replica sets and sharded clusters), clients must use MongoDB drivers updated for MongoDB 4.2.
*
* @see https://docs.mongodb.com/manual/core/transactions/
* @return void
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The @param and @return annotations here are redundant. My original point was that if PHP syntax can communicate the necessary information there is no reason to preserve doc block comments.

In @alcaeus' recent PHPLIB PRs where he added type hints, he removed doc block annotations unless they communicated something that couldn't be expressed the allowed PHP syntax (e.g. some union types).

$this->session = $session;
}

$callbackFunction = function (Session $session) use ($callback, &$attemptsLeft, &$callbackResult) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment should be added to the source code, as it's helpful context for anyone that comes across this method definition in the future.

$this->throwExceptionIfTransactionDoesNotStart();
$session = $this->getSession();

$session?->abortTransaction();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I'm assuming the decision to not NOP in these methods when there is no active session is intentional. I recall we spoke about this during the last meeting but I forgot what the conclusion was. I think the original PR (or perhaps Eloquent itself) did NOP and maybe we talked about not wanting to preserve that behavior.


What is the point of using the null-safe operator if you've already verified that the session exists with throwExceptionIfTransactionDoesNotStart()? I could imagine this being necessary to satisfy code analysis tools since they might not be able to infer that throwExceptionIfTransactionDoesNotStart() guaranteed that getSession() would never return null; however, that's not relevant here.

In light of my later comments on throwExceptionIfTransactionDoesNotStart (suggesting it be renamed and reduced in complexity), I think what you really need here is a variant of getSession() that returns Session instead of ?Session. Perhaps a private method named getSessionOrThrow(). That could then reduce this method to a single statement:

$this->getSessionOrThrow()->abortTransaction();

This suggestion also applies to other methods where you're using ?-> after throwExceptionIfTransactionDoesNotStart().

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of using the null-safe operator if you've already verified that the session exists with throwExceptionIfTransactionDoesNotStart()? I could imagine this being necessary to satisfy code analysis tools since they might not be able to infer that throwExceptionIfTransactionDoesNotStart() guaranteed that getSession() would never return null; however, that's not relevant here.

Not that it is relevant here, but Psalm is able to handle this via the @psalm-assert annotation. See the first example in the docs. Annotating the throwIfNoSessionStarted like this will tell psalm that $this->session is an instance of Session:

/** @psalm-assert Session $this->session */
protected function throwIfNoSessionStarted(): void
[...]

@@ -277,7 +281,7 @@ protected function getDefaultQueryGrammar()
/**
* @inheritdoc
*/
protected function getDefaultSchemaGrammar()
protected function getDefaultSchemaGrammar(): Schema\Grammar
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the addition of return type hints on non-private methods a potential BC break for inheriting classes?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is correct. Protected members in non-final classes have to be treated like public members when considering BC breaks.

$result = $this->collection->DeleteMany($wheres);
$options = $this->inheritConnectionOptions();

$result = $this->collection->DeleteMany($wheres, $options);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize method names are case-insensitive but we should use the canonical case:

Suggested change
$result = $this->collection->DeleteMany($wheres, $options);
$result = $this->collection->deleteMany($wheres, $options);

@@ -905,7 +919,7 @@ public function where($column, $operator = null, $value = null, $boolean = 'and'
*
* @return array
*/
protected function compileWheres()
protected function compileWheres(): array
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to my earlier comment, this could be a BC break for inheriting classes.

'serverSelectionTryOnce' => false,
],
],

'dsn_mongodb' => [
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a PHP file, do you think it makes sense to define the options array once at the top of the file and reference it in the three times it's used herein?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants