From 93cc40a5280c70458ac5276088796f60a99d42c5 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 31 Jul 2024 12:33:47 +0530 Subject: [PATCH 1/8] feat: Add transaction state --- docker-compose.yml | 2 -- src/Bolt/BoltUnmanagedTransaction.php | 49 +++++++++++++++++++-------- src/Enum/TransactionEffect.php | 40 ---------------------- src/Enum/TransactionState.php | 39 +++++++++++++++++++++ src/Exception/ClientException.php | 36 ++++++++++++++++++++ 5 files changed, 110 insertions(+), 56 deletions(-) delete mode 100644 src/Enum/TransactionEffect.php create mode 100644 src/Enum/TransactionState.php create mode 100644 src/Exception/ClientException.php diff --git a/docker-compose.yml b/docker-compose.yml index 6dbf3a8e..df0d5660 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - x-definitions: x-shared-env: &common-env diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index cf649e68..e0890193 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -20,6 +20,8 @@ use Laudis\Neo4j\Databags\SessionConfiguration; use Laudis\Neo4j\Databags\Statement; use Laudis\Neo4j\Databags\TransactionConfiguration; +use Laudis\Neo4j\Enum\TransactionState; +use Laudis\Neo4j\Exception\ClientException; use Laudis\Neo4j\Exception\Neo4jException; use Laudis\Neo4j\ParameterHelper; use Laudis\Neo4j\Types\AbstractCypherSequence; @@ -40,9 +42,7 @@ */ final class BoltUnmanagedTransaction implements UnmanagedTransactionInterface { - private bool $isRolledBack = false; - - private bool $isCommitted = false; + private TransactionState $state = TransactionState::ACTIVE; /** * @param FormatterInterface $formatter @@ -59,10 +59,26 @@ public function __construct( private readonly SessionConfiguration $config, private readonly TransactionConfiguration $tsxConfig, private readonly BookmarkHolder $bookmarkHolder - ) {} + ) { + } + /** + * @throws ClientException|Throwable + */ public function commit(iterable $statements = []): CypherList { + if ($this->isFinished()) { + switch ($this->state) { + case TransactionState::TERMINATED: + throw new ClientException("Can't commit, transaction has been terminated"); + case TransactionState::COMMITTED: + throw new ClientException("Can't commit, transaction has already been committed"); + case TransactionState::ROLLED_BACK: + throw new ClientException("Can't commit, transaction has already been rolled back"); + default: + } + } + // Force the results to pull all the results. // After a commit, the connection will be in the ready state, making it impossible to use PULL $tbr = $this->runStatements($statements)->each(static function ($list) { @@ -72,7 +88,7 @@ public function commit(iterable $statements = []): CypherList }); $this->connection->commit(); - $this->isCommitted = true; + $this->state = TransactionState::COMMITTED; return $tbr; } @@ -80,7 +96,7 @@ public function commit(iterable $statements = []): CypherList public function rollback(): void { $this->connection->rollback(); - $this->isRolledBack = true; + $this->state = TransactionState::ROLLED_BACK; } /** @@ -109,7 +125,7 @@ public function runStatement(Statement $statement) $this->config->getAccessMode() ); } catch (Throwable $e) { - $this->isRolledBack = true; + $this->state = TransactionState::TERMINATED; throw $e; } $run = microtime(true); @@ -140,18 +156,23 @@ public function runStatements(iterable $statements): CypherList } /** - * @throws Neo4jException + * @param Neo4jException $e * * @return never + * @throws Neo4jException + * */ - private function handleMessageException(Neo4jException $e): void + private function handleMessageException(Neo4jException $e): never { $exception = $e->getErrors()[0]; if (!($exception->getClassification() === 'ClientError' && $exception->getCategory() === 'Request')) { $this->connection->reset(); } - if (!$this->isFinished() && in_array($exception->getClassification(), TransactionHelper::ROLLBACK_CLASSIFICATIONS)) { - $this->isRolledBack = true; + if (!$this->isFinished() && in_array( + $exception->getClassification(), + TransactionHelper::ROLLBACK_CLASSIFICATIONS + )) { + $this->state = TransactionState::ROLLED_BACK; } throw $e; @@ -159,16 +180,16 @@ private function handleMessageException(Neo4jException $e): void public function isRolledBack(): bool { - return $this->isRolledBack; + return $this->state == TransactionState::ROLLED_BACK; } public function isCommitted(): bool { - return $this->isCommitted; + return $this->state == TransactionState::COMMITTED; } public function isFinished(): bool { - return $this->isRolledBack() || $this->isCommitted(); + return $this->state != TransactionState::ACTIVE; } } diff --git a/src/Enum/TransactionEffect.php b/src/Enum/TransactionEffect.php deleted file mode 100644 index 9d898538..00000000 --- a/src/Enum/TransactionEffect.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Laudis\Neo4j\Enum; - -use JsonSerializable; -use Laudis\TypedEnum\TypedEnum; - -/** - * Defines the access mode of a connection. - * - * @method static self ROLLBACK() - * @method static self NONE() - * - * @extends TypedEnum - * - * @psalm-immutable - * - * @psalm-suppress MutableDependency - */ -final class TransactionEffect extends TypedEnum implements JsonSerializable -{ - private const ROLLBACK = 'rollback'; - private const WRITE = 'none'; - - public function jsonSerialize(): string - { - return $this->getValue(); - } -} diff --git a/src/Enum/TransactionState.php b/src/Enum/TransactionState.php new file mode 100644 index 00000000..018cac94 --- /dev/null +++ b/src/Enum/TransactionState.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Laudis\Neo4j\Enum; + +/** + * The state of a transaction. + */ +enum TransactionState { + /** + * The transaction is running with no explicit success or failure marked + */ + case ACTIVE; + + /** + * This transaction has been terminated because of a fatal connection error. + */ + case TERMINATED; + + /** + * This transaction has successfully committed + */ + case COMMITTED; + + /** + * This transaction has been rolled back + */ + case ROLLED_BACK; +} diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php new file mode 100644 index 00000000..cbab139c --- /dev/null +++ b/src/Exception/ClientException.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Laudis\Neo4j\Exception; + +use RuntimeException; +use Throwable; + +/** + * Exception when a Client Error occurs. + * + * @psalm-immutable + * + * @psalm-suppress MutableDependency + */ +final class ClientException extends RuntimeException +{ + /** + * @param string $message + * @param Throwable|null $previous + */ + public function __construct(string $message, ?Throwable $previous = null) + { + parent::__construct($message, 0, $previous); + } +} From 585335e12ce8a8763de730b2f6112af3c5d7e962 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 31 Jul 2024 13:06:26 +0530 Subject: [PATCH 2/8] feat: Fix tests --- src/Bolt/BoltConnection.php | 25 +---- src/Bolt/BoltResult.php | 5 + src/Bolt/BoltUnmanagedTransaction.php | 14 ++- .../TransactionIntegrationTest.php | 98 +++++++++---------- 4 files changed, 72 insertions(+), 70 deletions(-) diff --git a/src/Bolt/BoltConnection.php b/src/Bolt/BoltConnection.php index 8bf528a0..9e3cf8ce 100644 --- a/src/Bolt/BoltConnection.php +++ b/src/Bolt/BoltConnection.php @@ -151,6 +151,11 @@ public function setTimeout(float $timeout): void public function consumeResults(): void { + if ($this->protocol()->serverState !== ServerState::STREAMING || $this->protocol()->serverState !== ServerState::TX_STREAMING) { + $this->subscribedResults = []; + return; + } + foreach ($this->subscribedResults as $result) { $result = $result->get(); if ($result) { @@ -185,10 +190,6 @@ public function begin(?string $database, ?float $timeout, BookmarkHolder $holder { $this->consumeResults(); - if ($this->protocol()->serverState !== ServerState::READY) { - throw new Neo4jException([Neo4jError::fromMessageAndCode('Neo.ClientError.Request.Invalid', 'Message \'BEGIN\' cannot be handled by a session which isn\'t in the READY state.')]); - } - $extra = $this->buildRunExtra($database, $timeout, $holder, AccessMode::WRITE()); $response = $this->protocol() ->begin($extra) @@ -203,10 +204,6 @@ public function begin(?string $database, ?float $timeout, BookmarkHolder $holder */ public function discard(?int $qid): void { - if (!in_array($this->protocol()->serverState, [ServerState::STREAMING, ServerState::TX_STREAMING], true)) { - 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.')]); - } - $extra = $this->buildResultExtra(null, $qid); $response = $this->protocol() ->discard($extra) @@ -223,10 +220,6 @@ public function discard(?int $qid): void */ public function run(string $text, array $parameters, ?string $database, ?float $timeout, BookmarkHolder $holder, ?AccessMode $mode): array { - if (!in_array($this->protocol()->serverState, [ServerState::READY, ServerState::TX_READY, ServerState::TX_STREAMING], true)) { - 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.')]); - } - $extra = $this->buildRunExtra($database, $timeout, $holder, $mode); $response = $this->protocol() ->run($text, $parameters, $extra) @@ -260,10 +253,6 @@ public function rollback(): void { $this->consumeResults(); - if ($this->protocol()->serverState !== ServerState::TX_READY) { - 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.')]); - } - $response = $this->protocol() ->rollback() ->getResponse(); @@ -284,10 +273,6 @@ public function protocol(): V4_4|V5|V5_1|V5_2|V5_3|V5_4 */ public function pull(?int $qid, ?int $fetchSize): array { - if (!in_array($this->protocol()->serverState, [ServerState::STREAMING, ServerState::TX_STREAMING], true)) { - 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.')]); - } - $extra = $this->buildResultExtra($fetchSize, $qid); $tbr = []; diff --git a/src/Bolt/BoltResult.php b/src/Bolt/BoltResult.php index dd243b28..35b3c6b1 100644 --- a/src/Bolt/BoltResult.php +++ b/src/Bolt/BoltResult.php @@ -13,6 +13,7 @@ namespace Laudis\Neo4j\Bolt; +use Bolt\enum\ServerState; use function array_splice; use function count; @@ -148,6 +149,10 @@ public function __destruct() public function discard(): void { + $serverState = $this->connection->protocol()->serverState; + if ($serverState !== ServerState::STREAMING || $serverState !== ServerState::TX_STREAMING) { + return; + } $this->connection->discard($this->qid === -1 ? null : $this->qid); } } diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index e0890193..a6998969 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -95,6 +95,18 @@ public function commit(iterable $statements = []): CypherList public function rollback(): void { + if ($this->isFinished()) { + switch ($this->state) { + case TransactionState::TERMINATED: + throw new ClientException("Can't rollback, transaction has been terminated"); + case TransactionState::COMMITTED: + throw new ClientException("Can't rollback, transaction has already been committed"); + case TransactionState::ROLLED_BACK: + throw new ClientException("Can't rollback, transaction has already been rolled back"); + default: + } + } + $this->connection->rollback(); $this->state = TransactionState::ROLLED_BACK; } @@ -180,7 +192,7 @@ private function handleMessageException(Neo4jException $e): never public function isRolledBack(): bool { - return $this->state == TransactionState::ROLLED_BACK; + return $this->state === TransactionState::ROLLED_BACK || $this->state === TransactionState::TERMINATED; } public function isCommitted(): bool diff --git a/tests/Integration/TransactionIntegrationTest.php b/tests/Integration/TransactionIntegrationTest.php index 8fdbbdf3..4d5f0a59 100644 --- a/tests/Integration/TransactionIntegrationTest.php +++ b/tests/Integration/TransactionIntegrationTest.php @@ -14,6 +14,7 @@ namespace Laudis\Neo4j\Tests\Integration; use Laudis\Neo4j\Databags\Statement; +use Laudis\Neo4j\Exception\ClientException; use Laudis\Neo4j\Exception\Neo4jException; use Laudis\Neo4j\Tests\EnvironmentAwareIntegrationTest; use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; @@ -213,61 +214,60 @@ public function testCommitValidFilledWithInvalidStatement(): void } // TODO commit on READY state cause stuck neo4j connection on older version and disconnect at newer -// public function testCommitInvalid(): void -// { -// $tsx = $this->getSession()->beginTransaction(); -// $tsx->commit(); -// -// self::assertTrue($tsx->isFinished()); -// self::assertFalse($tsx->isRolledBack()); -// self::assertTrue($tsx->isCommitted()); -// -// $exception = false; -// try { -// $tsx->commit(); -// } catch (Throwable) { -// $exception = true; -// } -// self::assertTrue($exception); -// -// self::assertTrue($tsx->isFinished()); -// self::assertTrue($tsx->isRolledBack()); -// self::assertFalse($tsx->isCommitted()); -// } + public function testCommitInvalid(): void + { + $tsx = $this->getSession()->beginTransaction(); + $tsx->commit(); + + self::assertTrue($tsx->isFinished()); + self::assertFalse($tsx->isRolledBack()); + self::assertTrue($tsx->isCommitted()); + + $exception = null; + try { + $tsx->commit(); + } catch (ClientException $e) { + $exception = $e; + } + self::assertTrue($exception instanceof ClientException); + + self::assertTrue($tsx->isFinished()); + self::assertFalse($tsx->isRolledBack()); + self::assertTrue($tsx->isCommitted()); + } public function testRollbackValid(): void { - $this->markTestSkipped('Skipped due to ConnectionTimeoutException'); -// $tsx = $this->getSession()->beginTransaction(); -// $tsx->rollback(); -// -// self::assertTrue($tsx->isFinished()); -// self::assertTrue($tsx->isRolledBack()); -// self::assertFalse($tsx->isCommitted()); + $tsx = $this->getSession()->beginTransaction(); + $tsx->rollback(); + + self::assertTrue($tsx->isFinished()); + self::assertTrue($tsx->isRolledBack()); + self::assertFalse($tsx->isCommitted()); } // TODO rollback on READY state cause stuck neo4j connection on older version and disconnect at newer -// public function testRollbackInvalid(): void -// { -// $tsx = $this->getSession()->beginTransaction(); -// $tsx->rollback(); -// -// self::assertTrue($tsx->isFinished()); -// self::assertTrue($tsx->isRolledBack()); -// self::assertFalse($tsx->isCommitted()); -// -// $exception = false; -// try { -// $tsx->rollback(); -// } catch (Throwable) { -// $exception = true; -// } -// self::assertTrue($exception); -// -// self::assertTrue($tsx->isFinished()); -// self::assertTrue($tsx->isRolledBack()); -// self::assertFalse($tsx->isCommitted()); -// } + public function testRollbackInvalid(): void + { + $tsx = $this->getSession()->beginTransaction(); + $tsx->rollback(); + + self::assertTrue($tsx->isFinished()); + self::assertTrue($tsx->isRolledBack()); + self::assertFalse($tsx->isCommitted()); + + $exception = null; + try { + $tsx->rollback(); + } catch (ClientException $e) { + $exception = $e; + } + self::assertTrue($exception instanceof ClientException); + + self::assertTrue($tsx->isFinished()); + self::assertTrue($tsx->isRolledBack()); + self::assertFalse($tsx->isCommitted()); + } // /** // * TODO - rework this test From 2d7bdd98c3883b1ac243539c3a24d725af426f66 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Sat, 3 Aug 2024 12:31:53 +0530 Subject: [PATCH 3/8] fix: Consume results if server state in streaming --- src/Bolt/BoltConnection.php | 2 +- src/Bolt/BoltResult.php | 4 ---- src/Bolt/BoltUnmanagedTransaction.php | 6 ++++++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Bolt/BoltConnection.php b/src/Bolt/BoltConnection.php index 9e3cf8ce..0254db2e 100644 --- a/src/Bolt/BoltConnection.php +++ b/src/Bolt/BoltConnection.php @@ -151,7 +151,7 @@ public function setTimeout(float $timeout): void public function consumeResults(): void { - if ($this->protocol()->serverState !== ServerState::STREAMING || $this->protocol()->serverState !== ServerState::TX_STREAMING) { + if ($this->protocol()->serverState !== ServerState::STREAMING && $this->protocol()->serverState !== ServerState::TX_STREAMING) { $this->subscribedResults = []; return; } diff --git a/src/Bolt/BoltResult.php b/src/Bolt/BoltResult.php index 35b3c6b1..3a41d573 100644 --- a/src/Bolt/BoltResult.php +++ b/src/Bolt/BoltResult.php @@ -149,10 +149,6 @@ public function __destruct() public function discard(): void { - $serverState = $this->connection->protocol()->serverState; - if ($serverState !== ServerState::STREAMING || $serverState !== ServerState::TX_STREAMING) { - return; - } $this->connection->discard($this->qid === -1 ? null : $this->qid); } } diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index a6998969..ef814cef 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -13,6 +13,7 @@ namespace Laudis\Neo4j\Bolt; +use Bolt\enum\ServerState; use Laudis\Neo4j\Common\TransactionHelper; use Laudis\Neo4j\Contracts\FormatterInterface; use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface; @@ -127,6 +128,11 @@ public function runStatement(Statement $statement) $parameters = ParameterHelper::formatParameters($statement->getParameters(), $this->connection->getProtocol()); $start = microtime(true); + $serverState = $this->connection->protocol()->serverState; + if (in_array($serverState, [ServerState::STREAMING, ServerState::TX_STREAMING])) { + $this->connection->consumeResults(); + } + try { $meta = $this->connection->run( $statement->getText(), From 82d7c53c3c16f4099936f700f3f05dc7a3642a2d Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 7 Aug 2024 10:19:07 +0530 Subject: [PATCH 4/8] fix: Run CS --- src/Bolt/BoltConnection.php | 2 +- src/Bolt/BoltResult.php | 1 - src/Bolt/BoltUnmanagedTransaction.php | 13 ++++--------- src/Enum/TransactionState.php | 9 +++++---- src/Exception/ClientException.php | 4 ---- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/Bolt/BoltConnection.php b/src/Bolt/BoltConnection.php index 0254db2e..dba4e9a2 100644 --- a/src/Bolt/BoltConnection.php +++ b/src/Bolt/BoltConnection.php @@ -28,7 +28,6 @@ use Laudis\Neo4j\Contracts\FormatterInterface; use Laudis\Neo4j\Databags\BookmarkHolder; use Laudis\Neo4j\Databags\DatabaseInfo; -use Laudis\Neo4j\Databags\Neo4jError; use Laudis\Neo4j\Enum\AccessMode; use Laudis\Neo4j\Enum\ConnectionProtocol; use Laudis\Neo4j\Exception\Neo4jException; @@ -153,6 +152,7 @@ public function consumeResults(): void { if ($this->protocol()->serverState !== ServerState::STREAMING && $this->protocol()->serverState !== ServerState::TX_STREAMING) { $this->subscribedResults = []; + return; } diff --git a/src/Bolt/BoltResult.php b/src/Bolt/BoltResult.php index 3a41d573..dd243b28 100644 --- a/src/Bolt/BoltResult.php +++ b/src/Bolt/BoltResult.php @@ -13,7 +13,6 @@ namespace Laudis\Neo4j\Bolt; -use Bolt\enum\ServerState; use function array_splice; use function count; diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index ef814cef..17e32d91 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -60,8 +60,7 @@ public function __construct( private readonly SessionConfiguration $config, private readonly TransactionConfiguration $tsxConfig, private readonly BookmarkHolder $bookmarkHolder - ) { - } + ) {} /** * @throws ClientException|Throwable @@ -174,11 +173,7 @@ public function runStatements(iterable $statements): CypherList } /** - * @param Neo4jException $e - * - * @return never * @throws Neo4jException - * */ private function handleMessageException(Neo4jException $e): never { @@ -187,9 +182,9 @@ private function handleMessageException(Neo4jException $e): never $this->connection->reset(); } if (!$this->isFinished() && in_array( - $exception->getClassification(), - TransactionHelper::ROLLBACK_CLASSIFICATIONS - )) { + $exception->getClassification(), + TransactionHelper::ROLLBACK_CLASSIFICATIONS + )) { $this->state = TransactionState::ROLLED_BACK; } diff --git a/src/Enum/TransactionState.php b/src/Enum/TransactionState.php index 018cac94..6df70917 100644 --- a/src/Enum/TransactionState.php +++ b/src/Enum/TransactionState.php @@ -16,9 +16,10 @@ /** * The state of a transaction. */ -enum TransactionState { +enum TransactionState +{ /** - * The transaction is running with no explicit success or failure marked + * The transaction is running with no explicit success or failure marked. */ case ACTIVE; @@ -28,12 +29,12 @@ enum TransactionState { case TERMINATED; /** - * This transaction has successfully committed + * This transaction has successfully committed. */ case COMMITTED; /** - * This transaction has been rolled back + * This transaction has been rolled back. */ case ROLLED_BACK; } diff --git a/src/Exception/ClientException.php b/src/Exception/ClientException.php index cbab139c..81639c5a 100644 --- a/src/Exception/ClientException.php +++ b/src/Exception/ClientException.php @@ -25,10 +25,6 @@ */ final class ClientException extends RuntimeException { - /** - * @param string $message - * @param Throwable|null $previous - */ public function __construct(string $message, ?Throwable $previous = null) { parent::__construct($message, 0, $previous); From 7f13b729de4c85d9ca44e455cf3f3dfc95177399 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 7 Aug 2024 12:54:47 +0530 Subject: [PATCH 5/8] refactor: Convert switch to if statements --- src/Bolt/BoltUnmanagedTransaction.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index 17e32d91..06cd77de 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -68,14 +68,16 @@ public function __construct( public function commit(iterable $statements = []): CypherList { if ($this->isFinished()) { - switch ($this->state) { - case TransactionState::TERMINATED: - throw new ClientException("Can't commit, transaction has been terminated"); - case TransactionState::COMMITTED: - throw new ClientException("Can't commit, transaction has already been committed"); - case TransactionState::ROLLED_BACK: - throw new ClientException("Can't commit, transaction has already been rolled back"); - default: + if ($this->state === TransactionState::TERMINATED) { + throw new ClientException("Can't commit, transaction has been terminated"); + } + + if ($this->state === TransactionState::COMMITTED) { + throw new ClientException("Can't commit, transaction has already been committed"); + } + + if ($this->state === TransactionState::ROLLED_BACK) { + throw new ClientException("Can't commit, transaction has already been rolled back"); } } From 06af7716665107458f57b342de39f3fafe11f6d8 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 7 Aug 2024 12:56:17 +0530 Subject: [PATCH 6/8] refactor: Convert switch to if statements --- src/Bolt/BoltUnmanagedTransaction.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index 06cd77de..082df8d4 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -98,14 +98,16 @@ public function commit(iterable $statements = []): CypherList public function rollback(): void { if ($this->isFinished()) { - switch ($this->state) { - case TransactionState::TERMINATED: - throw new ClientException("Can't rollback, transaction has been terminated"); - case TransactionState::COMMITTED: - throw new ClientException("Can't rollback, transaction has already been committed"); - case TransactionState::ROLLED_BACK: - throw new ClientException("Can't rollback, transaction has already been rolled back"); - default: + if ($this->state === TransactionState::TERMINATED) { + throw new ClientException("Can't rollback, transaction has been terminated"); + } + + if ($this->state === TransactionState::COMMITTED) { + throw new ClientException("Can't rollback, transaction has already been committed"); + } + + if ($this->state === TransactionState::ROLLED_BACK) { + throw new ClientException("Can't rollback, transaction has already been rolled back"); } } From 8bf344b2530e9b34014a2a5a20e6d5db7fa4abab Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 7 Aug 2024 12:57:28 +0530 Subject: [PATCH 7/8] refactor: Remove unused method --- src/Bolt/BoltUnmanagedTransaction.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index 082df8d4..e7541b40 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -176,25 +176,6 @@ public function runStatements(iterable $statements): CypherList return new CypherList($tbr); } - /** - * @throws Neo4jException - */ - private function handleMessageException(Neo4jException $e): never - { - $exception = $e->getErrors()[0]; - if (!($exception->getClassification() === 'ClientError' && $exception->getCategory() === 'Request')) { - $this->connection->reset(); - } - if (!$this->isFinished() && in_array( - $exception->getClassification(), - TransactionHelper::ROLLBACK_CLASSIFICATIONS - )) { - $this->state = TransactionState::ROLLED_BACK; - } - - throw $e; - } - public function isRolledBack(): bool { return $this->state === TransactionState::ROLLED_BACK || $this->state === TransactionState::TERMINATED; From 1c0a80ef105bb9c33671cdb60c578422c34fdf95 Mon Sep 17 00:00:00 2001 From: exaby73 Date: Wed, 7 Aug 2024 12:58:43 +0530 Subject: [PATCH 8/8] chore: Fix CS --- src/Bolt/BoltUnmanagedTransaction.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Bolt/BoltUnmanagedTransaction.php b/src/Bolt/BoltUnmanagedTransaction.php index e7541b40..9a547551 100644 --- a/src/Bolt/BoltUnmanagedTransaction.php +++ b/src/Bolt/BoltUnmanagedTransaction.php @@ -14,7 +14,6 @@ namespace Laudis\Neo4j\Bolt; use Bolt\enum\ServerState; -use Laudis\Neo4j\Common\TransactionHelper; use Laudis\Neo4j\Contracts\FormatterInterface; use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface; use Laudis\Neo4j\Databags\BookmarkHolder; @@ -23,7 +22,6 @@ use Laudis\Neo4j\Databags\TransactionConfiguration; use Laudis\Neo4j\Enum\TransactionState; use Laudis\Neo4j\Exception\ClientException; -use Laudis\Neo4j\Exception\Neo4jException; use Laudis\Neo4j\ParameterHelper; use Laudis\Neo4j\Types\AbstractCypherSequence; use Laudis\Neo4j\Types\CypherList;