Updated ClientManager to implement the cache system.
This commit is contained in:
parent
d346c4d23d
commit
6bbf9c3dab
5 changed files with 256 additions and 159 deletions
|
@ -38,8 +38,8 @@
|
||||||
*/
|
*/
|
||||||
public static function main(array $args=[]): void
|
public static function main(array $args=[]): void
|
||||||
{
|
{
|
||||||
tm::initialize(TamerMode::CLIENT, Configuration::getTamerLibConfiguration()->getServerConfiguration());
|
tm::initialize(TamerMode::CLIENT);
|
||||||
tm::createWorker(Configuration::getTamerLibConfiguration()->getCliWorkers(), FederationLib::getSubprocessorPath());
|
tm::createWorker(Configuration::getTamerLibConfiguration()->getCliWorkers(), FederationLib::getSubprocessPath());
|
||||||
|
|
||||||
self::$federation_lib = new FederationLib();
|
self::$federation_lib = new FederationLib();
|
||||||
|
|
||||||
|
|
|
@ -313,4 +313,40 @@
|
||||||
{
|
{
|
||||||
return (int)self::getConfiguration()['cache_system']['error_connection_priority'];
|
return (int)self::getConfiguration()['cache_system']['error_connection_priority'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function getObjectCacheEnabled(string $name): bool
|
||||||
|
{
|
||||||
|
return (bool)self::getConfiguration()['cache_system']['cache'][sprintf('%s_enabled', $name)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public static function getObjectCacheTtl(string $name): int
|
||||||
|
{
|
||||||
|
return (int)self::getConfiguration()['cache_system']['cache'][sprintf('%s_ttl', $name)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getObjectCacheServerPreference(string $name): string
|
||||||
|
{
|
||||||
|
return self::getConfiguration()['cache_system']['cache'][sprintf('%s_server_preference', $name)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getObjectCacheServerFallback(string $name): string
|
||||||
|
{
|
||||||
|
return self::getConfiguration()['cache_system']['cache'][sprintf('%s_server_fallback', $name)];
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use FederationLib\Classes\Configuration;
|
use FederationLib\Classes\Configuration;
|
||||||
use FederationLib\Enums\Misc;
|
|
||||||
use FederationLib\Enums\Standard\ErrorCodes;
|
use FederationLib\Enums\Standard\ErrorCodes;
|
||||||
use FederationLib\Enums\Standard\Methods;
|
use FederationLib\Enums\Standard\Methods;
|
||||||
use FederationLib\Exceptions\DatabaseException;
|
use FederationLib\Exceptions\DatabaseException;
|
||||||
|
@ -17,7 +16,6 @@
|
||||||
use FederationLib\Objects\Client;
|
use FederationLib\Objects\Client;
|
||||||
use FederationLib\Objects\ResolvedIdentity;
|
use FederationLib\Objects\ResolvedIdentity;
|
||||||
use FederationLib\Objects\Standard\ClientIdentity;
|
use FederationLib\Objects\Standard\ClientIdentity;
|
||||||
use LogLib\Log;
|
|
||||||
use TamerLib\Enums\TamerMode;
|
use TamerLib\Enums\TamerMode;
|
||||||
use TamerLib\tm;
|
use TamerLib\tm;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
@ -52,15 +50,23 @@
|
||||||
$this->client_manager->registerFunctions();
|
$this->client_manager->registerFunctions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function getSubprocessPath(): string
|
||||||
|
{
|
||||||
|
return __DIR__ . DIRECTORY_SEPARATOR . 'subproc';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the permission role from the given identity and attempts to check if the identity has the
|
* Resolves the permission role from the given identity and attempts to check if the identity has the
|
||||||
* required permission to perform the given method
|
* required permission to perform the given method
|
||||||
*
|
*
|
||||||
* @param ClientIdentity|null $identity
|
* @param ClientIdentity|null $identity
|
||||||
* @return ResolvedIdentity
|
|
||||||
* @throws AccessDeniedException
|
* @throws AccessDeniedException
|
||||||
* @throws ClientNotFoundException
|
* @throws ClientNotFoundException
|
||||||
* @throws InternalServerException
|
* @throws InternalServerException
|
||||||
|
* @return ResolvedIdentity
|
||||||
*/
|
*/
|
||||||
private function resolveIdentity(?ClientIdentity $identity): ResolvedIdentity
|
private function resolveIdentity(?ClientIdentity $identity): ResolvedIdentity
|
||||||
{
|
{
|
||||||
|
@ -75,11 +81,12 @@
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
$client = tm::waitFor($get_client);
|
$client = tm::waitFor($get_client);
|
||||||
|
tm::dof('client_updateLastSeen');
|
||||||
}
|
}
|
||||||
catch(ClientNotFoundException $e)
|
catch(ClientNotFoundException $e)
|
||||||
{
|
{
|
||||||
tm::clear();
|
tm::clear();
|
||||||
throw new ClientNotFoundException('The client you are trying to access does not exist', $e);
|
throw new ClientNotFoundException('Invalid client UUID or client does not exist', $e);
|
||||||
}
|
}
|
||||||
catch(Exception|Throwable $e)
|
catch(Exception|Throwable $e)
|
||||||
{
|
{
|
||||||
|
@ -87,7 +94,6 @@
|
||||||
throw new InternalServerException('There was an error while trying to access the client', $e);
|
throw new InternalServerException('There was an error while trying to access the client', $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
tm::dof('client_updateLastSeen');
|
|
||||||
return new ResolvedIdentity($client, $peer);
|
return new ResolvedIdentity($client, $peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,12 +264,4 @@
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public static function getSubprocessorPath(): string
|
|
||||||
{
|
|
||||||
return __DIR__ . DIRECTORY_SEPARATOR . 'subproc';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -6,13 +6,13 @@
|
||||||
use Exception;
|
use Exception;
|
||||||
use FederationLib\Classes\Configuration;
|
use FederationLib\Classes\Configuration;
|
||||||
use FederationLib\Classes\Database;
|
use FederationLib\Classes\Database;
|
||||||
use FederationLib\Classes\Redis;
|
|
||||||
use FederationLib\Classes\Security;
|
use FederationLib\Classes\Security;
|
||||||
use FederationLib\Classes\Utilities;
|
use FederationLib\Classes\Utilities;
|
||||||
use FederationLib\Classes\Validate;
|
use FederationLib\Classes\Validate;
|
||||||
use FederationLib\Enums\DatabaseTables;
|
use FederationLib\Enums\DatabaseTables;
|
||||||
use FederationLib\Enums\FilterOrder;
|
use FederationLib\Enums\FilterOrder;
|
||||||
use FederationLib\Enums\Filters\ListClientsFilter;
|
use FederationLib\Enums\Filters\ListClientsFilter;
|
||||||
|
use FederationLib\Enums\Misc;
|
||||||
use FederationLib\Exceptions\DatabaseException;
|
use FederationLib\Exceptions\DatabaseException;
|
||||||
use FederationLib\Exceptions\Standard\ClientNotFoundException;
|
use FederationLib\Exceptions\Standard\ClientNotFoundException;
|
||||||
use FederationLib\Exceptions\Standard\InvalidClientDescriptionException;
|
use FederationLib\Exceptions\Standard\InvalidClientDescriptionException;
|
||||||
|
@ -42,6 +42,11 @@
|
||||||
$this->federationLib = $federationLib;
|
$this->federationLib = $federationLib;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers functions to the TamerLib instance, if applicable
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
public function registerFunctions(): void
|
public function registerFunctions(): void
|
||||||
{
|
{
|
||||||
if(tm::getMode() !== TamerMode::WORKER)
|
if(tm::getMode() !== TamerMode::WORKER)
|
||||||
|
@ -54,7 +59,6 @@
|
||||||
tm::addFunction('client_changeClientName', [$this, 'changeClientName']);
|
tm::addFunction('client_changeClientName', [$this, 'changeClientName']);
|
||||||
tm::addFunction('client_changeClientDescription', [$this, 'changeClientDescription']);
|
tm::addFunction('client_changeClientDescription', [$this, 'changeClientDescription']);
|
||||||
tm::addFunction('client_changeClientPermissionRole', [$this, 'changeClientPermissionRole']);
|
tm::addFunction('client_changeClientPermissionRole', [$this, 'changeClientPermissionRole']);
|
||||||
tm::addFunction('client_updateClient', [$this, 'updateClient']);
|
|
||||||
tm::addFunction('client_updateLastSeen', [$this, 'updateLastSeen']);
|
tm::addFunction('client_updateLastSeen', [$this, 'updateLastSeen']);
|
||||||
tm::addFunction('client_listClients', [$this, 'listClients']);
|
tm::addFunction('client_listClients', [$this, 'listClients']);
|
||||||
tm::addFunction('client_getTotalClients', [$this, 'getTotalClients']);
|
tm::addFunction('client_getTotalClients', [$this, 'getTotalClients']);
|
||||||
|
@ -82,12 +86,10 @@
|
||||||
{
|
{
|
||||||
$name = Utilities::generateName(4);
|
$name = Utilities::generateName(4);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(!Validate::clientName($name))
|
||||||
{
|
{
|
||||||
if(!Validate::clientName($name))
|
throw new InvalidClientNameException(sprintf('Invalid client name: %s', $name));
|
||||||
{
|
|
||||||
throw new InvalidClientNameException(sprintf('Invalid client name: %s', $name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if($description !== null && strlen($description) > 128)
|
if($description !== null && strlen($description) > 128)
|
||||||
|
@ -129,6 +131,29 @@
|
||||||
$client_uuid = $client_uuid->getUuid();
|
$client_uuid = $client_uuid->getUuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use the cache first if it's enabled
|
||||||
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($client_uuid))
|
||||||
|
{
|
||||||
|
$client = Client::fromArray($redis->hGetAll($client_uuid));
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Loaded client object %s from cache', $client_uuid));
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to load client object %s from cache: %s', $client_uuid, $e->getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
$qb = Database::getConnection()->createQueryBuilder();
|
||||||
$qb->select('*');
|
$qb->select('*');
|
||||||
$qb->from(DatabaseTables::CLIENTS);
|
$qb->from(DatabaseTables::CLIENTS);
|
||||||
|
@ -156,6 +181,30 @@
|
||||||
throw new DatabaseException('Failed to get Client: ' . $e->getMessage(), $e);
|
throw new DatabaseException('Failed to get Client: ' . $e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store the record in the cache if caching is enabled.
|
||||||
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
$redis->hMSet($client->getUuid(), $client->toArray());
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis->expire($client->getUuid(), Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Cached client object %s', $client->getUuid()));
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to cache client object %s: %s', $client->getUuid(), $e->getMessage()), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $client;
|
return $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,20 +229,19 @@
|
||||||
{
|
{
|
||||||
$name = Utilities::generateName(4);
|
$name = Utilities::generateName(4);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if(!Validate::clientName($name))
|
||||||
{
|
{
|
||||||
if(!Validate::clientName($name))
|
throw new InvalidClientNameException(sprintf('Invalid client name: %s', $name));
|
||||||
{
|
|
||||||
throw new InvalidClientNameException(sprintf('Invalid client name: %s', $name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$update_timestamp = time();
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
$qb = Database::getConnection()->createQueryBuilder();
|
||||||
$qb->update(DatabaseTables::CLIENTS);
|
$qb->update(DatabaseTables::CLIENTS);
|
||||||
$qb->set('name', ':name');
|
$qb->set('name', ':name');
|
||||||
$qb->setParameter('name', $name);
|
$qb->setParameter('name', $name);
|
||||||
$qb->set('updated_timestamp', ':updated_timestamp');
|
$qb->set('updated_timestamp', ':updated_timestamp');
|
||||||
$qb->setParameter('updated_timestamp', time(), ParameterType::INTEGER);
|
$qb->setParameter('updated_timestamp', $update_timestamp, ParameterType::INTEGER);
|
||||||
$qb->where('uuid = :uuid');
|
$qb->where('uuid = :uuid');
|
||||||
$qb->setParameter('uuid', $client_uuid);
|
$qb->setParameter('uuid', $client_uuid);
|
||||||
$qb->setMaxResults(1);
|
$qb->setMaxResults(1);
|
||||||
|
@ -212,6 +260,34 @@
|
||||||
throw new ClientNotFoundException($client_uuid);
|
throw new ClientNotFoundException($client_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the record in redis if caching is enabled
|
||||||
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($client_uuid))
|
||||||
|
{
|
||||||
|
$redis->hSet($client_uuid, 'name', $name);
|
||||||
|
$redis->hSet($client_uuid, 'updated_timestamp', $update_timestamp);
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis->expire($client_uuid, Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Updated client object %s <%s> in cache', $client_uuid, 'name'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to update client object %s in cache: %s', $client_uuid, $e->getMessage()), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log::verbose('net.nosial.federationlib', sprintf('Changed client name for client %s to %s', $client_uuid, $name));
|
Log::verbose('net.nosial.federationlib', sprintf('Changed client name for client %s to %s', $client_uuid, $name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,12 +313,13 @@
|
||||||
throw new InvalidClientDescriptionException(sprintf('Invalid client description: %s', $description));
|
throw new InvalidClientDescriptionException(sprintf('Invalid client description: %s', $description));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$updated_timestamp = time();
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
$qb = Database::getConnection()->createQueryBuilder();
|
||||||
$qb->update(DatabaseTables::CLIENTS);
|
$qb->update(DatabaseTables::CLIENTS);
|
||||||
$qb->set('description', ':description');
|
$qb->set('description', ':description');
|
||||||
$qb->setParameter('description', $description, (is_null($description) ? ParameterType::NULL : ParameterType::STRING));
|
$qb->setParameter('description', $description, (is_null($description) ? ParameterType::NULL : ParameterType::STRING));
|
||||||
$qb->set('updated_timestamp', ':updated_timestamp');
|
$qb->set('updated_timestamp', ':updated_timestamp');
|
||||||
$qb->setParameter('updated_timestamp', time(), ParameterType::INTEGER);
|
$qb->setParameter('updated_timestamp', $updated_timestamp, ParameterType::INTEGER);
|
||||||
$qb->where('uuid = :uuid');
|
$qb->where('uuid = :uuid');
|
||||||
$qb->setParameter('uuid', $client_uuid);
|
$qb->setParameter('uuid', $client_uuid);
|
||||||
$qb->setMaxResults(1);
|
$qb->setMaxResults(1);
|
||||||
|
@ -261,6 +338,35 @@
|
||||||
throw new ClientNotFoundException($client_uuid);
|
throw new ClientNotFoundException($client_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($client_uuid))
|
||||||
|
{
|
||||||
|
$redis->hSet($client_uuid, 'description', $description);
|
||||||
|
$redis->hSet($client_uuid, 'updated_timestamp', $updated_timestamp);
|
||||||
|
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis->expire($client_uuid, Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Updated client object %s <%s> in cache', $client_uuid, 'description'));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to update client object %s in cache: %s', $client_uuid, $e->getMessage()), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Log::verbose('net.nosial.federationlib', sprintf('Changed client description for client %s to %s', $client_uuid, $description));
|
Log::verbose('net.nosial.federationlib', sprintf('Changed client description for client %s to %s', $client_uuid, $description));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,14 +392,13 @@
|
||||||
throw new InvalidPermissionRoleException(sprintf('Invalid permission role: %s', $permission_role));
|
throw new InvalidPermissionRoleException(sprintf('Invalid permission role: %s', $permission_role));
|
||||||
}
|
}
|
||||||
|
|
||||||
$time = time();
|
$updated_timestamp = time();
|
||||||
|
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
$qb = Database::getConnection()->createQueryBuilder();
|
||||||
$qb->update(DatabaseTables::CLIENTS);
|
$qb->update(DatabaseTables::CLIENTS);
|
||||||
$qb->set('permission_role', ':permission_role');
|
$qb->set('permission_role', ':permission_role');
|
||||||
$qb->setParameter('permission_role', $permission_role, ParameterType::INTEGER);
|
$qb->setParameter('permission_role', $permission_role, ParameterType::INTEGER);
|
||||||
$qb->set('updated_timestamp', ':updated_timestamp');
|
$qb->set('updated_timestamp', ':updated_timestamp');
|
||||||
$qb->setParameter('updated_timestamp', $time, ParameterType::INTEGER);
|
$qb->setParameter('updated_timestamp', $updated_timestamp, ParameterType::INTEGER);
|
||||||
$qb->where('uuid = :uuid');
|
$qb->where('uuid = :uuid');
|
||||||
$qb->setParameter('uuid', $client_uuid);
|
$qb->setParameter('uuid', $client_uuid);
|
||||||
$qb->setMaxResults(1);
|
$qb->setMaxResults(1);
|
||||||
|
@ -312,130 +417,35 @@
|
||||||
throw new ClientNotFoundException($client_uuid);
|
throw new ClientNotFoundException($client_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::verbose('net.nosial.federationlib', sprintf('Changed client permission role for client %s to %s', $client_uuid, $permission_role));
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates a client record in the database, if the client does not exist it will be created.
|
|
||||||
* This function is cache aware, if the client is cached it will only update the changed values.
|
|
||||||
*
|
|
||||||
* @param Client $client
|
|
||||||
* @return void
|
|
||||||
* @throws DatabaseException
|
|
||||||
*/
|
|
||||||
public function updateClient(Client $client): void
|
|
||||||
{
|
|
||||||
$cached_client = null;
|
|
||||||
|
|
||||||
if(Configuration::isRedisCacheClientObjectsEnabled())
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if(Redis::getConnection()?->exists(sprintf('Client<%s>', $client->getUuid())))
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($client_uuid))
|
||||||
{
|
{
|
||||||
$cached_client = Client::fromArray(Redis::getConnection()?->hGetAll(sprintf('Client<%s>', $client->getUuid())));
|
$redis->hSet($client_uuid, 'permission_role', $permission_role);
|
||||||
|
$redis->hSet($client_uuid, 'updated_timestamp', $updated_timestamp);
|
||||||
|
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis->expire($client_uuid, Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Updated client object %s <%s> in cache', $client_uuid, 'permission_role'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
Log::warning('net.nosial.federationlib', sprintf('Failed to get Client from redis: %s', $e->getMessage()));
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to update client object %s in cache: %s', $client_uuid, $e->getMessage()), $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
Log::verbose('net.nosial.federationlib', sprintf('Changed client permission role for client %s to %s', $client_uuid, $permission_role));
|
||||||
$qb->update(DatabaseTables::CLIENTS);
|
|
||||||
$qb->set('updated_timestamp', ':updated_timestamp');
|
|
||||||
$qb->setParameter('updated_timestamp', time());
|
|
||||||
$qb->where('uuid = :uuid');
|
|
||||||
$qb->setParameter('uuid', $client->getUuid());
|
|
||||||
|
|
||||||
if($cached_client instanceof Client)
|
|
||||||
{
|
|
||||||
$data = array_diff($client->toArray(), $cached_client->toArray());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$data = $client->toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach($data as $key => $value)
|
|
||||||
{
|
|
||||||
switch($key)
|
|
||||||
{
|
|
||||||
case 'uuid':
|
|
||||||
case 'created_timestamp':
|
|
||||||
case 'updated_timestamp':
|
|
||||||
case 'seen_timestamp':
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'name':
|
|
||||||
if($value === null || strlen($value) === 0 || !preg_match('/^[a-zA-Z0-9_\-]+$/', $value ))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$qb->set($key, ':' . $key);
|
|
||||||
$qb->setParameter($key, substr($value, 0, 64));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'description':
|
|
||||||
if($value !== null)
|
|
||||||
{
|
|
||||||
$qb->set($key, ':' . $key);
|
|
||||||
$qb->setParameter($key, substr($value, 0, 255));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'enabled':
|
|
||||||
$qb->set($key, ':' . $key);
|
|
||||||
$qb->setParameter($key, $value ? 1 : 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
$qb->set($key, ':' . $key);
|
|
||||||
$qb->setParameter($key, $value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
$qb->executeStatement();
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
throw new DatabaseException('Failed to update client: ' . $e->getMessage(), $e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Configuration::isRedisCacheClientObjectsEnabled())
|
|
||||||
{
|
|
||||||
// Update the differences in the cache
|
|
||||||
if($cached_client instanceof Client)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Redis::getConnection()?->hMSet((string)$client, array_diff($client->toArray(), $cached_client->toArray()));
|
|
||||||
Redis::getConnection()?->expire((string)$client, Configuration::getRedisCacheClientObjectsTTL());
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
Log::warning('net.nosial.federationlib', sprintf('Failed to cache client in redis: %s', $e->getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Redis::getConnection()?->hMSet((string)$client, $client->toArray());
|
|
||||||
Redis::getConnection()?->expire((string)$client, $client->getUuid(), Configuration::getRedisCacheClientObjectsTTL());
|
|
||||||
}
|
|
||||||
catch(Exception $e)
|
|
||||||
{
|
|
||||||
Log::warning('net.nosial.federationlib', sprintf('Failed to cache Client in redis: %s', $e->getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,18 +481,34 @@
|
||||||
throw new DatabaseException('Failed to update last seen timestamp: ' . $e->getMessage(), $e);
|
throw new DatabaseException('Failed to update last seen timestamp: ' . $e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the 'seen_timestamp' only in the hash table in redis
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
if(Configuration::isRedisCacheClientObjectsEnabled())
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Redis::getConnection()?->hSet(sprintf('Client<%s>', $uuid), 'seen_timestamp', $timestamp);
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($uuid))
|
||||||
|
{
|
||||||
|
$redis->hSet($uuid, 'seen_timestamp', $timestamp);
|
||||||
|
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis->expire($uuid, Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::debug(Misc::FEDERATIONLIB, sprintf('Updated client object %s <%s> in cache', $uuid, 'seen_timestamp'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
Log::warning('net.nosial.federationlib', sprintf('Failed to update last seen timestamp in redis: %s', $e->getMessage()));
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to update client object %s in cache: %s', $uuid, $e->getMessage()), $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log::verbose('net.nosial.federationlib', sprintf('Updated last seen timestamp for client %s to %s', $uuid, $timestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -499,9 +525,10 @@
|
||||||
{
|
{
|
||||||
$qb = Database::getConnection()->createQueryBuilder();
|
$qb = Database::getConnection()->createQueryBuilder();
|
||||||
$qb->select(
|
$qb->select(
|
||||||
'uuid', 'enabled', 'name', 'description', 'secret_totp', 'query_permission', 'update_permission',
|
'uuid', 'enabled', 'name', 'description', 'secret_totp', 'permission_role',
|
||||||
'flags', 'created_timestamp', 'updated_timestamp', 'seen_timestamp'
|
'flags', 'created_timestamp', 'updated_timestamp', 'seen_timestamp'
|
||||||
);
|
);
|
||||||
|
|
||||||
$qb->from(DatabaseTables::CLIENTS);
|
$qb->from(DatabaseTables::CLIENTS);
|
||||||
$qb->setFirstResult(($page - 1) * $max_items);
|
$qb->setFirstResult(($page - 1) * $max_items);
|
||||||
$qb->setMaxResults($max_items);
|
$qb->setMaxResults($max_items);
|
||||||
|
@ -511,6 +538,23 @@
|
||||||
throw new DatabaseException('Invalid order: ' . $order);
|
throw new DatabaseException('Invalid order: ' . $order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$redis_client = null;
|
||||||
|
|
||||||
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$redis_client = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch(Exception $e)
|
||||||
|
{
|
||||||
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to connect to Redis server: %s', $e->getMessage()), $e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch($filter)
|
switch($filter)
|
||||||
{
|
{
|
||||||
case ListClientsFilter::CREATED_TIMESTAMP:
|
case ListClientsFilter::CREATED_TIMESTAMP:
|
||||||
|
@ -540,14 +584,27 @@
|
||||||
|
|
||||||
while($row = $result->fetchAssociative())
|
while($row = $result->fetchAssociative())
|
||||||
{
|
{
|
||||||
$clients[] = Client::fromArray($row);
|
$client_object = Client::fromArray($row);
|
||||||
|
|
||||||
|
if($redis_client !== null)
|
||||||
|
{
|
||||||
|
$redis_client->hMSet($client_object->getUuid(), $client_object->toArray());
|
||||||
|
|
||||||
|
if(Configuration::getObjectCacheTTL('client_objects') > 0)
|
||||||
|
{
|
||||||
|
$redis_client->expire($row['uuid'], Configuration::getObjectCacheTTL('client_objects'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$clients[] = $client_object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
throw new DatabaseException('Failed to list clients: ' . $e->getMessage(), $e->getCode(), $e);
|
throw new DatabaseException('Failed to list clients: ' . $e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unset($client);
|
unset($client);
|
||||||
return $clients;
|
return $clients;
|
||||||
}
|
}
|
||||||
|
@ -571,7 +628,7 @@
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
throw new DatabaseException('Failed to get total clients: ' . $e->getMessage(), $e->getCode(), $e);
|
throw new DatabaseException('Failed to get total clients: ' . $e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int)$row['COUNT(uuid)'];
|
return (int)$row['COUNT(uuid)'];
|
||||||
|
@ -614,19 +671,26 @@
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
throw new DatabaseException('Failed to delete client: ' . $e->getMessage(), $e->getCode(), $e);
|
throw new DatabaseException('Failed to delete client: ' . $e->getMessage(), $e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate the cache
|
if(Configuration::isCacheSystemEnabled() && Configuration::getObjectCacheEnabled('client_objects'))
|
||||||
if(Configuration::isRedisCacheClientObjectsEnabled())
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Redis::getConnection()?->del(sprintf('Client<%s>', $uuid));
|
$redis = RedisConnectionManager::getConnection(
|
||||||
|
Configuration::getObjectCacheServerPreference('client_objects'),
|
||||||
|
Configuration::getObjectCacheServerFallback('client_objects')
|
||||||
|
);
|
||||||
|
|
||||||
|
if($redis->exists($uuid))
|
||||||
|
{
|
||||||
|
$redis->del($uuid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch(Exception $e)
|
catch(Exception $e)
|
||||||
{
|
{
|
||||||
Log::warning('net.nosial.federationlib', sprintf('Failed to invalidate client cache in redis: %s', $e->getMessage()));
|
Log::warning(Misc::FEDERATIONLIB, sprintf('Failed to delete client object %s from cache: %s', $uuid, $e->getMessage()), $e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
* @param string|null $fallback
|
* @param string|null $fallback
|
||||||
* @return \Redis
|
* @return \Redis
|
||||||
* @throws CacheConnectionException
|
* @throws CacheConnectionException
|
||||||
* @throws CacheDriverException
|
|
||||||
*/
|
*/
|
||||||
public static function getConnection(?string $name=null, ?string $fallback=null): \Redis
|
public static function getConnection(?string $name=null, ?string $fallback=null): \Redis
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue