forked from mongodb/laravel-mongodb
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathManagesTransactions.php
115 lines (91 loc) · 2.92 KB
/
ManagesTransactions.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<?php
declare(strict_types=1);
namespace MongoDB\Laravel\Concerns;
use Closure;
use MongoDB\Client;
use MongoDB\Driver\Exception\RuntimeException;
use MongoDB\Driver\Session;
use Throwable;
use function MongoDB\with_transaction;
/** @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;
}
/**
* 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;
}
}