Skip to content

Commit d070f27

Browse files
committed
updated to latest
1 parent cb58998 commit d070f27

File tree

10 files changed

+192
-26
lines changed

10 files changed

+192
-26
lines changed

.travis.yml

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
11
language: php
22

3-
php:
4-
- 5.3
5-
- 5.4
6-
- 5.5
7-
- 5.6
8-
- 7
9-
- hhvm
3+
matrix:
4+
include:
5+
- php: '5.4'
6+
env: PHP_VERSION_USED="5.4"
7+
- php: '5.5'
8+
env: PHP_VERSION_USED="5.5"
9+
- php: '5.6'
10+
env: PHP_VERSION_USED="5.6"
11+
- php: '7.0'
12+
env: PHP_VERSION_USED="7.0"
13+
- php: hhvm
14+
env: PHP_VERSION_USED="hhvm"
1015

1116
before_script:
17+
- wget https://phar.phpunit.de/phpunit.phar
18+
- chmod a+x phpunit.phar
1219
- chmod 777 ./tests/travis/setup_arangodb.sh
1320
- ./tests/travis/setup_arangodb.sh
1421

15-
script: phpunit --configuration ./tests/phpunit.xml
22+
script:
23+
- if [[ "${PHP_VERSION_USED}" == "5.4" ]]; then phpunit --configuration ./tests/phpunit.xml; fi
24+
- if [[ "${PHP_VERSION_USED}" == "5.5" ]]; then phpunit --configuration ./tests/phpunit.xml; fi
25+
- if [[ "${PHP_VERSION_USED}" == "5.6" ]]; then phpunit --configuration ./tests/phpunit.xml; fi
26+
- if [[ "${PHP_VERSION_USED}" == "7.0" ]]; then (cd tests && ../phpunit.phar . --colors=auto --verbose --bootstrap=bootstrap.php); fi
27+
- if [[ "${PHP_VERSION_USED}" == "hhvm" ]]; then phpunit --configuration ./tests/phpunit.xml; fi

README.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,6 @@
3939

4040
<br>
4141

42-
Please take a look [here](https://github.com/arangodb/arangodb-php/wiki/Important-versioning-information-on-ArangoDB-PHP#arangodb-php-client-to-arangodb-server-interoperability-matrix) for the **ArangoDB-PHP Client** / **ArangoDB Server** interoperability matrix.
43-
44-
**[Important versioning information on ArangoDB-PHP](https://github.com/arangodb/arangodb-php/wiki/Important-versioning-information-on-ArangoDB-PHP)**
45-
46-
<br>
4742
<a name="description"></a>
4843
# Description
4944

@@ -57,7 +52,7 @@ There is an example for this kind of statements in the file examples/select.php.
5752
To use the PHP client, you must include the file autoloader.php from the main directory.
5853
The autoloader will care about loading additionally required classes on the fly. The autoloader can be nested with other autoloaders.
5954

60-
The ArangoDB PHP client is an API that allows you to send and retrieve documents from ArangoDB from out of your PHP application. The client library itself is written in PHP and has no further dependencies but just plain PHP 5.3 (or higher).
55+
The ArangoDB PHP client is an API that allows you to send and retrieve documents from ArangoDB from out of your PHP application. The client library itself is written in PHP and has no further dependencies but just plain PHP 5.4 (or higher).
6156

6257
The client library provides document and collection classes you can use to work with documents and collections in an OO fashion. When exchanging document data with the server, the library internally will use the [HTTP REST interface of ArangoDB](https://docs.arangodb.com/HttpApi/index.html). The library user does not have to care about this fact as all the details of the REST interface are abstracted by the client library.
6358

@@ -68,9 +63,9 @@ The client library provides document and collection classes you can use to work
6863
<a name="requirements"></a>
6964
# Requirements
7065

71-
* ArangoDB database server version 1.4 or higher. Detailed info [here](https://github.com/arangodb/arangodb-php/wiki/Important-versioning-information-on-ArangoDB-PHP#arangodb-php-client-to-arangodb-server-interoperability-matrix)
66+
* ArangoDB database server version 2.5 or higher. Detailed info [here](https://github.com/arangodb/arangodb-php/wiki/Important-versioning-information-on-ArangoDB-PHP#arangodb-php-client-to-arangodb-server-interoperability-matrix)
7267

73-
* PHP version 5.3 or higher (Travis-tested with PHP 5.3, 5.4, 5.5, 5.6, 7 and hhvm)
68+
* PHP version 5.4 or higher (Travis-tested with PHP 5.4, 5.5, 5.6, 7 and hhvm)
7469

7570
<br>
7671

@@ -79,7 +74,7 @@ The client library provides document and collection classes you can use to work
7974
<a name="installing"></a>
8075
## Installing the PHP client
8176

82-
To get started you need PHP 5.3 or higher plus an ArangoDB server running on any host that you can access.
77+
To get started you need PHP 5.4 or higher plus an ArangoDB server running on any host that you can access.
8378

8479
There are two alternative ways to get the ArangoDB PHP client:
8580

lib/triagens/ArangoDb/Connection.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,10 @@ public function parseResponse(HttpResponse $response)
473473
private function executeRequest($method, $url, $data, array $customHeaders = array())
474474
{
475475
assert($this->_httpHeader !== '');
476+
$wasAsync = false;
477+
if (is_array($customHeaders) && isset($customHeaders[HttpHelper::ASYNC_HEADER])) {
478+
$wasAsync = true;
479+
}
476480

477481
// check if a custom queue should be used
478482
if (! isset($customHeaders[ConnectionOptions::OPTION_CUSTOM_QUEUE]) &&
@@ -566,7 +570,7 @@ private function executeRequest($method, $url, $data, array $customHeaders = arr
566570
fclose($handle);
567571
}
568572

569-
$response = new HttpResponse($result, $url, $method);
573+
$response = new HttpResponse($result, $url, $method, $wasAsync);
570574

571575
if ($traceFunc) {
572576
// call tracer func

lib/triagens/ArangoDb/HttpHelper.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ class HttpHelper
7979
* HTTP Header for specifying a custom queue
8080
*/
8181
const QUEUE_HEADER = 'X-Arango-Queue';
82+
83+
/**
84+
* HTTP Header for making an operation asynchronous
85+
*/
86+
const ASYNC_HEADER = 'X-Arango-Async';
8287

8388
/**
8489
* Validate an HTTP request method name

lib/triagens/ArangoDb/HttpResponse.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ class HttpResponse
5555
*/
5656
private $_httpCode;
5757

58+
/**
59+
* Whether or not the response is for an async request without a response body
60+
*
61+
* @var bool
62+
*/
63+
private $_wasAsync = false;
64+
5865
/**
5966
* HTTP location header
6067
*/
@@ -71,13 +78,15 @@ class HttpResponse
7178
*
7279
* @throws ClientException
7380
*/
74-
public function __construct($responseString, $originUrl = null, $originMethod = null)
81+
public function __construct($responseString, $originUrl = null, $originMethod = null, $wasAsync = false)
7582
{
83+
$this->_wasAsync = $wasAsync;
84+
7685
list($this->_header, $this->_body) = HttpHelper::parseHttpMessage($responseString, $originUrl, $originMethod);
7786
list($this->_httpCode, $this->_result, $this->_headers) = HttpHelper::parseHeaders($this->_header);
78-
87+
7988
if ((! isset($this->_body) or $this->_body === null) and
80-
($this->_httpCode !== 204 and $this->_httpCode !== 304)) {
89+
($this->_httpCode !== 204 and $this->_httpCode !== 304 and !$wasAsync)) {
8190
// got no response body!
8291
if ($originUrl !== null && $originMethod !== null) {
8392
if ($responseString === '') {
@@ -174,6 +183,10 @@ public function getJson()
174183
$json = json_decode($body, true);
175184

176185
if (!is_array($json)) {
186+
if ($this->_wasAsync) {
187+
return array();
188+
}
189+
177190
// should be an array, fail otherwise
178191
throw new ClientException('Got a malformed result from the server');
179192
}

lib/triagens/ArangoDb/Statement.php

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,13 @@ class Statement
105105
*/
106106
private $_sanitize = false;
107107

108+
/**
109+
* Number of retries in case a deadlock occurs
110+
*
111+
* @var bool
112+
*/
113+
private $_retries = 0;
114+
108115
/**
109116
* Whether or not the query cache should be consulted
110117
*
@@ -141,6 +148,11 @@ class Statement
141148
* Batch size index
142149
*/
143150
const ENTRY_BATCHSIZE = 'batchSize';
151+
152+
/**
153+
* Retries index
154+
*/
155+
const ENTRY_RETRIES = 'retries';
144156

145157
/**
146158
* Bind variables index
@@ -151,7 +163,7 @@ class Statement
151163
* Full count option index
152164
*/
153165
const FULL_COUNT = 'fullCount';
154-
166+
155167
/**
156168
* Initialise the statement
157169
*
@@ -200,6 +212,10 @@ public function __construct(Connection $connection, array $data)
200212
if (isset($data[Cursor::ENTRY_SANITIZE])) {
201213
$this->_sanitize = (bool) $data[Cursor::ENTRY_SANITIZE];
202214
}
215+
216+
if (isset($data[self::ENTRY_RETRIES])) {
217+
$this->_retries = (int) $data[self::ENTRY_RETRIES];
218+
}
203219

204220
if (isset($data[Cursor::ENTRY_FLAT])) {
205221
$this->_flat = (bool) $data[Cursor::ENTRY_FLAT];
@@ -240,9 +256,25 @@ public function execute()
240256
}
241257

242258
$data = $this->buildData();
243-
$response = $this->_connection->post(Urls::URL_CURSOR, $this->getConnection()->json_encode_wrapper($data), $this->buildHeaders());
259+
260+
$tries = 0;
261+
while (true) {
262+
try {
263+
$response = $this->_connection->post(Urls::URL_CURSOR, $this->getConnection()->json_encode_wrapper($data), $this->buildHeaders());
244264

245-
return new Cursor($this->_connection, $response->getJson(), $this->getCursorOptions());
265+
return new Cursor($this->_connection, $response->getJson(), $this->getCursorOptions());
266+
}
267+
catch (ServerException $e) {
268+
if ($tries++ >= $this->_retries) {
269+
throw $e;
270+
}
271+
if ($e->getServerCode() !== 29) {
272+
// 29 is "deadlock detected"
273+
throw $e;
274+
}
275+
// try again
276+
}
277+
}
246278
}
247279

248280

tests/CollectionBasicTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ public function setUp()
2424
{
2525
$this->connection = getConnection();
2626
$this->collectionHandler = new CollectionHandler($this->connection);
27+
try {
28+
$this->collectionHandler->drop('ArangoDB_PHP_TestSuite_IndexTestCollection');
29+
} catch (Exception $e) {
30+
//Silence the exception
31+
}
2732
$this->collectionHandler->create('ArangoDB_PHP_TestSuite_IndexTestCollection');
2833

2934
$adminHandler = new AdminHandler($this->connection);

tests/StatementTest.php

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function setUp()
3939
$this->collectionHandler->add($this->collection);
4040
}
4141

42-
42+
4343
/**
4444
* This is just a test to really test connectivity with the server before moving on to further tests.
4545
*/
@@ -72,6 +72,26 @@ public function testExecuteStatement()
7272
}
7373

7474

75+
/**
76+
* Test deadlock handling
77+
*/
78+
public function testDeadlock()
79+
{
80+
$connection = $this->connection;
81+
$statement = new Statement($connection, array(
82+
"query" => 'RETURN TEST_INTERNAL("DEADLOCK", null)',
83+
"_sanitize" => true
84+
));
85+
try {
86+
$cursor = $statement->execute();
87+
}
88+
catch (ServerException $e) {
89+
}
90+
91+
$this->assertEquals(500, $e->getCode());
92+
$this->assertEquals(29, $e->getServerCode());
93+
}
94+
7595
/**
7696
* Test warnings returned by statement
7797
*/

tests/TransactionTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,86 @@ public function setUp()
5151
$this->collectionHandler->add($this->collection2);
5252
}
5353

54+
/**
55+
* Test if a deadlock occurs and error 29 is thrown
56+
*/
57+
public function testDeadlockHandling()
58+
{
59+
$w1 = array($this->collection1->getName());
60+
$action1 = '
61+
try {
62+
require("internal").db._executeTransaction({ collections: { write: [ "' . $this->collection2->getName() . '" ] }, action: function () {
63+
require("internal").wait(7);
64+
var db = require("internal").db;
65+
db.' . $this->collection1->getName() . '.any();
66+
}});
67+
return { message: "ok" };
68+
} catch (err) {
69+
return { message: err.errorNum };
70+
}
71+
';
72+
73+
$result1 = $this->connection->post("/_admin/execute?returnAsJSON=true", $action1, array("X-Arango-Async" => "store"));
74+
$id1 = $result1->getHeader("x-arango-async-id");
75+
76+
$action2 = '
77+
try {
78+
require("internal").db._executeTransaction({ collections: { write: [ "' . $this->collection1->getName() . '" ] }, action: function () {
79+
require("internal").wait(7);
80+
var db = require("internal").db;
81+
db.' . $this->collection2->getName() . '.any();
82+
}});
83+
return { message: "ok" };
84+
} catch (err) {
85+
return { message: err.errorNum };
86+
}
87+
';
88+
89+
$result2 = $this->connection->post("/_admin/execute?returnAsJSON=true", $action2, array("X-Arango-Async" => "store"));
90+
$id2 = $result2->getHeader("x-arango-async-id");
91+
92+
$tries = 0;
93+
$got1 = false;
94+
$got2 = false;
95+
$result1 = null;
96+
$result2 = null;
97+
while ($tries++ < 20) {
98+
if (! $got1) {
99+
try {
100+
$result1 = $this->connection->put("/_api/job/" . $id1, "");
101+
if ($result1->getHeader("x-arango-async-id") !== null) {
102+
$got1 = true;
103+
}
104+
}
105+
catch (Exception $e) {
106+
}
107+
}
108+
if (! $got2) {
109+
try {
110+
$result2 = $this->connection->put("/_api/job/" . $id2, "");
111+
if ($result2->getHeader("x-arango-async-id") !== null) {
112+
$got2 = true;
113+
}
114+
}
115+
catch (Exception $e) {
116+
}
117+
}
118+
119+
if ($got1 && $got2) {
120+
break;
121+
}
122+
123+
sleep(1);
124+
}
125+
126+
127+
$this->assertTrue($got1);
128+
$this->assertTrue($got2);
129+
130+
$r1 = json_decode($result1->getBody());
131+
$r2 = json_decode($result2->getBody());
132+
$this->assertTrue($r1->message === 29 || $r2->message === 29);
133+
}
54134

55135
/**
56136
* Test if we can create and execute a transaction by using array initialization at construction time

tests/travis/setup_arangodb.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
44
cd $DIR
55

6-
VERSION="devel-nightly"
6+
VERSION="2.8-nightly"
77
NAME="ArangoDB-$VERSION"
88

99
if [ ! -d "$DIR/$NAME" ]; then

0 commit comments

Comments
 (0)