Failed Conditions
Push — next ( 580d6f...1a59b4 )
by Bas
02:36
created

TransactionManager::commit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 10
ccs 6
cts 6
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace ArangoClient\Transactions;
6
7
use ArangoClient\ArangoClient;
8
use ArangoClient\Exceptions\ArangoException;
9
use ArangoClient\Manager;
10
11
/**
12
 * Class TransactionManager
13
 * Begins transactions and manages those transactions.
14
 *
15
 * @see https://www.arangodb.com/docs/stable/http/transaction-stream-transaction.html
16
 *
17
 * @package ArangoClient\Transactions
18
 */
19
class TransactionManager extends Manager
20
{
21
    /**
22
     * @var ArangoClient
23
     */
24
    protected ArangoClient $arangoClient;
25
26
    /**
27
     * @var array<string>
28
     */
29
    protected array $transactions = [];
30
31
    /**
32
     * Documents constructor.
33
     * @param  ArangoClient  $arangoClient
34
     */
35 22
    public function __construct(ArangoClient $arangoClient)
36
    {
37 22
        $this->arangoClient = $arangoClient;
38
39 22
        register_shutdown_function(array($this, 'abortRunningTransactions'));
40 22
    }
41
42
    /**
43
     * @return string[]
44
     */
45 6
    public function getTransactions(): array
46
    {
47 6
        return $this->transactions;
48
    }
49
50
    /**
51
     * @param  string|null  $id
52
     * @return string
53
     * @throws ArangoException
54
     */
55 20
    public function getTransaction(string $id = null): string
56
    {
57 20
        $this->validateId($id);
58
59 10
        if ($id === null) {
60 8
            return (string) end($this->transactions);
61
        }
62
63 2
        return $this->transactions[$id];
64
    }
65
66
    /**
67
     * Begin a transactions and return its id.
68
     * @param  array{read?: string[], write?: string[], exclusive?: string[]}  $collections
69
     * @param  array<mixed>  $options
70
     * @return string
71
     * @throws ArangoException
72
     */
73 11
    public function begin(array $collections = [], array $options = []): string
74
    {
75 11
        $options['collections'] = $this->prepareCollections($collections);
76
77 11
        $config = [];
78 11
        $config['body'] = $this->arangoClient->jsonEncode($options);
79 11
        $results = $this->arangoClient->request('post', '/_api/transaction/begin', $config);
80
81 11
        $id = (string) ((array)$results['result'])['id'];
82 11
        $this->transactions[$id] = $id;
83
84 11
        return $id;
85
    }
86
87
    /**
88
     * @param  string|null  $id
89
     * @return bool
90
     * @throws ArangoException
91
     */
92 2
    public function commit(string $id = null): bool
93
    {
94 2
        $id = $this->getTransaction($id);
95
96 2
        $uri =  '/_api/transaction/' . $id;
97
98 2
        $this->arangoClient->request('put', $uri);
99 2
        unset($this->transactions[$id]);
100
101 2
        return true;
102
    }
103
104
    /**
105
     * @param  string|null  $id
106
     * @return true
107
     * @throws ArangoException
108
     */
109 9
    public function abort(string $id = null): bool
110
    {
111 9
        $id = $this->getTransaction($id);
112
113 7
        $uri =  '/_api/transaction/' . $id;
114
115 7
        $this->arangoClient->request('delete', $uri);
116 7
        unset($this->transactions[$id]);
117
118 7
        return true;
119
    }
120
121
    /**
122
     * @param  string|null  $id
123
     * @return bool
124
     * @throws ArangoException
125
     */
126 20
    protected function validateId(string $id = null): bool
127
    {
128
        if (
129 20
            empty($this->transactions)
130
            || (
131 10
                $id !== null
132 20
                && ! isset($this->transactions[$id])
133
            )
134
        ) {
135 12
            throw new ArangoException('Transaction not found.', 404);
136
        }
137
138 10
        return true;
139
    }
140
141
    /**
142
     * @param  array{read?: string[], write?: string[], exclusive?: string[]}  $collections
143
     * @return array<string, array<string>>
144
     */
145 11
    protected function prepareCollections(array $collections): array
146
    {
147
        $collectionTemplate = [
148 11
            'read' => [],
149
            'write' => [],
150
            'exclusive' => []
151
        ];
152
153 11
        return array_intersect_key(array_merge($collectionTemplate, $collections), $collectionTemplate);
154
    }
155
156
    /**
157
     * Cleanup any open transactions on shutdown as registered in the constructor.
158
     *
159
     * @see TransactionManager::__construct
160
     *
161
     * @throws ArangoException
162
     */
163 2
    public function abortRunningTransactions(): void
164
    {
165 2
        foreach ($this->transactions as $id) {
166
            try {
167 2
                $this->abort($id);
168 2
            } finally {
169
                // Ignore any errors, this is just for clean up.
170
            }
171
        }
172 2
    }
173
}
174