Skip to content

Commit

Permalink
feat: extended complex search functionality to fetch lists data.
Browse files Browse the repository at this point in the history
  • Loading branch information
vbyndych committed Oct 12, 2023
1 parent 4828881 commit 0734075
Show file tree
Hide file tree
Showing 17 changed files with 622 additions and 70 deletions.
106 changes: 106 additions & 0 deletions common/persistence/Graph/BasicTransactionManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2023 (original work) Open Assessment Technologies SA;
*
*/

namespace oat\generis\persistence\Graph;

use Laudis\Neo4j\Contracts\ClientInterface;
use Laudis\Neo4j\Contracts\UnmanagedTransactionInterface;
use Laudis\Neo4j\Databags\Statement;
use Laudis\Neo4j\Databags\SummarizedResult;

class BasicTransactionManager implements TransactionManagerInterface
{
private ClientInterface $client;
private UnmanagedTransactionInterface $transaction;

public function __construct(ClientInterface $client)
{
$this->client = $client;
}

public function beginTransaction(): void
{
try {
$this->transaction = $this->client->beginTransaction();
} catch (\Throwable $e) {
throw new GraphTransactionException('Transaction was not started.', $e);
}
}

public function commit(): void
{
try {
if (isset($this->transaction)) {
$this->transaction->commit();
unset($this->transaction);
}
} catch (\Throwable $e) {
throw new GraphTransactionException('Transaction was not committed.', $e);
}
}

public function rollback(): void
{
try {
if (isset($this->transaction)) {
$this->transaction->rollback();
unset($this->transaction);
}
} catch (\Throwable $e) {
throw new GraphTransactionException('Transaction was not rolled back.', $e);
}
}

public function run(string $statement, iterable $parameters = []): SummarizedResult
{
try {
if (isset($this->transaction)) {
$result = $this->transaction->run($statement, $parameters);
} else {
$result = $this->client->run($statement, $parameters);
}
} catch (\Throwable $e) {
throw new GraphTransactionException(
sprintf('Exception happen during query run: %s.', $e->getMessage()),
$e
);
}

return $result;
}

public function runStatement(Statement $statement): SummarizedResult
{
try {
if (isset($this->transaction)) {
$result = $this->transaction->runStatement($statement);
} else {
$result = $this->client->runStatement($statement);
}
} catch (\Throwable $e) {
throw new GraphTransactionException(
sprintf('Exception happen during statement run: %s.', $e->getMessage()),
$e
);
}

return $result;
}
}
29 changes: 29 additions & 0 deletions common/persistence/Graph/GraphTransactionException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2023 (original work) Open Assessment Technologies SA;
*
*/

namespace oat\generis\persistence\Graph;

class GraphTransactionException extends \RuntimeException
{
public function __construct($message = "", \Throwable $previous = null)
{
parent::__construct($message, 0, $previous);
}
}
90 changes: 90 additions & 0 deletions common/persistence/Graph/NestedTransactionWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<?php
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2023 (original work) Open Assessment Technologies SA;
*
*/

namespace oat\generis\persistence\Graph;

use Laudis\Neo4j\Databags\Statement;
use Laudis\Neo4j\Databags\SummarizedResult;

class NestedTransactionWrapper implements TransactionManagerInterface
{
private TransactionManagerInterface $nestedTransactionManager;
private int $transactionNestingLevel = 0;
private bool $isRollbackOnly = false;

public function __construct(TransactionManagerInterface $nestedManager)
{
$this->nestedTransactionManager = $nestedManager;
}

public function beginTransaction(): void
{
$this->transactionNestingLevel++;

if ($this->transactionNestingLevel === 1) {
$this->nestedTransactionManager->beginTransaction();
}
}

public function commit(): void
{
if ($this->transactionNestingLevel === 0) {
throw new GraphTransactionException('Transaction should be started first.');
}

if ($this->isRollbackOnly) {
throw new GraphTransactionException(
'Nested transaction failed, so all data should be rolled back now.'
);
}

if ($this->transactionNestingLevel === 1) {
$this->nestedTransactionManager->commit();
}

$this->transactionNestingLevel--;
}

public function rollback(): void
{
if ($this->transactionNestingLevel === 0) {
throw new GraphTransactionException('Transaction should be started first.');
}

if ($this->transactionNestingLevel === 1) {
$this->nestedTransactionManager->rollBack();
$this->isRollbackOnly = false;
} else {
$this->isRollbackOnly = true;
}

$this->transactionNestingLevel--;
}

public function run(string $statement, iterable $parameters = []): SummarizedResult
{
return $this->nestedTransactionManager->run($statement, $parameters);
}

public function runStatement(Statement $statement): SummarizedResult
{
return $this->nestedTransactionManager->runStatement($statement);
}
}
67 changes: 67 additions & 0 deletions common/persistence/Graph/TransactionManagerInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2023 (original work) Open Assessment Technologies SA;
*
*/

namespace oat\generis\persistence\Graph;

use Laudis\Neo4j\Databags\Statement;
use Laudis\Neo4j\Databags\SummarizedResult;

interface TransactionManagerInterface
{
/**
* @return void
*
* @throws GraphTransactionException when starting transaction failed.
*/
public function beginTransaction(): void;

/**
* @return void
*
* @throws GraphTransactionException when transaction commit failed.
*/
public function commit(): void;

/**
* @return void
*
* @throws GraphTransactionException when transaction was not rolled back.
*/
public function rollback(): void;

/**
* @param string $statement
* @param iterable $parameters
*
* @return SummarizedResult
*
* @throws GraphTransactionException
*/
public function run(string $statement, iterable $parameters = []): SummarizedResult;

/**
* @param Statement $statement
*
* @return SummarizedResult
*
* @throws GraphTransactionException
*/
public function runStatement(Statement $statement): SummarizedResult;
}
47 changes: 39 additions & 8 deletions common/persistence/class.GraphPersistence.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,53 @@

use Laudis\Neo4j\Contracts\ClientInterface;
use Laudis\Neo4j\Databags\Statement;
use Laudis\Neo4j\Databags\SummarizedResult;
use oat\generis\persistence\Graph\BasicTransactionManager;
use oat\generis\persistence\Graph\NestedTransactionWrapper;
use oat\generis\persistence\Graph\TransactionManagerInterface;

class common_persistence_GraphPersistence extends common_persistence_Persistence
implements common_persistence_Transactional
{
public function run(string $statement, iterable $parameters = [])
private TransactionManagerInterface $transactionManager;

public function run(string $statement, iterable $parameters = []): SummarizedResult
{
/** @var ClientInterface $client */
$client = $this->getDriver()->getClient();
return $this->getConnection()->run($statement, $parameters);
}

public function runStatement(Statement $statement): SummarizedResult
{
return $this->getConnection()->runStatement($statement);
}

public function transactional(Closure $func)
{
$transactionManager = $this->getConnection();

$transactionManager->beginTransaction();
try {
$res = $func();
$transactionManager->commit();

return $res;
} catch (\Throwable $e) {
$transactionManager->rollBack();

return $client->run($statement, $parameters);
throw $e;
}
}

public function runStatement(Statement $statement)
private function getConnection(): TransactionManagerInterface
{
/** @var ClientInterface $client */
$client = $this->getDriver()->getClient();
if (!isset($this->transactionManager)) {
/** @var ClientInterface $client */
$client = $this->getDriver()->getClient();
$this->transactionManager = new NestedTransactionWrapper(
new BasicTransactionManager($client)
);
}

return $client->runStatement($statement);
return $this->transactionManager;
}
}
2 changes: 1 addition & 1 deletion common/persistence/class.SqlPersistence.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/**
* Persistence base on SQL
*/
class common_persistence_SqlPersistence extends common_persistence_Persistence
class common_persistence_SqlPersistence extends common_persistence_Persistence implements common_persistence_Transactional
{
/**
* @return common_persistence_sql_SchemaManager
Expand Down
Loading

0 comments on commit 0734075

Please sign in to comment.