From ded817c8fdfb95367c3941f0ec5c96605f558984 Mon Sep 17 00:00:00 2001 From: SQKo <87897282+SQKo@users.noreply.github.com> Date: Tue, 6 Dec 2022 10:26:08 +0700 Subject: [PATCH] Add CacheConfig, replacing cacheInterface, cacheSweep and cacheCompress (#1003) * BC: CacheConfig * wrong conflict merge * getter and default null --- src/Discord/Discord.php | 40 +++++----- src/Discord/Helpers/CacheConfig.php | 77 +++++++++++++++++++ src/Discord/Helpers/CacheWrapper.php | 34 ++++---- src/Discord/Repository/AbstractRepository.php | 2 +- 4 files changed, 115 insertions(+), 38 deletions(-) create mode 100644 src/Discord/Helpers/CacheConfig.php diff --git a/src/Discord/Discord.php b/src/Discord/Discord.php index 3da24c620..276556c4c 100644 --- a/src/Discord/Discord.php +++ b/src/Discord/Discord.php @@ -14,6 +14,7 @@ use Discord\Exceptions\IntentException; use Discord\Factory\Factory; use Discord\Helpers\BigInt; +use Discord\Helpers\CacheConfig; use Discord\Http\Http; use Discord\Parts\Guild\Guild; use Discord\Parts\OAuth\Application; @@ -322,11 +323,11 @@ class Discord protected $factory; /** - * The react/cache interface. + * The cache configuration. * - * @var \React\Cache\CacheInterface[]|\Psr\SimpleCache\CacheInterface[] + * @var CacheConfig */ - protected $cache; + protected $cacheConfig; /** * The Client class. @@ -368,8 +369,8 @@ public function __construct(array $options = []) $this->logger->debug('Initializing DiscordPHP '.self::VERSION.' (DiscordPHP-Http: '.Http::VERSION.' & Gateway: v'.self::GATEWAY_VERSION.') on PHP '.PHP_VERSION); - $this->cache = $options['cacheInterface']; - $this->logger->warning('Attached experimental CacheInterface: '.get_class($this->cache[AbstractRepository::class])); + $this->cacheConfig = $options['cache']; + $this->logger->warning('Attached experimental CacheInterface: '.get_class($this->getCacheConfig()->interface)); $connector = new SocketConnector($options['socket_options'], $this->loop); $this->wsFactory = new Connector($this->loop, $connector); @@ -1385,9 +1386,7 @@ protected function resolveOptions(array $options = []): array 'intents', 'socket_options', 'dnsConfig', - 'cacheInterface', - 'cacheSweep', - 'cacheCompress', + 'cache', ]) ->setDefaults([ 'logger' => null, @@ -1397,9 +1396,7 @@ protected function resolveOptions(array $options = []): array 'retrieveBans' => false, 'intents' => Intents::getDefaultIntents(), 'socket_options' => [], - 'cacheInterface' => new ArrayCache(), - 'cacheSweep' => false, - 'cacheCompress' => false, + 'cache' => new ArrayCache(), ]) ->setAllowedTypes('token', 'string') ->setAllowedTypes('logger', ['null', LoggerInterface::class]) @@ -1411,11 +1408,12 @@ protected function resolveOptions(array $options = []): array ->setAllowedTypes('intents', ['array', 'int']) ->setAllowedTypes('socket_options', 'array') ->setAllowedTypes('dnsConfig', ['string', \React\Dns\Config\Config::class]) - ->setAllowedTypes('cacheInterface', ['array', \React\Cache\CacheInterface::class, \Psr\SimpleCache\CacheInterface::class]) - ->setAllowedTypes('cacheSweep', 'bool') - ->setAllowedTypes('cacheCompress', 'bool') - ->setNormalizer('cacheInterface', function ($options, $value) { + ->setAllowedTypes('cache', ['array', CacheConfig::class, \React\Cache\CacheInterface::class, \Psr\SimpleCache\CacheInterface::class]) + ->setNormalizer('cache', function ($options, $value) { if (! is_array($value)) { + if (! ($value instanceof CacheConfig)) { + $value = new CacheConfig($value); + } return [AbstractRepository::class => $value]; } @@ -1577,19 +1575,19 @@ public function getHttp(): Http } /** - * Gets the cache interface. + * Gets the cache configuration. * * @param string $name Repository class name. * - * @return \React\Cache\CacheInterface|\Psr\SimpleCache\CacheInterface + * @return CacheConfig */ - public function getCache($repository_class = AbstractRepository::class) + public function getCacheConfig($repository_class = AbstractRepository::class) { - if (! isset($this->cache[$repository_class])) { + if (! isset($this->cacheConfig[$repository_class])) { $repository_class = AbstractRepository::class; } - return $this->cache[$repository_class]; + return $this->cacheConfig[$repository_class]; } /** @@ -1601,7 +1599,7 @@ public function getCache($repository_class = AbstractRepository::class) */ public function __get(string $name) { - $allowed = ['loop', 'options', 'logger', 'http', 'application_commands', 'cache']; + $allowed = ['loop', 'options', 'logger', 'http', 'application_commands']; if (in_array($name, $allowed)) { return $this->{$name}; diff --git a/src/Discord/Helpers/CacheConfig.php b/src/Discord/Helpers/CacheConfig.php new file mode 100644 index 000000000..3ccaf6f58 --- /dev/null +++ b/src/Discord/Helpers/CacheConfig.php @@ -0,0 +1,77 @@ + + * + * This file is subject to the MIT license that is bundled + * with this source code in the LICENSE.md file. + */ + +namespace Discord\Helpers; + +/** + * Cache configuration class. To be used with Discord `cache` Options. + * + * @see Discord + * + * @since 10.0.0 + * + * @property-read \React\Cache\CacheInterface|\Psr\SimpleCache\CacheInterface $interface The PSR-16 cache interface. + * @property-read bool $separator The cache key prefix separator if supported by the interface. Usually dot `.` for generic cache or colon `:` for Redis/Memcached. + */ +class CacheConfig +{ + /** + * @var \React\Cache\CacheInterface|\Psr\SimpleCache\CacheInterface + */ + protected $interface; + + /** + * Whether to compress cache data before serialization, disabled by default, ignored in ArrayCache. + * + * @var bool + */ + public bool $compress = false; + + /** + * Whether to automatically sweep cached items from memory, disabled by default. + * + * @var bool + */ + public bool $sweep = false; + + /** + * @var string + */ + protected string $separator = '.'; + + /** + * @param \React\Cache\CacheInterface|\Psr\SimpleCache\CacheInterface $interface The PSR-16 Cache Interface. + * @param bool $compress Whether to compress cache data before serialization, ignored in ArrayCache. + * @param bool $sweep Whether to automatically sweep cache. + * @param string|null $separator The cache key prefix separator, null for default. + */ + public function __construct($interface, bool $compress = false, bool $sweep = false, ?string $separator = null) + { + $this->interface = $interface; + $this->sweep = $sweep; + $this->compress = $compress; + if (null === $separator) { + $separator = '.'; + $interfaceName = get_class($interface); + if (stripos($interfaceName, 'Redis') !== false || stripos($interfaceName, 'Memcached') !== false) { + $separator = ':'; + } + } + $this->separator = $separator; + } + + public function __get(string $name) + { + if (in_array($name, ['interface', 'separator'])) { + return $this->$name; + } + } +} diff --git a/src/Discord/Helpers/CacheWrapper.php b/src/Discord/Helpers/CacheWrapper.php index bd48bc7b0..b244d234f 100644 --- a/src/Discord/Helpers/CacheWrapper.php +++ b/src/Discord/Helpers/CacheWrapper.php @@ -67,30 +67,32 @@ class CacheWrapper protected $prefix; /** - * @param Discord $discord - * @param \React\Cache\CacheInterface|\Psr\SimpleCache\CacheInterface $cacheInterface The actual CacheInterface. - * @param array &$items Repository items passed by reference. - * @param string &$class Part class name. - * @param string[] $vars Variable containing hierarchy parent IDs. + * Cache configuration. + * + * @var CacheConfig + */ + protected $config; + + /** + * @param Discord $discord + * @param CacheConfig $config The cache configuration. + * @param array &$items Repository items passed by reference. + * @param string &$class Part class name. + * @param string[] $vars Variable containing hierarchy parent IDs. * * @internal */ - public function __construct(Discord $discord, $cacheInterface, &$items, string &$class, array $vars) + public function __construct(Discord $discord, $config, &$items, string &$class, array $vars) { $this->discord = $discord; - $this->interface = $cacheInterface; + $this->config = $config; $this->items = &$items; $this->class = &$class; - $separator = '.'; - $cacheInterfaceName = get_class($cacheInterface); - if (stripos($cacheInterfaceName, 'Redis') !== false || stripos($cacheInterfaceName, 'Memcached') !== false) { - $separator = ':'; - } - - $this->prefix = implode($separator, [substr(strrchr($this->class, '\\'), 1)] + $vars).$separator; + $this->interface = $config->interface; + $this->prefix = implode($config->separator, [substr(strrchr($this->class, '\\'), 1)] + $vars).$config->separator; - if ($discord->options['cacheSweep']) { + if ($config->sweep) { // Sweep every heartbeat ack $discord->on('heartbeat-ack', [$this, 'sweep']); } @@ -424,7 +426,7 @@ public function serializer($part) if ($this->interface instanceof \React\Cache\CacheInterface && ! ($this->interface instanceof ArrayCache)) { $data = serialize($data); - if ($this->discord->options['cacheCompress']) { + if ($this->config->compress) { $data = zlib_encode($data, ZLIB_ENCODING_DEFLATE); } } diff --git a/src/Discord/Repository/AbstractRepository.php b/src/Discord/Repository/AbstractRepository.php index 05c8de2b8..ea45fd897 100755 --- a/src/Discord/Repository/AbstractRepository.php +++ b/src/Discord/Repository/AbstractRepository.php @@ -90,7 +90,7 @@ public function __construct(Discord $discord, array $vars = []) $this->http = $discord->getHttpClient(); $this->factory = $discord->getFactory(); $this->vars = $vars; - $this->cache = new CacheWrapper($discord, $discord->getCache(static::class), $this->items, $this->class, $this->vars); + $this->cache = new CacheWrapper($discord, $discord->getCacheConfig(static::class), $this->items, $this->class, $this->vars); parent::__construct([], $this->discrim, $this->class); }