Completed
Push — devops/catch-breaking-changes-... ( 88c9a6 )
by Bas
28s queued 18s
created

ManagesTransactions::beginTransaction()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 3
c 1
b 0
f 0
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace LaravelFreelancerNL\Aranguent\Concerns;
4
5
use Closure;
6
use Throwable;
7
8
trait ManagesTransactions
9
{
10
    /**
11
     * Execute a Closure within a transaction.
12
     *
13
     * @param  Closure  $callback
14
     * @param  int  $attempts
15
     * @param  array  $collections
16
     * @return mixed
17
     *
18
     * @throws Throwable
19
     */
20 1
    public function transaction(Closure $callback, $attempts = 1, $collections = [])
21
    {
22 1
        for ($currentAttempt = 1; $currentAttempt <= $attempts; $currentAttempt++) {
23 1
            $this->beginTransaction($collections);
24
25
            // We'll simply execute the given callback within a try / catch block and if we
26
            // catch any exception we can rollback this transaction so that none of this
27
            // gets actually persisted to a database or stored in a permanent fashion.
28
            try {
29 1
                $callbackResult = $callback($this);
30
            } catch (Throwable $e) {
31
                // If we catch an exception we'll rollback this transaction and try again if we
32
                // are not out of attempts. If we are out of attempts we will just throw the
33
                // exception back out and let the developer handle an uncaught exceptions.
34
35
                $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

35
                $this->/** @scrutinizer ignore-call */ 
36
                       handleTransactionException(
Loading history...
36
                    $e,
37
                    $currentAttempt,
38
                    $attempts
39
                );
40
41
                continue;
42
            }
43
44
            try {
45 1
                if ($this->transactions == 1) {
46 1
                    $this->commit();
47
                }
48
49 1
                $this->transactions = max(0, $this->transactions - 1);
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
50
            } catch (Throwable $e) {
51
                $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

51
                $this->/** @scrutinizer ignore-call */ 
52
                       handleCommitTransactionException(
Loading history...
52
                    $e,
53
                    $currentAttempt,
54
                    $attempts
55
                );
56
57
                continue;
58
            }
59
60 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

60
            $this->/** @scrutinizer ignore-call */ 
61
                   fireConnectionEvent('committed');
Loading history...
61
62 1
            return $callbackResult;
63
        }
64
    }
65
66
    /**
67
     * Start a new database transaction.
68
     *
69
     * @param array<string, array<string>> $collections
70
     * @throws Throwable
71
     */
72 159
    public function beginTransaction(array $collections = []): void
73
    {
74 159
        $this->createTransaction($collections);
75
76 159
        $this->transactions++;
77
78 159
        $this->fireConnectionEvent('beganTransaction');
79
    }
80
81
    /**
82
     * Create a transaction within the database.
83
     *
84
     * @param array<string, array<string>> $collections
85
     * @throws Throwable
86
     */
87 159
    protected function createTransaction(array $collections = []): void
88
    {
89 159
        if ($this->transactions == 0) {
90 159
            $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

90
            $this->/** @scrutinizer ignore-call */ 
91
                   reconnectIfMissingConnection();
Loading history...
91
92
            try {
93 159
                $this->arangoClient->begin($collections);
94
            } catch (Throwable $e) {
95
                $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

95
                $this->/** @scrutinizer ignore-call */ 
96
                       handleBeginTransactionException($e);
Loading history...
96
            }
97
        }
98
    }
99
100
    /**
101
     * Commit the active database transaction.
102
     *
103
     * @return void
104
     *
105
     * @throws Throwable
106
     */
107 3
    public function commit()
108
    {
109 3
        if ($this->transactions == 1) {
110 3
            $this->arangoClient->commit();
111
        }
112
113 3
        $this->transactions = max(0, $this->transactions - 1);
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
114
115 3
        $this->fireConnectionEvent('committed');
116
    }
117
118
    /**
119
     * Rollback the active database transaction.
120
     *
121
     * @param  int|null  $toLevel
122
     * @return void
123
     *
124
     * @throws \Throwable
125
     */
126 156
    public function rollBack($toLevel = null)
127
    {
128
        // We allow developers to rollback to a certain transaction level. We will verify
129
        // that this given transaction level is valid before attempting to rollback to
130
        // that level. If it's not we will just return out and not attempt anything.
131 156
        $toLevel = is_null($toLevel)
132 156
            ? $this->transactions - 1
133
            : $toLevel;
134
135 156
        if ($toLevel < 0 || $toLevel >= $this->transactions) {
136
            return;
137
        }
138
139
        // Next, we will actually perform this rollback within this database and fire the
140
        // rollback event. We will also set the current transaction level to the given
141
        // level that was passed into this method so it will be right from here out.
142
        try {
143 156
            $this->performRollBack($toLevel);
144
        } catch (Throwable $e) {
145
            $this->handleRollBackException($e);
0 ignored issues
show
Bug introduced by
It seems like handleRollBackException() 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

145
            $this->/** @scrutinizer ignore-call */ 
146
                   handleRollBackException($e);
Loading history...
146
        }
147
148 156
        $this->transactions = $toLevel;
0 ignored issues
show
Bug Best Practice introduced by
The property transactions does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
149
150 156
        $this->fireConnectionEvent('rollingBack');
151
    }
152
153
    /**
154
     * Perform a rollback within the database.
155
     *
156
     * @param  int  $toLevel
157
     * @return void
158
     *
159
     * @throws Throwable
160
     */
161 156
    protected function performRollBack($toLevel)
162
    {
163 156
        if ($toLevel == 0) {
164 156
            $this->arangoClient->abort();
165
        }
166
    }
167
}
168