Improve collection reference caching and remove legacy maps

This commit is contained in:
Thibaud Fabre
2015-07-10 18:39:36 +02:00
parent fcb369486a
commit d8f498aa26
12 changed files with 238 additions and 68 deletions

View File

@@ -2,7 +2,7 @@
namespace Alchemy\Phrasea\Collection; namespace Alchemy\Phrasea\Collection;
interface CollectionRepository interface CollectionRepository
{ {
/** /**
@@ -21,4 +21,10 @@ interface CollectionRepository
* @return void * @return void
*/ */
public function save(Collection $collection); public function save(Collection $collection);
/**
* @param Collection $collection
* @return void
*/
public function delete(Collection $collection);
} }

View File

@@ -2,6 +2,7 @@
namespace Alchemy\Phrasea\Collection; namespace Alchemy\Phrasea\Collection;
use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository; use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository;
class CollectionRepositoryRegistry class CollectionRepositoryRegistry
@@ -9,6 +10,11 @@ class CollectionRepositoryRegistry
private $baseIdMap = null; private $baseIdMap = null;
/**
* @var Application
*/
private $application;
/** /**
* @var CollectionRepository[] * @var CollectionRepository[]
*/ */
@@ -25,13 +31,16 @@ class CollectionRepositoryRegistry
private $repositoryFactory; private $repositoryFactory;
/** /**
* @param Application $app
* @param CollectionRepositoryFactory $collectionRepositoryFactory * @param CollectionRepositoryFactory $collectionRepositoryFactory
* @param CollectionReferenceRepository $referenceRepository * @param CollectionReferenceRepository $referenceRepository
*/ */
public function __construct( public function __construct(
Application $app,
CollectionRepositoryFactory $collectionRepositoryFactory, CollectionRepositoryFactory $collectionRepositoryFactory,
CollectionReferenceRepository $referenceRepository CollectionReferenceRepository $referenceRepository
) { ) {
$this->application = $app;
$this->repositoryFactory = $collectionRepositoryFactory; $this->repositoryFactory = $collectionRepositoryFactory;
$this->referenceRepository = $referenceRepository; $this->referenceRepository = $referenceRepository;
} }
@@ -70,6 +79,11 @@ class CollectionRepositoryRegistry
public function purgeRegistry() public function purgeRegistry()
{ {
$this->baseIdMap = null; $this->baseIdMap = null;
$appBox = $this->application->getApplicationBox();
\phrasea::reset_baseDatas($appBox);
\phrasea::reset_sbasDatas($appBox);
} }
private function loadBaseIdMap() private function loadBaseIdMap()

View File

@@ -162,8 +162,6 @@ class CollectionService
$stmt->execute([':base_id' => $reference->getBaseId()]); $stmt->execute([':base_id' => $reference->getBaseId()]);
$stmt->closeCursor(); $stmt->closeCursor();
$this->app['manipulator.registration']->deleteRegistrationsOnCollection($this);
return; return;
} }

View File

@@ -0,0 +1,110 @@
<?php
namespace Alchemy\Phrasea\Collection\Reference;
class ArrayCacheCollectionReferenceRepository implements CollectionReferenceRepository
{
/**
* @var CollectionReferenceRepository
*/
private $repository;
/**
* @var null|array
*/
private $referenceCache = null;
public function __construct(CollectionReferenceRepository $referenceRepository)
{
$this->repository = $referenceRepository;
}
/**
* @return CollectionReference[]
*/
public function findAll()
{
if ($this->referenceCache === null) {
$this->referenceCache = $this->repository->findAll();
}
return $this->referenceCache;
}
/**
* @param int $databoxId
* @return CollectionReference[]
*/
public function findAllByDatabox($databoxId)
{
$references = $this->findAll();
$found = array();
foreach ($references as $reference) {
if ($reference->getDataboxId() == $databoxId) {
$found[$reference->getBaseId()] = $reference;
}
}
return $found;
}
/**
* @param int $baseId
* @return CollectionReference|null
*/
public function find($baseId)
{
$references = $this->findAll();
if (isset($references[$baseId])) {
return $references[$baseId];
}
return null;
}
/**
* @param int $databoxId
* @param int $collectionId
* @return CollectionReference|null
*/
public function findByCollectionId($databoxId, $collectionId)
{
$references = $this->findAll();
foreach ($references as $reference) {
if ($reference->getCollectionId() == $collectionId) {
return $reference;
}
}
return null;
}
/**
* @param CollectionReference $reference
* @return void
*/
public function save(CollectionReference $reference)
{
$this->repository->save($reference);
if ($this->referenceCache !== null) {
$this->referenceCache[$reference->getBaseId()] = $reference;
}
}
/**
* @param CollectionReference $reference
* @return void
*/
public function delete(CollectionReference $reference)
{
$this->repository->delete($reference);
if ($this->referenceCache !== null) {
unset($this->referenceCache[$reference->getBaseId()]);
}
}
}

View File

@@ -33,4 +33,10 @@ interface CollectionReferenceRepository
* @return void * @return void
*/ */
public function save(CollectionReference $reference); public function save(CollectionReference $reference);
/**
* @param CollectionReference $reference
* @return void
*/
public function delete(CollectionReference $reference);
} }

View File

@@ -31,6 +31,8 @@ class DbalCollectionReferenceRepository implements CollectionReferenceRepository
private static $updateQuery = 'UPDATE bas SET ord = :displayIndex, active = :isActive, aliases = :alias private static $updateQuery = 'UPDATE bas SET ord = :displayIndex, active = :isActive, aliases = :alias
WHERE base_id = :baseId'; WHERE base_id = :baseId';
private static $deleteQuery = 'DELETE FROM bas WHERE base_id = :baseId';
/** /**
* @var Connection * @var Connection
*/ */
@@ -126,6 +128,19 @@ class DbalCollectionReferenceRepository implements CollectionReferenceRepository
} }
} }
/**
* @param CollectionReference $collectionReference
* @throws \Doctrine\DBAL\DBALException
*/
public function delete(CollectionReference $collectionReference)
{
$parameters = [
'baseId' => $collectionReference->getBaseId()
];
$this->connection->executeQuery(self::$deleteQuery, $parameters);
}
/** /**
* @param array $row * @param array $row
* @return CollectionReference * @return CollectionReference

View File

@@ -54,7 +54,16 @@ class ArrayCacheCollectionRepository implements CollectionRepository
$this->collectionRepository->save($collection); $this->collectionRepository->save($collection);
if ($this->collectionCache !== null) { if ($this->collectionCache !== null) {
$this->collectionCache = null; $this->collectionCache[$collection->getCollectionId()] = $collection;
}
}
public function delete(Collection $collection)
{
$this->collectionRepository->delete($collection);
if (isset($this->collectionCache[$collection->getCollectionId()])) {
unset($this->collectionCache[$collection->getCollectionId()]);
} }
} }
} }

View File

@@ -96,6 +96,15 @@ final class CachedCollectionRepository implements CollectionRepository
$this->cache->delete($cacheKey); $this->cache->delete($cacheKey);
} }
public function delete(Collection $collection)
{
$this->repository->delete($collection);
$cacheKey = hash('sha256', $this->cacheKey);
$this->cache->delete($cacheKey);
}
private function putInCache($key, $value) private function putInCache($key, $value)
{ {
$this->cache->save($key, $value); $this->cache->save($key, $value);

View File

@@ -20,6 +20,8 @@ class DbalCollectionRepository implements CollectionRepository
label_de = :labelDe, label_nl = :labelNl, prefs = :preferences, logo = :logo, label_de = :labelDe, label_nl = :labelNl, prefs = :preferences, logo = :logo,
majLogo = :logoTimestamp, pub_wm = :publicWatermark WHERE coll_id = :collectionId'; majLogo = :logoTimestamp, pub_wm = :publicWatermark WHERE coll_id = :collectionId';
private static $deleteQuery = 'DELETE FROM coll WHERE coll_id = :collectionId';
/** /**
* @var int * @var int
*/ */
@@ -150,4 +152,13 @@ class DbalCollectionRepository implements CollectionRepository
$collection->setCollectionId($this->connection->lastInsertId()); $collection->setCollectionId($this->connection->lastInsertId());
} }
} }
public function delete(Collection $collection)
{
$parameters = [
'collectionId' => $collection->getCollectionId()
];
$this->connection->executeQuery(self::$deleteQuery, $parameters);
}
} }

View File

@@ -17,6 +17,7 @@ use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry;
use Alchemy\Phrasea\Collection\Factory\ArrayCachedCollectionRepositoryFactory; use Alchemy\Phrasea\Collection\Factory\ArrayCachedCollectionRepositoryFactory;
use Alchemy\Phrasea\Collection\Factory\CachedCollectionRepositoryFactory; use Alchemy\Phrasea\Collection\Factory\CachedCollectionRepositoryFactory;
use Alchemy\Phrasea\Collection\Factory\DbalCollectionRepositoryFactory; use Alchemy\Phrasea\Collection\Factory\DbalCollectionRepositoryFactory;
use Alchemy\Phrasea\Collection\Reference\ArrayCacheCollectionReferenceRepository;
use Alchemy\Phrasea\Collection\Reference\DbalCollectionReferenceRepository; use Alchemy\Phrasea\Collection\Reference\DbalCollectionReferenceRepository;
use Alchemy\Phrasea\Collection\Repository\ArrayCacheCollectionRepository; use Alchemy\Phrasea\Collection\Repository\ArrayCacheCollectionRepository;
use Alchemy\Phrasea\Collection\Repository\CachedCollectionRepository; use Alchemy\Phrasea\Collection\Repository\CachedCollectionRepository;
@@ -150,7 +151,9 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
}); });
$app['repo.collection-references'] = $app->share(function (PhraseaApplication $app) { $app['repo.collection-references'] = $app->share(function (PhraseaApplication $app) {
return new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection()); $repository = new DbalCollectionReferenceRepository($app->getApplicationBox()->get_connection());
return new ArrayCacheCollectionReferenceRepository($repository);
}); });
$app['repo.collections-registry'] = $app->share(function (PhraseaApplication $app) { $app['repo.collections-registry'] = $app->share(function (PhraseaApplication $app) {
@@ -172,7 +175,7 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
$repositoryFactory = new ArrayCachedCollectionRepositoryFactory($repositoryFactory); $repositoryFactory = new ArrayCachedCollectionRepositoryFactory($repositoryFactory);
return new CollectionRepositoryRegistry($repositoryFactory, $app['repo.collection-references']); return new CollectionRepositoryRegistry($app, $repositoryFactory, $app['repo.collection-references']);
}); });
} }

View File

@@ -302,6 +302,14 @@ class collection implements ThumbnailedElement
); );
} }
/**
* @return CollectionVO
*/
public function getCollection()
{
return $this->collectionVO;
}
/** /**
* @return CollectionReference * @return CollectionReference
*/ */
@@ -642,6 +650,8 @@ class collection implements ThumbnailedElement
$this->collectionService->delete($this->databox, $this->collectionVO, $this->reference); $this->collectionService->delete($this->databox, $this->collectionVO, $this->reference);
$this->getCollectionRepository()->delete($this->collectionVO); $this->getCollectionRepository()->delete($this->collectionVO);
$this->app['manipulator.registration']->deleteRegistrationsOnCollection($this);
$this->app['repo.collections-registry']->purgeRegistry(); $this->app['repo.collections-registry']->purgeRegistry();
} }
@@ -654,6 +664,8 @@ class collection implements ThumbnailedElement
$this->collectionService->unmountCollection($this->reference); $this->collectionService->unmountCollection($this->reference);
$this->getReferenceRepository()->delete($this->reference); $this->getReferenceRepository()->delete($this->reference);
$this->app['manipulator.registration']->deleteRegistrationsOnCollection($this);
$this->app['repo.collections-registry']->purgeRegistry(); $this->app['repo.collections-registry']->purgeRegistry();
return $this; return $this;

View File

@@ -10,6 +10,8 @@
*/ */
use Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application;
use Alchemy\Phrasea\Collection\CollectionRepositoryRegistry;
use Alchemy\Phrasea\Collection\Reference\CollectionReferenceRepository;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
class phrasea class phrasea
@@ -98,49 +100,28 @@ class phrasea
public static function sbasFromBas(Application $app, $base_id) public static function sbasFromBas(Application $app, $base_id)
{ {
if (!self::$_bas2sbas) { /** @var CollectionReferenceRepository $repository */
try { $repository = $app['repo.collection-references'];
$data = $app->getApplicationBox()->get_data_from_cache(self::CACHE_SBAS_FROM_BAS); $reference = $repository->find($base_id);
if (!$data) {
throw new \Exception('Could not get sbas from cache');
}
self::$_bas2sbas = $data;
} catch (\Exception $e) {
$sql = 'SELECT base_id, sbas_id FROM bas';
$stmt = $app->getApplicationBox()->get_connection()->prepare($sql);
$stmt->execute();
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
foreach ($rs as $row) { if ($reference) {
self::$_bas2sbas[$row['base_id']] = (int) $row['sbas_id']; return $reference->getDataboxId();
}
$app->getApplicationBox()->set_data_to_cache(self::$_bas2sbas, self::CACHE_SBAS_FROM_BAS);
}
} }
return isset(self::$_bas2sbas[$base_id]) ? self::$_bas2sbas[$base_id] : false; return false;
} }
public static function baseFromColl($sbas_id, $coll_id, Application $app) public static function baseFromColl($sbas_id, $coll_id, Application $app)
{ {
if (!self::$_coll2bas) { /** @var CollectionReferenceRepository $repository */
$conn = $app->getApplicationBox()->get_connection(); $repository = $app['repo.collection-references'];
$sql = 'SELECT base_id, server_coll_id, sbas_id FROM bas'; $reference = $repository->findByCollectionId($sbas_id, $coll_id);
$stmt = $conn->prepare($sql);
$stmt->execute();
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
foreach ($rs as $row) { if ($reference) {
if (!isset(self::$_coll2bas[$row['sbas_id']])) return $reference->getBaseId();
self::$_coll2bas[$row['sbas_id']] = [];
self::$_coll2bas[$row['sbas_id']][$row['server_coll_id']] = (int) $row['base_id'];
}
} }
return isset(self::$_coll2bas[$sbas_id][$coll_id]) ? self::$_coll2bas[$sbas_id][$coll_id] : false; return false;
} }
public static function reset_baseDatas(appbox $appbox) public static function reset_baseDatas(appbox $appbox)
@@ -175,20 +156,15 @@ class phrasea
public static function collFromBas(Application $app, $base_id) public static function collFromBas(Application $app, $base_id)
{ {
if (!self::$_bas2coll) { /** @var CollectionReferenceRepository $repository */
$conn = $app->getApplicationBox()->get_connection(); $repository = $app['repo.collection-references'];
$sql = 'SELECT base_id, server_coll_id FROM bas'; $reference = $repository->find($base_id);
$stmt = $conn->prepare($sql);
$stmt->execute();
$rs = $stmt->fetchAll(PDO::FETCH_ASSOC);
$stmt->closeCursor();
foreach ($rs as $row) { if ($reference) {
self::$_bas2coll[$row['base_id']] = (int) $row['server_coll_id']; return $reference->getCollectionId();
}
} }
return isset(self::$_bas2coll[$base_id]) ? self::$_bas2coll[$base_id] : false; return false;
} }
public static function sbas_names($sbas_id, Application $app) public static function sbas_names($sbas_id, Application $app)
@@ -234,27 +210,28 @@ class phrasea
public static function bas_labels($base_id, Application $app) public static function bas_labels($base_id, Application $app)
{ {
if (!self::$_bas_labels) { /** @var CollectionReferenceRepository $repository */
try { $referenceRepository = $app['repo.collection-references'];
self::$_bas_labels = $app->getApplicationBox()->get_data_from_cache(self::CACHE_BAS_LABELS); $reference = $referenceRepository->find($base_id);
} catch (\Exception $e) {
foreach ($app->getDataboxes() as $databox) {
foreach ($databox->get_collections() as $collection) {
self::$_bas_labels[$collection->get_base_id()] = [
'fr' => $collection->get_label('fr'),
'en' => $collection->get_label('en'),
'de' => $collection->get_label('de'),
'nl' => $collection->get_label('nl'),
];
}
}
$app->getApplicationBox()->set_data_to_cache(self::$_bas_labels, self::CACHE_BAS_LABELS); if (! $reference) {
} return 'Unknown collection';
} }
if (isset(self::$_bas_labels[$base_id]) && isset(self::$_bas_labels[$base_id][$app['locale']])) { /** @var CollectionRepositoryRegistry $collectionRepositoryRegistry */
return self::$_bas_labels[$base_id][$app['locale']]; $collectionRepositoryRegistry = $app['repo.collections-registry'];
$collectionRepository = $collectionRepositoryRegistry->getRepositoryByDatabox($reference->getDataboxId());
$collection = $collectionRepository->find($reference->getCollectionId());
if (! $collection) {
throw new \RuntimeException('Missing collection ' . $base_id . '.');
}
$labels = $collection->getCollection()->getLabels();
if (isset($labels[$app['locale']])) {
return $labels[$app['locale']];
} }
return 'Unknown collection'; return 'Unknown collection';