Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: decrease query count by cacheing some RDF property fields #1085

Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions config/default/PropertyCache.conf.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

/**
* The default cache implementation
*/

use oat\generis\persistence\PersistenceManager;
use oat\oatbox\cache\KeyValueCache;
use oat\oatbox\service\ServiceFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

return new class implements ServiceFactoryInterface {
public function __invoke(ServiceLocatorInterface $serviceLocator)
{
try {
$serviceLocator
->get(PersistenceManager::SERVICE_ID)
->getPersistenceById('redis');

return new KeyValueCache([
KeyValueCache::OPTION_PERSISTENCE => 'redis'
]);
} catch (Exception $e) {
return new KeyValueCache([
KeyValueCache::OPTION_PERSISTENCE => 'cache'
]);
}
}
};
205 changes: 139 additions & 66 deletions core/kernel/classes/class.Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use oat\generis\model\GenerisRdf;
use oat\generis\model\OntologyRdfs;
use oat\generis\model\resource\DependsOnPropertyCollection;
use oat\generis\model\kernel\persistence\Cache;

/**
* uriProperty must be a valid property otherwis return false, add this as a
Expand Down Expand Up @@ -86,23 +87,6 @@ class core_kernel_classes_Property extends core_kernel_classes_Resource
*/
public $widget = false;

/**
* Short description of attribute lgDependent
*
* @access public
* @var boolean
*/
public $lgDependent = false;


/**
* Short description of attribute multiple
*
* @access public
* @var boolean
*/
public $multiple = false;

/** @var DependsOnPropertyCollection */
private $dependsOnPropertyCollection;

Expand All @@ -115,7 +99,6 @@ private function getImplementation()
return $this->getModel()->getRdfsInterface()->getPropertyImplementation();
}


/**
* constructor
*
Expand All @@ -128,9 +111,6 @@ private function getImplementation()
public function __construct($uri, $debug = '')
{
parent::__construct($uri, $debug);

$this->lgDependent = null;
$this->multiple = null;
}

/**
Expand All @@ -154,18 +134,15 @@ public function feed()
*/
public function getDomain()
{
$returnValue = null;
if (is_null($this->domain)) {
$this->domain = new core_kernel_classes_ContainerCollection(new common_Object(__METHOD__));
$domainValues = $this->getPropertyValues($this->getProperty(OntologyRdfs::RDFS_DOMAIN));
foreach ($domainValues as $domainValue) {
$this->domain->add($this->getClass($domainValue));
}
}
$returnValue = $this->domain;


return $returnValue;
return $this->domain;
}

public function getRelatedClass(): ?core_kernel_classes_Class
Expand Down Expand Up @@ -231,7 +208,7 @@ public function getRange()
$rangeProperty = $this->getProperty(OntologyRdfs::RDFS_RANGE);
$rangeValues = $this->getPropertyValues($rangeProperty);

if (sizeOf($rangeValues) > 0) {
if (!empty($rangeValues)) {
$returnValue = $this->getClass($rangeValues[0]);
}
$this->range = $returnValue;
Expand All @@ -248,14 +225,13 @@ public function getRange()
* @param Class class
* @return boolean
*/
public function setRange(core_kernel_classes_Class $class)
public function setRange(core_kernel_classes_Class $class): bool
{
$returnValue = (bool) false;
$returnValue = $this->getImplementation()->setRange($this, $class);
if ($returnValue) {
$this->range = $class;
}
return (bool) $returnValue;
return (bool)$returnValue;
}

public function getAlias(): ?string
Expand Down Expand Up @@ -326,26 +302,38 @@ public function getWidget()
* @author Cédric Alfonsi, <cedric.alfonsi@tudor.lu>
* @return boolean
*/
public function isLgDependent()
public function isLgDependent(): bool
{
if (is_null($this->lgDependent)) {
$this->lgDependent = $this->getImplementation()->isLgDependent($this);
if (
$this->supportCache()
&& $this->getModel()->getCache()->has($this->generateIsLgDependentKey($this->getUri()))
) {
return (bool)$this->getModel()->getCache()->get($this->generateIsLgDependentKey($this->getUri()));
}

$isLgDependent = $this->getImplementation()->isLgDependent($this);

if ($this->supportCache()) {
$this->getModel()->getCache()->set($this->generateIsLgDependentKey($this->getUri()), $isLgDependent);
}
return (bool) $this->lgDependent;

return $isLgDependent;
}

/**
* Set mannually if a property can be translated
*
* @access public
* @author Cédric Alfonsi, <cedric.alfonsi@tudor.lu>
* @param boolean isLgDependent
* @return mixed
*/
public function setLgDependent($isLgDependent)
public function setLgDependent($isLgDependent): void
{
$this->getImplementation()->setLgDependent($this, $isLgDependent);
$this->lgDependent = $isLgDependent;

if ($this->supportCache()) {
$this->getModel()->getCache()->set($this->generateIsLgDependentKey($this->getUri()), $isLgDependent);
}
}

/**
Expand All @@ -355,24 +343,29 @@ public function setLgDependent($isLgDependent)
* @author Cédric Alfonsi, <cedric.alfonsi@tudor.lu>
* @return boolean
*/
public function isMultiple()
public function isMultiple(): bool
{
$returnValue = (bool) false;
if (
$this->supportCache()
&& $this->getModel()->getCache()->has($this->generateIsMultipleKey($this->getUri()))
) {
return (bool)$this->getModel()->getCache()->get($this->generateIsMultipleKey($this->getUri()));
}

if (is_null($this->multiple)) {
$multipleProperty = $this->getProperty(GenerisRdf::PROPERTY_MULTIPLE);
$multiple = $this->getOnePropertyValue($multipleProperty);
$multipleProperty = $this->getProperty(GenerisRdf::PROPERTY_MULTIPLE);
$multiple = $this->getOnePropertyValue($multipleProperty);

if (is_null($multiple)) {
$returnValue = false;
} else {
$returnValue = ($multiple->getUri() == GenerisRdf::GENERIS_TRUE);
}
$this->multiple = $returnValue;
if (is_null($multiple)) {
$returnValue = false;
} else {
$returnValue = ($multiple->getUri() == GenerisRdf::GENERIS_TRUE);
}

$returnValue = $this->multiple;
return (bool) $returnValue;
if ($this->supportCache()) {
$this->getModel()->getCache()->set($this->generateIsMultipleKey($this->getUri()), $returnValue);
}

return $returnValue;
}

/**
Expand All @@ -381,14 +374,15 @@ public function isMultiple()
*
* @access public
* @author Cédric Alfonsi, <cedric.alfonsi@tudor.lu>
* @param boolean isMultiple
* @return mixed
*/
public function setMultiple($isMultiple)
public function setMultiple($isMultiple): void
{

$this->getImplementation()->setMultiple($this, $isMultiple);
$this->multiple = $isMultiple;

if ($this->supportCache()) {
$this->getModel()->getCache()->set($this->generateIsMultipleKey($this->getUri()), $isMultiple);
}
}

/**
Expand All @@ -406,17 +400,29 @@ public function isRelationship(): bool
return false;
}

$range = $this->getRange();

return $range
&& !in_array(
$range->getUri(),
[
OntologyRdfs::RDFS_LITERAL,
GenerisRdf::CLASS_GENERIS_FILE
],
true
);
$model = $this->getModel();

if ($this->supportCache() && $model->getCache()->has($this->generateIsRelationshipKey($this->getUri()))) {
$isRelationship = (bool)$model->getCache()->get($this->generateIsRelationshipKey($this->getUri()));
} else {
$range = $this->getRange();

$isRelationship = $range
&& !in_array(
$range->getUri(),
[
OntologyRdfs::RDFS_LITERAL,
GenerisRdf::CLASS_GENERIS_FILE
],
true
);

if ($this->supportCache()) {
$this->getModel()->getCache()->set($this->generateIsRelationshipKey($this->getUri()), $isRelationship);
}
}

return $isRelationship;
}

/**
Expand All @@ -427,10 +433,77 @@ public function isRelationship(): bool
* @param boolean deleteReference
* @return boolean
*/
public function delete($deleteReference = false)
public function delete($deleteReference = false): bool
{
$returnValue = (bool) false;
$returnValue = $this->getImplementation()->delete($this, $deleteReference);

$this->clearCachedValues();

return (bool) $returnValue;
}

/**
* Clear property cached data
*/
public function clearCachedValues(): void
{
if (!$this->supportCache()) {
return;
}

/** @var \oat\oatbox\cache\SimpleCache $cache */
$cache = $this->getModel()->getCache();
$isRelationshipKey = $this->generateIsRelationshipKey($this->getUri());
$isMultipleKey = $this->generateIsMultipleKey($this->getUri());
$isLgDependentKey = $this->generateIsLgDependentKey($this->getUri());

if ($cache->has($isRelationshipKey)) {
$cache->delete($isRelationshipKey);
}

if ($cache->has($isMultipleKey)) {
$cache->delete($isMultipleKey);
}

if ($cache->has($isLgDependentKey)) {
$cache->delete($isLgDependentKey);
}
}

/**
* Warmup property cached data
*/
public function warmupCachedValues(): void
{
if (!$this->supportCache()) {
return;
}

$this->isRelationship();
$this->isMultiple();
$this->isLgDependent();
}

protected function generateIsRelationshipKey(string $uri): string
{
return sprintf('PropIsRelationship_%s', $uri);
}

protected function generateIsLgDependentKey(string $uri): string
{
return sprintf('PropIsLgDependent_%s', $uri);
}

protected function generateIsMultipleKey(string $uri): string
{
return sprintf('PropIsMultiple_%s', $uri);
}

/**
* @return bool
*/
protected function supportCache(): bool
{
return $this->getModel() instanceof Cache;
}
}
3 changes: 1 addition & 2 deletions core/kernel/classes/class.Resource.php
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,8 @@ public function setComment($comment)
*/
public function getPropertyValues(core_kernel_classes_Property $property, $options = [])
{
$returnValue = [];
$returnValue = $this->getImplementation()->getPropertyValues($this, $property, $options);
return (array) $returnValue;
return $returnValue;
}

/**
Expand Down
28 changes: 28 additions & 0 deletions core/kernel/persistence/Cache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?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\model\kernel\persistence;

use oat\oatbox\cache\SimpleCache;

interface Cache
augustas marked this conversation as resolved.
Show resolved Hide resolved
{
public function getCache(): SimpleCache;
}
Loading
Loading