-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Transaction support #2465
Merged
Merged
Transaction support #2465
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
898f4e2
Add support for transactions
alcaeus e68124c
Start single-member replica set in CI
alcaeus eea9943
Add connection options for faster failures in tests
alcaeus 0a2e605
Apply readme code review suggestions
alcaeus 203160e
Simplify replica set creation in CI
alcaeus 8fc6915
Apply feedback from code review
alcaeus 2c549c8
Update naming of database env variable in tests
alcaeus a6aa3cc
Use default argument for server selection (which defaults to primary)
alcaeus 2a82a54
Revert "Simplify replica set creation in CI"
alcaeus bb58fcb
Pass connection instance to transactional closure
alcaeus df3a53a
Correctly re-throw exception when callback attempts have been exceeded.
alcaeus f2510b1
Limit transaction lifetime to 5 seconds
alcaeus 8afe105
Add build step to print MongoDB server status
alcaeus 7a644bc
Update src/Concerns/ManagesTransactions.php
alcaeus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<?php | ||
|
||
namespace Jenssegers\Mongodb\Concerns; | ||
|
||
use Closure; | ||
use MongoDB\Client; | ||
use MongoDB\Driver\Exception\RuntimeException; | ||
use MongoDB\Driver\Session; | ||
use function MongoDB\with_transaction; | ||
use Throwable; | ||
|
||
/** | ||
* @see https://docs.mongodb.com/manual/core/transactions/ | ||
*/ | ||
trait ManagesTransactions | ||
{ | ||
protected ?Session $session = null; | ||
|
||
protected $transactions = 0; | ||
|
||
/** | ||
* @return Client | ||
*/ | ||
abstract public function getMongoClient(); | ||
|
||
public function getSession(): ?Session | ||
{ | ||
return $this->session; | ||
} | ||
|
||
private function getSessionOrCreate(): Session | ||
{ | ||
if ($this->session === null) { | ||
$this->session = $this->getMongoClient()->startSession(); | ||
} | ||
|
||
return $this->session; | ||
} | ||
|
||
private function getSessionOrThrow(): Session | ||
{ | ||
$session = $this->getSession(); | ||
|
||
if ($session === null) { | ||
throw new RuntimeException('There is no active session.'); | ||
} | ||
|
||
return $session; | ||
} | ||
|
||
/** | ||
* Starts a transaction on the active session. An active session will be created if none exists. | ||
*/ | ||
public function beginTransaction(array $options = []): void | ||
{ | ||
$this->getSessionOrCreate()->startTransaction($options); | ||
$this->transactions = 1; | ||
alcaeus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
/** | ||
* Commit transaction in this session. | ||
*/ | ||
public function commit(): void | ||
{ | ||
$this->getSessionOrThrow()->commitTransaction(); | ||
$this->transactions = 0; | ||
} | ||
|
||
/** | ||
* Abort transaction in this session. | ||
*/ | ||
public function rollBack($toLevel = null): void | ||
{ | ||
$this->getSessionOrThrow()->abortTransaction(); | ||
$this->transactions = 0; | ||
} | ||
|
||
/** | ||
* Static transaction function realize the with_transaction functionality provided by MongoDB. | ||
* | ||
* @param int $attempts | ||
*/ | ||
public function transaction(Closure $callback, $attempts = 1, array $options = []): mixed | ||
{ | ||
$attemptsLeft = $attempts; | ||
$callbackResult = null; | ||
$throwable = null; | ||
|
||
$callbackFunction = function (Session $session) use ($callback, &$attemptsLeft, &$callbackResult, &$throwable) { | ||
$attemptsLeft--; | ||
|
||
if ($attemptsLeft < 0) { | ||
$session->abortTransaction(); | ||
|
||
return; | ||
} | ||
|
||
// Catch, store, and re-throw any exception thrown during execution | ||
// of the callable. The last exception is re-thrown if the transaction | ||
// was aborted because the number of callback attempts has been exceeded. | ||
try { | ||
$callbackResult = $callback($this); | ||
} catch (Throwable $throwable) { | ||
throw $throwable; | ||
} | ||
}; | ||
|
||
with_transaction($this->getSessionOrCreate(), $callbackFunction, $options); | ||
|
||
if ($attemptsLeft < 0 && $throwable) { | ||
throw $throwable; | ||
} | ||
|
||
return $callbackResult; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Just looking at the CI output. I'm not certain, but if this line is the only thing responsible for printing the exact MongoDB server version then perhaps we should use
buildInfo
here instead ofping
.serverStatus
was definitely TMI but it'd be helpful to have some details about the server (vs. just trusting the shell verison).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.
Done - I added an additional build step for this to avoid people having to look through the entire setup output for this.