Move create and mount SQL calls to repository for proper cache invalidation

This commit is contained in:
Thibaud Fabre
2016-01-28 15:53:23 +01:00
parent 2643874b73
commit 40ff41501c
6 changed files with 212 additions and 105 deletions

View File

@@ -145,9 +145,9 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
}); });
$app['repo.databoxes'] = $app->share(function (PhraseaApplication $app) { $app['repo.databoxes'] = $app->share(function (PhraseaApplication $app) {
$factory = new DataboxFactory($app);
$appbox = $app->getApplicationBox(); $appbox = $app->getApplicationBox();
$factory = new DataboxFactory($app);
$repository = new CachingDataboxRepositoryDecorator( $repository = new CachingDataboxRepositoryDecorator(
new DbalDataboxRepository($appbox->get_connection(), $factory), new DbalDataboxRepository($appbox->get_connection(), $factory),
$app['cache'], $app['cache'],
@@ -155,9 +155,11 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
$factory $factory
); );
$repository = new ArrayCacheDataboxRepository($repository);
$factory->setDataboxRepository($repository); $factory->setDataboxRepository($repository);
return new ArrayCacheDataboxRepository($repository); return $repository;
}); });
$app['repo.fields.factory'] = $app->protect(function (\databox $databox) use ($app) { $app['repo.fields.factory'] = $app->protect(function (\databox $databox) use ($app) {

View File

@@ -57,12 +57,46 @@ class ArrayCacheDataboxRepository implements DataboxRepository
*/ */
public function save(\databox $databox) public function save(\databox $databox)
{ {
$this->loaded = false; $this->clear();
$this->databoxes = [];
return $this->repository->save($databox); return $this->repository->save($databox);
} }
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function mount($host, $port, $user, $password, $dbname)
{
$this->clear();
return $this->repository->mount($host, $port, $user, $password, $dbname);
}
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function create($host, $port, $user, $password, $dbname)
{
$this->clear();
return $this->repository->create($host, $port, $user, $password, $dbname);
}
/**
* Initializes the memory cache if needed.
*/
private function load() private function load()
{ {
if (! $this->loaded) { if (! $this->loaded) {
@@ -70,4 +104,13 @@ class ArrayCacheDataboxRepository implements DataboxRepository
$this->loaded = true; $this->loaded = true;
} }
} }
/**
* Clears the memory cache.
*/
private function clear()
{
$this->loaded = false;
$this->databoxes = [];
}
} }

View File

@@ -32,7 +32,7 @@ final class CachingDataboxRepositoryDecorator implements DataboxRepository
{ {
$this->repository = $repository; $this->repository = $repository;
$this->cache = $cache; $this->cache = $cache;
$this->cacheKey = 'databoxes:' . hash('sha256', $cacheKey); $this->cacheKey = $cacheKey;
$this->factory = $factory; $this->factory = $factory;
} }
@@ -64,11 +64,47 @@ final class CachingDataboxRepositoryDecorator implements DataboxRepository
public function save(\databox $databox) public function save(\databox $databox)
{ {
$this->cache->delete($this->cacheKey); $this->clearCache();
return $this->repository->save($databox); return $this->repository->save($databox);
} }
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function mount($host, $port, $user, $password, $dbname)
{
$databox = $this->repository->mount($host, $port, $user, $password, $dbname);
$this->clearCache();
return $databox;
}
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function create($host, $port, $user, $password, $dbname)
{
$databox = $this->repository->create($host, $port, $user, $password, $dbname);
$this->clearCache();
return $databox;
}
/** /**
* @param \databox[] $databoxes * @param \databox[] $databoxes
*/ */
@@ -82,4 +118,9 @@ final class CachingDataboxRepositoryDecorator implements DataboxRepository
$this->cache->save($this->cacheKey, $rows); $this->cache->save($this->cacheKey, $rows);
} }
private function clearCache()
{
$this->cache->delete($this->cacheKey);
}
} }

View File

@@ -26,4 +26,26 @@ interface DataboxRepository
* @param \databox $databox * @param \databox $databox
*/ */
public function save(\databox $databox); public function save(\databox $databox);
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function mount($host, $port, $user, $password, $dbname);
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function create($host, $port, $user, $password, $dbname);
} }

View File

@@ -47,6 +47,10 @@ final class DbalDataboxRepository implements DataboxRepository
return $this->factory->createMany($this->fetchRows()); return $this->factory->createMany($this->fetchRows());
} }
/**
* @param \databox $databox
* @return bool
*/
public function save(\databox $databox) public function save(\databox $databox)
{ {
return true; return true;
@@ -87,4 +91,73 @@ final class DbalDataboxRepository implements DataboxRepository
return $rows; return $rows;
} }
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function mount($host, $port, $user, $password, $dbname)
{
$query = 'INSERT INTO sbas (ord, host, port, dbname, sqlengine, user, pwd)
SELECT COALESCE(MAX(ord), 0) + 1 AS ord, :host AS host, :port AS port, :dbname AS dbname,
"MYSQL" AS sqlengine, :user AS user, :password AS pwd FROM sbas';
$statement = $this->connection->prepare($query);
$statement->execute([
':host' => $host,
':port' => $port,
':dbname' => $dbname,
':user' => $user,
':password' => $password
]);
$statement->closeCursor();
return $this->find((int) $this->connection->lastInsertId());
}
/**
* @param $host
* @param $port
* @param $user
* @param $password
* @param $dbname
*
* @return \databox
*/
public function create($host, $port, $user, $password, $dbname)
{
$params = [
':host' => $host,
':port' => $port,
':user' => $user,
':password' => $password,
':dbname' => $dbname
];
$query = 'SELECT sbas_id FROM sbas
WHERE host = :host AND port = :port AND `user` = :user AND pwd = :password AND dbname = :dbname';
$statement = $this->connection->executeQuery($query, $params);
if ($row = $statement->fetch(\PDO::FETCH_ASSOC)) {
return $this->find((int) $row['sbas_id']);
}
$query = 'INSERT INTO sbas (ord, host, port, dbname, sqlengine, user, pwd)
SELECT COALESCE(MAX(ord), 0) + 1 AS ord, :host AS host, :port AS port, :dbname AS dbname,
"MYSQL" AS sqlengine, :user AS user, :password AS pwd FROM sbas';
$stmt = $this->connection->prepare($query);
$stmt->execute($params);
$stmt->closeCursor();
return $this->find((int) $this->connection->lastInsertId());
}
} }

View File

@@ -62,51 +62,28 @@ class databox extends base implements ThumbnailedElement
/** /**
* @param Application $app * @param Application $app
* @param Connection $connection * @param Connection $databoxConnection
* @param SplFileInfo $data_template * @param SplFileInfo $data_template
* @return databox * @return databox
* @throws \Doctrine\DBAL\DBALException * @throws \Doctrine\DBAL\DBALException
*/ */
public static function create(Application $app, Connection $connection, \SplFileInfo $data_template) public static function create(Application $app, Connection $databoxConnection, \SplFileInfo $data_template)
{ {
if ( ! file_exists($data_template->getRealPath())) { if ( ! file_exists($data_template->getRealPath())) {
throw new \InvalidArgumentException($data_template->getRealPath() . " does not exist"); throw new \InvalidArgumentException($data_template->getRealPath() . " does not exist");
} }
$sql = 'SELECT sbas_id $host = $databoxConnection->getHost();
FROM sbas $port = $databoxConnection->getPort();
WHERE host = :host AND port = :port AND dbname = :dbname $dbname = $databoxConnection->getDatabase();
AND user = :user AND pwd = :password'; $user = $databoxConnection->getUsername();
$password = $databoxConnection->getPassword();
$host = $connection->getHost(); $appbox = $app->getApplicationBox();
$port = $connection->getPort();
$dbname = $connection->getDatabase();
$user = $connection->getUsername();
$password = $connection->getPassword();
$params = [
':host' => $host,
':port' => $port,
':dbname' => $dbname,
':user' => $user,
':password' => $password
];
/** @var appbox $appbox */
$appbox = $app['phraseanet.appbox'];
$stmt = $appbox->get_connection()->prepare($sql);
$stmt->execute($params);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if ($row) {
return $appbox->get_databox((int) $row['sbas_id']);
}
try { try {
$sql = 'CREATE DATABASE `' . $dbname . '` $sql = 'CREATE DATABASE `' . $dbname . '` CHARACTER SET utf8 COLLATE utf8_unicode_ci';
CHARACTER SET utf8 COLLATE utf8_unicode_ci'; $stmt = $databoxConnection->prepare($sql);
$stmt = $connection->prepare($sql);
$stmt->execute(); $stmt->execute();
$stmt->closeCursor(); $stmt->closeCursor();
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -114,29 +91,10 @@ class databox extends base implements ThumbnailedElement
} }
$sql = 'USE `' . $dbname . '`'; $sql = 'USE `' . $dbname . '`';
$stmt = $connection->prepare($sql); $stmt = $databoxConnection->prepare($sql);
$stmt->execute(); $stmt->execute();
$stmt->closeCursor(); $stmt->closeCursor();
$sql = 'SELECT MAX(ord) as ord FROM sbas';
$stmt = $appbox->get_connection()->prepare($sql);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if ($row) {
$ord = $row['ord'] + 1;
}
$params[':ord'] = $ord;
$sql = 'INSERT INTO sbas (sbas_id, ord, host, port, dbname, sqlengine, user, pwd)
VALUES (null, :ord, :host, :port, :dbname, "MYSQL", :user, :password)';
$stmt = $appbox->get_connection()->prepare($sql);
$stmt->execute($params);
$stmt->closeCursor();
$sbas_id = (int) $appbox->get_connection()->lastInsertId();
$app['orm.add']([ $app['orm.add']([
'host' => $host, 'host' => $host,
'port' => $port, 'port' => $port,
@@ -145,21 +103,20 @@ class databox extends base implements ThumbnailedElement
'password' => $password 'password' => $password
]); ]);
phrasea::reset_sbasDatas($app['phraseanet.appbox']);
/** @var DataboxRepository $databoxRepository */
$databoxRepository = $app['repo.databoxes'];
$databox = $databoxRepository->create($host, $port, $user, $password, $dbname);
$appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES); $appbox->delete_data_from_cache(appbox::CACHE_LIST_BASES);
$databox = $appbox->get_databox($sbas_id);
$databox->insert_datas(); $databox->insert_datas();
$databox->setNewStructure( $databox->setNewStructure(
$data_template, $app['conf']->get(['main', 'storage', 'subdefs']) $data_template, $app['conf']->get(['main', 'storage', 'subdefs'])
); );
$app['dispatcher']->dispatch( $app['dispatcher']->dispatch(DataboxEvents::CREATED, new CreatedEvent($databox));
DataboxEvents::CREATED,
new CreatedEvent(
$databox
)
);
return $databox; return $databox;
} }
@@ -176,56 +133,25 @@ class databox extends base implements ThumbnailedElement
*/ */
public static function mount(Application $app, $host, $port, $user, $password, $dbname) public static function mount(Application $app, $host, $port, $user, $password, $dbname)
{ {
$conn = $app['db.provider']([ $app['db.provider']([
'host' => $host, 'host' => $host,
'port' => $port, 'port' => $port,
'user' => $user, 'user' => $user,
'password' => $password, 'password' => $password,
'dbname' => $dbname, 'dbname' => $dbname,
]); ])->connect();
$conn->connect(); /** @var DataboxRepository $databoxRepository */
$databoxRepository = $app['repo.databoxes'];
$conn = $app->getApplicationBox()->get_connection(); $databox = $databoxRepository->mount($host, $port, $user, $password, $dbname);
$sql = 'SELECT MAX(ord) as ord FROM sbas';
$stmt = $conn->prepare($sql);
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
$stmt->closeCursor();
if ($row)
$ord = $row['ord'] + 1;
$sql = 'INSERT INTO sbas (sbas_id, ord, host, port, dbname, sqlengine, user, pwd)
VALUES (null, :ord, :host, :port, :dbname, "MYSQL", :user, :password)';
$stmt = $conn->prepare($sql);
$stmt->execute([
':ord' => $ord,
':host' => $host,
':port' => $port,
':dbname' => $dbname,
':user' => $user,
':password' => $password
]);
$stmt->closeCursor();
$sbas_id = (int) $conn->lastInsertId();
$app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
$databox = $app->findDataboxById($sbas_id);
$databox->delete_data_from_cache(databox::CACHE_COLLECTIONS); $databox->delete_data_from_cache(databox::CACHE_COLLECTIONS);
$app->getApplicationBox()->delete_data_from_cache(appbox::CACHE_LIST_BASES);
phrasea::reset_sbasDatas($app['phraseanet.appbox']); phrasea::reset_sbasDatas($app['phraseanet.appbox']);
cache_databox::update($app, $databox->get_sbas_id(), 'structure'); cache_databox::update($app, $databox->get_sbas_id(), 'structure');
$app['dispatcher']->dispatch( $app['dispatcher']->dispatch(DataboxEvents::MOUNTED, new MountedEvent($databox));
DataboxEvents::MOUNTED,
new MountedEvent(
$databox
)
);
return $databox; return $databox;
} }