From 9dd8c39ce14315a9bbc1ad97f34bf6b5ac168f59 Mon Sep 17 00:00:00 2001 From: netkas Date: Wed, 15 Jan 2025 15:49:53 -0500 Subject: [PATCH] Refactor peer resolution logic and add sync interval setting --- src/Socialbox/Classes/Configuration.php | 4 + .../Configuration/PoliciesConfiguration.php | 12 +++ .../Classes/StandardMethods/ResolvePeer.php | 26 +------ src/Socialbox/Socialbox.php | 77 +++++++++++++++++-- 4 files changed, 88 insertions(+), 31 deletions(-) diff --git a/src/Socialbox/Classes/Configuration.php b/src/Socialbox/Classes/Configuration.php index dd07b14..8ec6a5e 100644 --- a/src/Socialbox/Classes/Configuration.php +++ b/src/Socialbox/Classes/Configuration.php @@ -153,6 +153,10 @@ // answer within the time-frame that the captcha was generated // If expired; client is expected to request for a new captcha which will generate a new random answer. $config->setDefault('policies.image_captcha_expires', 300); + // The amount of time in seconds it takes before a peer's external address is resolved again + // When a peer's external address is resolved, it is cached for this amount of time before resolving again. + // This reduces the amount of times a resolution request is made to the external server. + $config->setDefault('policies.peer_sync_interval', 3600); // Storage configuration $config->setDefault('storage.path', '/etc/socialbox'); // The main path for file storage diff --git a/src/Socialbox/Classes/Configuration/PoliciesConfiguration.php b/src/Socialbox/Classes/Configuration/PoliciesConfiguration.php index bf7de98..8216907 100644 --- a/src/Socialbox/Classes/Configuration/PoliciesConfiguration.php +++ b/src/Socialbox/Classes/Configuration/PoliciesConfiguration.php @@ -7,12 +7,14 @@ private int $maxSigningKeys; private int $sessionInactivityExpires; private int $imageCaptchaExpires; + private int $peerSyncInterval; public function __construct(array $data) { $this->maxSigningKeys = $data['max_signing_keys']; $this->sessionInactivityExpires = $data['session_inactivity_expires']; $this->imageCaptchaExpires = $data['image_captcha_expires']; + $this->peerSyncInterval = $data['peer_sync_interval']; } /** @@ -46,4 +48,14 @@ { return $this->imageCaptchaExpires; } + + /** + * Returns the maximum amount of seconds before the external peer resolve cache is considered expired + * + * @return int + */ + public function getPeerSyncInterval(): int + { + return $this->peerSyncInterval; + } } \ No newline at end of file diff --git a/src/Socialbox/Classes/StandardMethods/ResolvePeer.php b/src/Socialbox/Classes/StandardMethods/ResolvePeer.php index a83ee69..0cdc6bf 100644 --- a/src/Socialbox/Classes/StandardMethods/ResolvePeer.php +++ b/src/Socialbox/Classes/StandardMethods/ResolvePeer.php @@ -41,32 +41,10 @@ throw new StandardException('Peer Address Error: ' . $e->getMessage(), StandardError::RPC_INVALID_ARGUMENTS, $e); } - // If the requested peer resides in the server, resolve the peer internally. - if($peerAddress->getDomain() === Configuration::getInstanceConfiguration()->getDomain()) - { - try - { - $registeredPeer = RegisteredPeerManager::getPeerByAddress($peerAddress); - } - catch (DatabaseOperationException $e) - { - throw new StandardException('There was an unexpected error while trying to resolve the peer internally', StandardError::INTERNAL_SERVER_ERROR, $e); - } - - // Return not found if the returned record is null or if the registered peer isn't enabled - if($registeredPeer === null || !$registeredPeer->isEnabled()) - { - return $rpcRequest->produceError(StandardError::PEER_NOT_FOUND, sprintf('Peer %s not found', $peerAddress->getAddress())); - } - - // Return standard peer representation - return $rpcRequest->produceResponse($registeredPeer->toStandardPeer()); - } - - // Otherwise, resolve the peer from the remote server + // Resolve the peer using the server's peer resolver, this will resolve both internal peers and external peers try { - return $rpcRequest->produceResponse(Socialbox::resolveExternalPeer($peerAddress)); + return $rpcRequest->produceResponse(Socialbox::resolvePeer($peerAddress)); } catch(Exception $e) { diff --git a/src/Socialbox/Socialbox.php b/src/Socialbox/Socialbox.php index 27d0d04..c86e89e 100644 --- a/src/Socialbox/Socialbox.php +++ b/src/Socialbox/Socialbox.php @@ -762,19 +762,82 @@ /** * Resolves an external peer based on the given peer address or string identifier. * - * @param PeerAddress|string $externalPeer The external peer address or string identifier to be resolved. + * @param PeerAddress|string $peer The external peer address or string identifier to be resolved. * @return Peer The resolved external peer after synchronization. */ - public static function resolveExternalPeer(PeerAddress|string $externalPeer): Peer + public static function resolvePeer(PeerAddress|string $peer): Peer { - if($externalPeer instanceof PeerAddress) + if($peer instanceof PeerAddress) { - $externalPeer = $externalPeer->getAddress(); + $peer = $peer->getAddress(); } - $resolvedPeer = self::getExternalSession($externalPeer->getDomain())->resolvePeer($externalPeer); - self::synchronizeExternalPeer($resolvedPeer); - return $resolvedPeer; + try + { + $registeredPeer = RegisteredPeerManager::getPeerByAddress($peer); + } + catch (DatabaseOperationException $e) + { + throw new StandardException('There was an unexpected error while trying to resolve the peer internally', StandardError::INTERNAL_SERVER_ERROR, $e); + } + + // Return not found if the peer was found but is disabled + if($registeredPeer !== null && !$registeredPeer->isEnabled()) + { + throw new StandardException('The requested peer is disabled', StandardError::PEER_NOT_FOUND); + } + + // If the peer was not found but the peer resides in an external server, resolve it + try + { + if($registeredPeer === null && $peer->getDomain() !== Configuration::getInstanceConfiguration()->getDomain()) + { + try + { + $registeredPeer = self::getExternalSession($peer->getDomain())->resolvePeer($peer); + } + catch (DatabaseOperationException $e) + { + throw new StandardException('There was an unexpected error while trying to resolve the peer externally: ' . $e->getMessage(), StandardError::RESOLUTION_FAILED, $e); + } + + // Synchronize the peer for future use + self::synchronizeExternalPeer($registeredPeer); + } + // If the peer was found and the peer does reside in an external server, re-resolve it if necessary + elseif($registeredPeer !== null && $peer->getDomain() !== Configuration::getInstanceConfiguration()->getDomain()) + { + if($registeredPeer->getUpdated()->getTimestamp() < time() - Configuration::getPoliciesConfiguration()->getPeerSyncInterval()) + { + try + { + $registeredPeer = self::getExternalSession($peer->getDomain())->resolvePeer($peer); + } + catch (DatabaseOperationException $e) + { + throw new StandardException('There was an unexpected error while trying to resolve the peer externally: ' . $e->getMessage(), StandardError::RESOLUTION_FAILED, $e); + } + + // Synchronize the peer for future use + self::synchronizeExternalPeer($registeredPeer); + } + } + } + catch(StandardException $e) + { + throw $e; + } + catch(Exception $e) + { + throw new StandardException('Failed to resolve the peer: ' . $e->getMessage(), StandardError::RESOLUTION_FAILED, $e); + } + + if($registeredPeer === null) + { + throw new StandardException('The requested peer was not found', StandardError::PEER_NOT_FOUND); + } + + return $registeredPeer; } /**