Skip to content

Commit 8335f8b

Browse files
stefanak-michaltransistive
authored andcommitted
Added server state check for bolt.
1 parent dc75b65 commit 8335f8b

File tree

4 files changed

+64
-79
lines changed

4 files changed

+64
-79
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"psr/http-factory": "^1.0",
2929
"psr/http-client": "^1.0",
3030
"php-http/message": "^1.0",
31-
"stefanak-michal/bolt": "^7.0",
31+
"stefanak-michal/bolt": "^7.0.1",
3232
"symfony/polyfill-php80": "^1.2",
3333
"psr/simple-cache": ">=2.0",
3434
"ext-json": "*",

src/Bolt/BoltConnection.php

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use Laudis\Neo4j\Contracts\FormatterInterface;
2727
use Laudis\Neo4j\Databags\BookmarkHolder;
2828
use Laudis\Neo4j\Databags\DatabaseInfo;
29+
use Laudis\Neo4j\Databags\Neo4jError;
2930
use Laudis\Neo4j\Enum\AccessMode;
3031
use Laudis\Neo4j\Enum\ConnectionProtocol;
3132
use Laudis\Neo4j\Exception\Neo4jException;
@@ -166,11 +167,10 @@ public function consumeResults(): void
166167
*/
167168
public function reset(): void
168169
{
169-
$response = $this->protocol()->reset()
170+
$response = $this->protocol()
171+
->reset()
170172
->getResponse();
171-
172173
$this->assertNoFailure($response);
173-
174174
$this->subscribedResults = [];
175175
}
176176

@@ -182,12 +182,15 @@ public function reset(): void
182182
public function begin(?string $database, ?float $timeout, BookmarkHolder $holder): void
183183
{
184184
$this->consumeResults();
185-
$extra = $this->buildRunExtra($database, $timeout, $holder, AccessMode::WRITE());
186185

186+
if ($this->protocol()->serverState !== ServerState::READY) {
187+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'BEGIN\' cannot be handled by a session which isn\'t in the READY state.')]);
188+
}
189+
190+
$extra = $this->buildRunExtra($database, $timeout, $holder, AccessMode::WRITE());
187191
$response = $this->protocol()
188192
->begin($extra)
189193
->getResponse();
190-
191194
$this->assertNoFailure($response);
192195
}
193196

@@ -198,12 +201,14 @@ public function begin(?string $database, ?float $timeout, BookmarkHolder $holder
198201
*/
199202
public function discard(?int $qid): void
200203
{
201-
$extra = $this->buildResultExtra(null, $qid);
202-
$bolt = $this->protocol();
204+
if (!in_array($this->protocol()->serverState, [ServerState::STREAMING, ServerState::TX_STREAMING], true)) {
205+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'DISCARD\' cannot be handled by a session which isn\'t in the STREAMING|TX_STREAMING state.')]);
206+
}
203207

204-
$response = $bolt->discard($extra)
208+
$extra = $this->buildResultExtra(null, $qid);
209+
$response = $this->protocol()
210+
->discard($extra)
205211
->getResponse();
206-
207212
$this->assertNoFailure($response);
208213
}
209214

@@ -216,12 +221,15 @@ public function discard(?int $qid): void
216221
*/
217222
public function run(string $text, array $parameters, ?string $database, ?float $timeout, BookmarkHolder $holder, ?AccessMode $mode): array
218223
{
224+
if (!in_array($this->protocol()->serverState, [ServerState::READY, ServerState::TX_READY, ServerState::TX_STREAMING], true)) {
225+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'RUN\' cannot be handled by a session which isn\'t in the READY|TX_READY|TX_STREAMING state.')]);
226+
}
227+
219228
$extra = $this->buildRunExtra($database, $timeout, $holder, $mode);
220-
$response = $this->protocol()->run($text, $parameters, $extra)
229+
$response = $this->protocol()
230+
->run($text, $parameters, $extra)
221231
->getResponse();
222-
223232
$this->assertNoFailure($response);
224-
225233
/** @var BoltMeta */
226234
return $response->content;
227235
}
@@ -234,10 +242,14 @@ public function run(string $text, array $parameters, ?string $database, ?float $
234242
public function commit(): void
235243
{
236244
$this->consumeResults();
245+
246+
if ($this->protocol()->serverState !== ServerState::TX_READY) {
247+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'COMMIT\' cannot be handled by a session which isn\'t in the TX_READY state.')]);
248+
}
249+
237250
$response = $this->protocol()
238251
->commit()
239252
->getResponse();
240-
241253
$this->assertNoFailure($response);
242254
}
243255

@@ -249,10 +261,14 @@ public function commit(): void
249261
public function rollback(): void
250262
{
251263
$this->consumeResults();
264+
265+
if ($this->protocol()->serverState !== ServerState::TX_READY) {
266+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'ROLLBACK\' cannot be handled by a session which isn\'t in the TX_READY state.')]);
267+
}
268+
252269
$response = $this->protocol()
253270
->rollback()
254271
->getResponse();
255-
256272
$this->assertNoFailure($response);
257273
}
258274

@@ -270,13 +286,16 @@ public function protocol(): V4_4|V5|V5_3|V5_4
270286
*/
271287
public function pull(?int $qid, ?int $fetchSize): array
272288
{
289+
if (!in_array($this->protocol()->serverState, [ServerState::STREAMING, ServerState::TX_STREAMING], true)) {
290+
throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'PULL\' cannot be handled by a session which isn\'t in the STREAMING|TX_STREAMING state.')]);
291+
}
292+
273293
$extra = $this->buildResultExtra($fetchSize, $qid);
274294

275295
$tbr = [];
276296
/** @var Response $response */
277297
foreach ($this->protocol()->pull($extra)->getResponses() as $response) {
278298
$this->assertNoFailure($response);
279-
280299
$tbr[] = $response->content;
281300
}
282301

src/Bolt/BoltUnmanagedTransaction.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,8 @@ public function commit(iterable $statements = []): CypherList
7171
}
7272
});
7373

74-
try {
75-
$this->connection->commit();
76-
$this->isCommitted = true;
77-
} catch (Throwable $e) {
78-
$this->isCommitted = false;
79-
$this->isRolledBack = true;
80-
throw $e;
81-
}
74+
$this->connection->commit();
75+
$this->isCommitted = true;
8276

8377
return $tbr;
8478
}

tests/Integration/TransactionIntegrationTest.php

Lines changed: 27 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,9 @@
1313

1414
namespace Laudis\Neo4j\Tests\Integration;
1515

16-
use Laudis\Neo4j\Bolt\BoltDriver;
17-
use Laudis\Neo4j\Bolt\Connection;
18-
use Laudis\Neo4j\Bolt\ConnectionPool;
1916
use Laudis\Neo4j\Databags\Statement;
2017
use Laudis\Neo4j\Exception\Neo4jException;
21-
use ReflectionClass;
22-
use Throwable;
18+
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
2319

2420
final class TransactionIntegrationTest extends EnvironmentAwareIntegrationTest
2521
{
@@ -215,28 +211,18 @@ public function testCommitValidFilledWithInvalidStatement(): void
215211
self::assertFalse($tsx->isCommitted());
216212
}
217213

218-
// TODO commit on READY state cause stuck neo4j connection on older version and disconnect at newer
219-
// public function testCommitInvalid(): void
220-
// {
221-
// $tsx = $this->getSession()->beginTransaction();
222-
// $tsx->commit();
223-
//
224-
// self::assertTrue($tsx->isFinished());
225-
// self::assertFalse($tsx->isRolledBack());
226-
// self::assertTrue($tsx->isCommitted());
227-
//
228-
// $exception = false;
229-
// try {
230-
// $tsx->commit();
231-
// } catch (Throwable) {
232-
// $exception = true;
233-
// }
234-
// self::assertTrue($exception);
235-
//
236-
// self::assertTrue($tsx->isFinished());
237-
// self::assertTrue($tsx->isRolledBack());
238-
// self::assertFalse($tsx->isCommitted());
239-
// }
214+
public function testCommitInvalid(): void
215+
{
216+
$tsx = $this->getSession()->beginTransaction();
217+
$tsx->commit();
218+
219+
self::assertTrue($tsx->isFinished());
220+
self::assertFalse($tsx->isRolledBack());
221+
self::assertTrue($tsx->isCommitted());
222+
223+
$this->expectException(Neo4jException::class);
224+
$tsx->commit();
225+
}
240226

241227
public function testRollbackValid(): void
242228
{
@@ -248,28 +234,18 @@ public function testRollbackValid(): void
248234
self::assertFalse($tsx->isCommitted());
249235
}
250236

251-
// TODO rollback on READY state cause stuck neo4j connection on older version and disconnect at newer
252-
// public function testRollbackInvalid(): void
253-
// {
254-
// $tsx = $this->getSession()->beginTransaction();
255-
// $tsx->rollback();
256-
//
257-
// self::assertTrue($tsx->isFinished());
258-
// self::assertTrue($tsx->isRolledBack());
259-
// self::assertFalse($tsx->isCommitted());
260-
//
261-
// $exception = false;
262-
// try {
263-
// $tsx->rollback();
264-
// } catch (Throwable) {
265-
// $exception = true;
266-
// }
267-
// self::assertTrue($exception);
268-
//
269-
// self::assertTrue($tsx->isFinished());
270-
// self::assertTrue($tsx->isRolledBack());
271-
// self::assertFalse($tsx->isCommitted());
272-
// }
237+
public function testRollbackInvalid(): void
238+
{
239+
$tsx = $this->getSession()->beginTransaction();
240+
$tsx->rollback();
241+
242+
self::assertTrue($tsx->isFinished());
243+
self::assertTrue($tsx->isRolledBack());
244+
self::assertFalse($tsx->isCommitted());
245+
246+
$this->expectException(Neo4jException::class);
247+
$tsx->rollback();
248+
}
273249

274250
// /**
275251
// * TODO - rework this test
@@ -306,9 +282,7 @@ public function testRollbackValid(): void
306282
// self::assertCount(3, $cache[$key]);
307283
// }
308284

309-
/**
310-
* @doesNotPerformAssertions
311-
*/
285+
#[DoesNotPerformAssertions]
312286
public function testTransactionRunNoConsumeResult(): void
313287
{
314288
$tsx = $this->getSession()->beginTransaction([]);
@@ -317,9 +291,7 @@ public function testTransactionRunNoConsumeResult(): void
317291
$tsx->commit();
318292
}
319293

320-
/**
321-
* @doesNotPerformAssertions
322-
*/
294+
#[DoesNotPerformAssertions]
323295
public function testTransactionRunNoConsumeButSaveResult(): void
324296
{
325297
$tsx = $this->getSession()->beginTransaction([]);

0 commit comments

Comments
 (0)