@@ -78,41 +78,57 @@ public function rollBack($toLevel = null): void
78
78
}
79
79
80
80
/**
81
- * Static transaction function realize the with_transaction functionality provided by MongoDB.
82
- *
83
- * @param int $attempts
81
+ * @param Closure $callback
82
+ * @param $attempts
83
+ * @param Closure|null $onFailure
84
+ * @return mixed
85
+ * @throws Throwable
84
86
*/
85
- public function transaction (Closure $ callback , $ attempts = 1 , array $ options = [] ): mixed
87
+ public function transaction (Closure $ callback , $ attempts = 1 , ? Closure $ onFailure = null ): mixed
86
88
{
87
- $ attemptsLeft = $ attempts ;
88
- $ callbackResult = null ;
89
- $ throwable = null ;
90
89
91
- $ callbackFunction = function (Session $ session ) use ($ callback , &$ attemptsLeft , &$ callbackResult , &$ throwable ) {
92
- $ attemptsLeft --;
90
+ if ($ attempts <= 0 ) {
91
+ throw new \InvalidArgumentException ('Attempts must be at least 1 ' );
92
+ }
93
93
94
- if ( $ attemptsLeft < 0 ) {
95
- $ session -> abortTransaction () ;
94
+ $ attemptsLeft = $ attempts ;
95
+ $ lastException = null ;
96
96
97
- return ;
98
- }
97
+ while ( $ attemptsLeft --) {
98
+ $ this -> session = $ this -> getMongoClient ()-> startSession ();
99
99
100
- // Catch, store, and re-throw any exception thrown during execution
101
- // of the callable. The last exception is re-thrown if the transaction
102
- // was aborted because the number of callback attempts has been exceeded.
103
100
try {
104
- $ callbackResult = $ callback ($ this );
105
- } catch (Throwable $ throwable ) {
106
- throw $ throwable ;
101
+ $ this ->session ->startTransaction ();
102
+ $ result = $ callback ();
103
+ $ this ->session ->commitTransaction ();
104
+
105
+ return $ result ;
106
+ } catch (\Throwable $ e ) {
107
+ if ($ this ->session ->isInTransaction ()) {
108
+ $ this ->session ->abortTransaction ();
109
+ }
110
+
111
+ $ lastException = $ e ;
112
+
113
+ if ($ e instanceof RuntimeException && $ attemptsLeft > 0 ) {
114
+ continue ;
115
+ }
116
+
117
+ if ($ onFailure ) {
118
+ return $ onFailure ($ e );
119
+ }
120
+
121
+ throw $ e ;
122
+ } finally {
123
+ $ this ->session ->endSession ();
124
+ $ this ->session = null ;
107
125
}
108
- };
109
-
110
- with_transaction ($ this ->getSessionOrCreate (), $ callbackFunction , $ options );
126
+ }
111
127
112
- if ($ attemptsLeft < 0 && $ throwable ) {
113
- throw $ throwable ;
128
+ if ($ onFailure ) {
129
+ return $ onFailure ( $ lastException ) ;
114
130
}
115
131
116
- return $ callbackResult ;
132
+ throw $ lastException ;
117
133
}
118
134
}
0 commit comments