File size: 3.32Kb
<?php
namespace AsyncAws\Core\EndpointDiscovery;
use AsyncAws\Core\Exception\LogicException;
/**
* @author Jérémy Derussé <jeremy@derusse.com>
*
* @internal
*/
class EndpointCache
{
/**
* @var array<string, array<string, int>>
*/
private $endpoints = [];
/**
* @var array<string, array<string, int>>
*/
private $expired = [];
/**
* @param EndpointInterface[] $endpoints
*/
public function addEndpoints(?string $region, array $endpoints): void
{
$now = time();
if (null === $region) {
$region = '';
}
if (!isset($this->endpoints[$region])) {
$this->endpoints[$region] = [];
}
foreach ($endpoints as $endpoint) {
$this->endpoints[$region][$this->sanitizeEndpoint($endpoint->getAddress())] = $now + ($endpoint->getCachePeriodInMinutes() * 60);
}
arsort($this->endpoints[$region]);
}
public function removeEndpoint(string $endpoint): void
{
$endpoint = $this->sanitizeEndpoint($endpoint);
foreach ($this->endpoints as &$endpoints) {
unset($endpoints[$endpoint]);
}
unset($endpoints);
foreach ($this->expired as &$endpoints) {
unset($endpoints[$endpoint]);
}
unset($endpoints);
}
public function getActiveEndpoint(?string $region): ?string
{
if (null === $region) {
$region = '';
}
$now = time();
foreach ($this->endpoints[$region] ?? [] as $endpoint => $expiresAt) {
if ($expiresAt < $now) {
$this->expired[$region] = \array_slice($this->expired[$region] ?? [], -100); // keep only the last 100 items
unset($this->endpoints[$region][$endpoint]);
$this->expired[$region][$endpoint] = $expiresAt;
continue;
}
return $endpoint;
}
return null;
}
public function getExpiredEndpoint(?string $region): ?string
{
if (null === $region) {
$region = '';
}
if (empty($this->expired[$region])) {
return null;
}
return array_key_last($this->expired[$region]);
}
private function sanitizeEndpoint(string $address): string
{
$parsed = parse_url($address);
// parse_url() will correctly parse full URIs with schemes
if (isset($parsed['host'])) {
return rtrim(\sprintf(
'%s://%s/%s',
$parsed['scheme'] ?? 'https',
$parsed['host'],
ltrim($parsed['path'] ?? '/', '/')
), '/');
}
// parse_url() will put host & path in 'path' if scheme is not provided
if (isset($parsed['path'])) {
$split = explode('/', $parsed['path'], 2);
$parsed['host'] = $split[0];
if (isset($split[1])) {
$parsed['path'] = $split[1];
} else {
$parsed['path'] = '';
}
return rtrim(\sprintf(
'%s://%s/%s',
$parsed['scheme'] ?? 'https',
$parsed['host'],
ltrim($parsed['path'], '/')
), '/');
}
throw new LogicException(\sprintf('The supplied endpoint "%s" is invalid.', $address));
}
}