Failed Conditions
Pull Request — master (#41)
by Bas
16:49
created

ManagesTransactions::transaction()   A

Complexity

Conditions 5
Paths 7

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 7.6055

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 22
c 1
b 0
f 0
dl 0
loc 43
ccs 9
cts 17
cp 0.5294
rs 9.2568
cc 5
nc 7
nop 3
crap 7.6055
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Concerns;
4
5
use ArangoDBClient\StreamingTransaction;
6
use ArangoDBClient\TransactionBase;
7
use Closure;
8
use Throwable;
9
10
trait ManagesTransactions
11
{
12
    protected $transactions = 0;
13
14
    protected $arangoTransaction;
15
16
    /**
17
     * Execute a Closure within a transaction.
18
     *
19
     * @param  \Closure  $callback
20
     * @param  int  $attempts
21
     * @param  array  $collections
22
     * @return mixed
23
     *
24
     * @throws Throwable
25
     */
26 1
    public function transaction(Closure $callback, $attempts = 1, $collections = [])
27
    {
28 1
        for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
29 1
            $this->beginTransaction($collections);
30
31
            // We'll simply execute the given callback within a try / catch block and if we
32
            // catch any exception we can rollback this transaction so that none of this
33
            // gets actually persisted to a database or stored in a permanent fashion.
34
            try {
35 1
                $callbackResult = $callback($this);
36
            } catch (Throwable $e) {
37
                // If we catch an exception we'll rollback this transaction and try again if we
38
                // are not out of attempts. If we are out of attempts we will just throw the
39
                // exception back out and let the developer handle an uncaught exceptions.
40
41
                $this->handleTransactionException(
0 ignored issues
show
Bug introduced by
It seems like handleTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
                $this->/** @scrutinizer ignore-call */ 
42
                       handleTransactionException(
Loading history...
42
                    $e,
43
                    $currentAttempt,
44
                    $attempts
45
                );
46
47
                continue;
48
            }
49
50
            try {
51 1
                if ($this->transactions == 1) {
52 1
                    $this->commitArangoTransaction();
53
                }
54
55 1
                $this->transactions = max(0, $this->transactions - 1);
56
            } catch (Throwable $e) {
57
                $this->handleCommitTransactionException(
0 ignored issues
show
Bug introduced by
It seems like handleCommitTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

57
                $this->/** @scrutinizer ignore-call */ 
58
                       handleCommitTransactionException(
Loading history...
58
                    $e,
59
                    $currentAttempt,
60
                    $attempts
61
                );
62
63
                continue;
64
            }
65
66 1
            $this->fireConnectionEvent('committed');
0 ignored issues
show
Bug introduced by
It seems like fireConnectionEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

66
            $this->/** @scrutinizer ignore-call */ 
67
                   fireConnectionEvent('committed');
Loading history...
67
68 1
            return $callbackResult;
69
        }
70
    }
71
72
    /**
73
     * Start a new database transaction.
74
     *
75
     * @param  array  $collections
76
     * @return void
77
     *
78
     * @throws Throwable
79
     */
80 5
    public function beginTransaction($collections = [])
81
    {
82 5
        $this->createTransaction($collections);
83
84 5
        $this->transactions++;
85
86 5
        $this->fireConnectionEvent('beganTransaction');
87 5
    }
88
89
    /**
90
     * Create a transaction within the database.
91
     *
92
     * @param  array  $collections
93
     * @return void
94
     *
95
     */
96 5
    protected function createTransaction($collections = [])
97
    {
98 5
        if ($this->transactions == 0) {
99 5
            $this->reconnectIfMissingConnection();
0 ignored issues
show
Bug introduced by
It seems like reconnectIfMissingConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

99
            $this->/** @scrutinizer ignore-call */ 
100
                   reconnectIfMissingConnection();
Loading history...
100
101
            try {
102 5
                $this->beginArangoTransaction($collections);
103
            } catch (Throwable $e) {
104
                $this->handleBeginTransactionException($e);
0 ignored issues
show
Bug introduced by
It seems like handleBeginTransactionException() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

104
                $this->/** @scrutinizer ignore-call */ 
105
                       handleBeginTransactionException($e);
Loading history...
105
            }
106
        }
107 5
    }
108
109 5
    protected function beginArangoTransaction($collections = [])
110
    {
111 5
        $transactionHandler = $this->getTransactionHandler();
0 ignored issues
show
Bug introduced by
It seems like getTransactionHandler() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
        /** @scrutinizer ignore-call */ 
112
        $transactionHandler = $this->getTransactionHandler();
Loading history...
112
113 5
        $this->arangoTransaction = new StreamingTransaction($this->getArangoConnection(), [
0 ignored issues
show
Bug introduced by
It seems like getArangoConnection() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

113
        $this->arangoTransaction = new StreamingTransaction($this->/** @scrutinizer ignore-call */ getArangoConnection(), [
Loading history...
114 5
            TransactionBase::ENTRY_COLLECTIONS => $collections
115
        ]);
116 5
        $this->arangoTransaction = $transactionHandler->create($this->arangoTransaction);
117 5
    }
118
119
    /**
120
     * Commit the active database transaction.
121
     *
122
     * @return void
123
     *
124
     * @throws Throwable
125
     */
126 3
    public function commit()
127
    {
128 3
        if ($this->transactions == 1) {
129 2
            $this->commitArangoTransaction();
130
        }
131
132 3
        $this->transactions = max(0, $this->transactions - 1);
133
134 3
        $this->fireConnectionEvent('committed');
135 3
    }
136
137
    /**
138
     *  Commit the transaction through the ArangoDB driver.
139
     */
140 3
    protected function commitArangoTransaction()
141
    {
142 3
        $transactionHandler = $this->getTransactionHandler();
143
144 3
        $transactionHandler->commit($this->arangoTransaction);
145
146 3
        $this->arangoTransaction = null;
147 3
    }
148
149
    /**
150
     * Perform a rollback within the database.
151
     *
152
     * @param  int  $toLevel
153
     * @return void
154
     *
155
     * @throws \Throwable
156
     */
157 1
    protected function performRollBack($toLevel)
158
    {
159 1
        if ($toLevel == 0) {
160 1
            $transactionHandler = $this->getTransactionHandler();
161
162 1
            $transactionHandler->abort($this->arangoTransaction);
163 1
            $this->arangoTransaction = null;
164
        }
165 1
    }
166
167 2
    public function getArangoTransaction()
168
    {
169 2
        return $this->arangoTransaction;
170
    }
171
}
172