Skip to content

Commit d9b27aa

Browse files
Merge 5.5 into 5.x (#3450)
2 parents cee14c4 + dee170a commit d9b27aa

File tree

2 files changed

+341
-3
lines changed

2 files changed

+341
-3
lines changed

src/Concerns/ManagesTransactions.php

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
use MongoDB\Client;
99
use MongoDB\Driver\Exception\RuntimeException;
1010
use MongoDB\Driver\Session;
11+
use MongoDB\Laravel\Connection;
1112
use Throwable;
1213

14+
use function max;
1315
use function MongoDB\with_transaction;
16+
use function property_exists;
1417

1518
/**
1619
* @internal
@@ -55,32 +58,93 @@ private function getSessionOrThrow(): Session
5558
*/
5659
public function beginTransaction(array $options = []): void
5760
{
61+
$this->runCallbacksBeforeTransaction();
62+
5863
$this->getSessionOrCreate()->startTransaction($options);
64+
65+
$this->handleInitialTransactionState();
66+
}
67+
68+
private function handleInitialTransactionState(): void
69+
{
5970
$this->transactions = 1;
71+
72+
$this->transactionsManager?->begin(
73+
$this->getName(),
74+
$this->transactions,
75+
);
76+
77+
$this->fireConnectionEvent('beganTransaction');
6078
}
6179

6280
/**
6381
* Commit transaction in this session.
6482
*/
6583
public function commit(): void
6684
{
85+
$this->fireConnectionEvent('committing');
6786
$this->getSessionOrThrow()->commitTransaction();
68-
$this->transactions = 0;
87+
88+
$this->handleCommitState();
89+
}
90+
91+
private function handleCommitState(): void
92+
{
93+
[$levelBeingCommitted, $this->transactions] = [
94+
$this->transactions,
95+
max(0, $this->transactions - 1),
96+
];
97+
98+
$this->transactionsManager?->commit(
99+
$this->getName(),
100+
$levelBeingCommitted,
101+
$this->transactions,
102+
);
103+
104+
$this->fireConnectionEvent('committed');
69105
}
70106

71107
/**
72108
* Abort transaction in this session.
73109
*/
74110
public function rollBack($toLevel = null): void
75111
{
76-
$this->getSessionOrThrow()->abortTransaction();
112+
$session = $this->getSessionOrThrow();
113+
if ($session->isInTransaction()) {
114+
$session->abortTransaction();
115+
}
116+
117+
$this->handleRollbackState();
118+
}
119+
120+
private function handleRollbackState(): void
121+
{
77122
$this->transactions = 0;
123+
124+
$this->transactionsManager?->rollback(
125+
$this->getName(),
126+
$this->transactions,
127+
);
128+
129+
$this->fireConnectionEvent('rollingBack');
130+
}
131+
132+
private function runCallbacksBeforeTransaction(): void
133+
{
134+
// ToDo: remove conditional once we stop supporting Laravel 10.x
135+
if (property_exists(Connection::class, 'beforeStartingTransaction')) {
136+
foreach ($this->beforeStartingTransaction as $beforeTransactionCallback) {
137+
$beforeTransactionCallback($this);
138+
}
139+
}
78140
}
79141

80142
/**
81143
* Static transaction function realize the with_transaction functionality provided by MongoDB.
82144
*
83-
* @param int $attempts
145+
* @param int $attempts
146+
*
147+
* @throws Throwable
84148
*/
85149
public function transaction(Closure $callback, $attempts = 1, array $options = []): mixed
86150
{
@@ -93,15 +157,20 @@ public function transaction(Closure $callback, $attempts = 1, array $options = [
93157

94158
if ($attemptsLeft < 0) {
95159
$session->abortTransaction();
160+
$this->handleRollbackState();
96161

97162
return;
98163
}
99164

165+
$this->runCallbacksBeforeTransaction();
166+
$this->handleInitialTransactionState();
167+
100168
// Catch, store, and re-throw any exception thrown during execution
101169
// of the callable. The last exception is re-thrown if the transaction
102170
// was aborted because the number of callback attempts has been exceeded.
103171
try {
104172
$callbackResult = $callback($this);
173+
$this->fireConnectionEvent('committing');
105174
} catch (Throwable $throwable) {
106175
throw $throwable;
107176
}
@@ -110,9 +179,12 @@ public function transaction(Closure $callback, $attempts = 1, array $options = [
110179
with_transaction($this->getSessionOrCreate(), $callbackFunction, $options);
111180

112181
if ($attemptsLeft < 0 && $throwable) {
182+
$this->handleRollbackState();
113183
throw $throwable;
114184
}
115185

186+
$this->handleCommitState();
187+
116188
return $callbackResult;
117189
}
118190
}

0 commit comments

Comments
 (0)