diff --git a/.travis.yml b/.travis.yml index 985059b9..d519b075 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,6 @@ services: - postgresql before_install: - - echo 'extension = memcached.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - echo 'extension = apcu.so' >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - yes | pecl install swoole - phpenv config-rm xdebug.ini || return 0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 81571e05..9b7bbff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com), and this #### Changed -* *Nothing* +* [#56](https://github.com/shlinkio/shlink/issues/56) Simplified supported cache, requiring APCu always. ### Deprecated diff --git a/data/infra/php.Dockerfile b/data/infra/php.Dockerfile index 19454a48..b571ecb0 100644 --- a/data/infra/php.Dockerfile +++ b/data/infra/php.Dockerfile @@ -2,7 +2,6 @@ FROM php:7.3.1-fpm-alpine3.8 MAINTAINER Alejandro Celaya ENV PREDIS_VERSION 4.2.0 -ENV MEMCACHED_VERSION 3.1.3 ENV APCU_VERSION 5.1.16 ENV APCU_BC_VERSION 1.0.4 ENV XDEBUG_VERSION "2.7.0RC1" @@ -41,18 +40,6 @@ RUN docker-php-ext-configure redis\ # cleanup RUN rm /tmp/phpredis.tar.gz -# Install memcached extension -RUN apk add --no-cache --virtual cyrus-sasl-dev -RUN apk add --no-cache --virtual libmemcached-dev -ADD https://github.com/php-memcached-dev/php-memcached/archive/v$MEMCACHED_VERSION.tar.gz /tmp/memcached.tar.gz -RUN mkdir -p /usr/src/php/ext/memcached\ - && tar xf /tmp/memcached.tar.gz -C /usr/src/php/ext/memcached --strip-components=1 -# configure and install -RUN docker-php-ext-configure memcached\ - && docker-php-ext-install memcached -# cleanup -RUN rm /tmp/memcached.tar.gz - # Install APCu extension ADD https://pecl.php.net/get/apcu-$APCU_VERSION.tgz /tmp/apcu.tar.gz RUN mkdir -p /usr/src/php/ext/apcu\ diff --git a/data/infra/swoole.Dockerfile b/data/infra/swoole.Dockerfile index 6b647a42..f27cbafe 100644 --- a/data/infra/swoole.Dockerfile +++ b/data/infra/swoole.Dockerfile @@ -2,7 +2,6 @@ FROM php:7.3.1-cli-alpine3.8 MAINTAINER Alejandro Celaya ENV PREDIS_VERSION 4.2.0 -ENV MEMCACHED_VERSION 3.1.3 ENV APCU_VERSION 5.1.16 ENV APCU_BC_VERSION 1.0.4 ENV INOTIFY_VERSION 2.0.0 @@ -41,18 +40,6 @@ RUN docker-php-ext-configure redis\ # cleanup RUN rm /tmp/phpredis.tar.gz -# Install memcached extension -RUN apk add --no-cache --virtual cyrus-sasl-dev -RUN apk add --no-cache --virtual libmemcached-dev -ADD https://github.com/php-memcached-dev/php-memcached/archive/v$MEMCACHED_VERSION.tar.gz /tmp/memcached.tar.gz -RUN mkdir -p /usr/src/php/ext/memcached\ - && tar xf /tmp/memcached.tar.gz -C /usr/src/php/ext/memcached --strip-components=1 -# configure and install -RUN docker-php-ext-configure memcached\ - && docker-php-ext-install memcached -# cleanup -RUN rm /tmp/memcached.tar.gz - # Install APCu extension ADD https://pecl.php.net/get/apcu-$APCU_VERSION.tgz /tmp/apcu.tar.gz RUN mkdir -p /usr/src/php/ext/apcu\ diff --git a/module/Common/src/Factory/CacheFactory.php b/module/Common/src/Factory/CacheFactory.php index 590e5351..5a810c68 100644 --- a/module/Common/src/Factory/CacheFactory.php +++ b/module/Common/src/Factory/CacheFactory.php @@ -5,98 +5,19 @@ namespace Shlinkio\Shlink\Common\Factory; use Doctrine\Common\Cache; use Interop\Container\ContainerInterface; -use Interop\Container\Exception\ContainerException; -use Memcached; use Shlinkio\Shlink\Core\Options\AppOptions; -use Zend\ServiceManager\Exception\ServiceNotCreatedException; -use Zend\ServiceManager\Exception\ServiceNotFoundException; use Zend\ServiceManager\Factory\FactoryInterface; -use function Functional\contains; use function Shlinkio\Shlink\Common\env; -use function sys_get_temp_dir; class CacheFactory implements FactoryInterface { - private const VALID_CACHE_ADAPTERS = [ - Cache\ApcuCache::class, - Cache\ArrayCache::class, - Cache\FilesystemCache::class, - Cache\PhpFileCache::class, - Cache\MemcachedCache::class, - ]; - private const DEFAULT_MEMCACHED_PORT = 11211; - - /** - * Create an object - * - * @param ContainerInterface $container - * @param string $requestedName - * @param null|array $options - * @return object - * @throws ServiceNotFoundException if unable to resolve the service. - * @throws ServiceNotCreatedException if an exception is raised when - * creating a service. - * @throws ContainerException if any other error occurs - */ - public function __invoke(ContainerInterface $container, $requestedName, array $options = null) + public function __invoke(ContainerInterface $container, $requestedName, array $options = null): Cache\Cache { $appOptions = $container->get(AppOptions::class); - $adapter = $this->getAdapter($container); + $adapter = env('APP_ENV', 'pro') === 'pro' ? new Cache\ApcuCache() : new Cache\ArrayCache(); $adapter->setNamespace((string) $appOptions); return $adapter; } - - private function getAdapter(ContainerInterface $container): Cache\CacheProvider - { - // Try to get the adapter from config - $config = $container->get('config'); - if (isset($config['cache']['adapter']) && contains(self::VALID_CACHE_ADAPTERS, $config['cache']['adapter'])) { - return $this->resolveCacheAdapter($config['cache']); - } - - // If the adapter has not been set in config, create one based on environment - return env('APP_ENV', 'pro') === 'pro' ? new Cache\ApcuCache() : new Cache\ArrayCache(); - } - - private function resolveCacheAdapter(array $cacheConfig): Cache\CacheProvider - { - switch ($cacheConfig['adapter']) { - case Cache\ArrayCache::class: - case Cache\ApcuCache::class: - return new $cacheConfig['adapter'](); - case Cache\FilesystemCache::class: - case Cache\PhpFileCache::class: - return new $cacheConfig['adapter']($cacheConfig['options']['dir'] ?? sys_get_temp_dir()); - case Cache\MemcachedCache::class: - $cache = new Cache\MemcachedCache(); - $cache->setMemcached($this->buildMemcached($cacheConfig)); - return $cache; - default: - return new Cache\ArrayCache(); - } - } - - private function buildMemcached(array $cacheConfig): Memcached - { - $memcached = new Memcached(); - $servers = $cacheConfig['options']['servers'] ?? []; - - foreach ($servers as $server) { - $this->addMemcachedServer($memcached, $server); - } - - return $memcached; - } - - private function addMemcachedServer(Memcached $memcached, array $server): void - { - if (! isset($server['host'])) { - return; - } - $port = (int) ($server['port'] ?? self::DEFAULT_MEMCACHED_PORT); - - $memcached->addServer($server['host'], $port); - } } diff --git a/module/Common/test/Factory/CacheFactoryTest.php b/module/Common/test/Factory/CacheFactoryTest.php index 9f175221..d861b02b 100644 --- a/module/Common/test/Factory/CacheFactoryTest.php +++ b/module/Common/test/Factory/CacheFactoryTest.php @@ -5,27 +5,26 @@ namespace ShlinkioTest\Shlink\Common\Factory; use Doctrine\Common\Cache\ApcuCache; use Doctrine\Common\Cache\ArrayCache; -use Doctrine\Common\Cache\FilesystemCache; -use Doctrine\Common\Cache\MemcachedCache; -use Doctrine\Common\Cache\RedisCache; use PHPUnit\Framework\TestCase; use Shlinkio\Shlink\Common\Factory\CacheFactory; use Shlinkio\Shlink\Core\Options\AppOptions; use Zend\ServiceManager\ServiceManager; -use function count; use function putenv; -use function realpath; -use function sys_get_temp_dir; class CacheFactoryTest extends TestCase { /** @var CacheFactory */ private $factory; + /** @var ServiceManager */ + private $sm; public function setUp(): void { $this->factory = new CacheFactory(); + $this->sm = new ServiceManager(['services' => [ + AppOptions::class => new AppOptions(), + ]]); } public static function tearDownAfterClass(): void @@ -34,76 +33,18 @@ class CacheFactoryTest extends TestCase } /** @test */ - public function productionReturnsApcAdapter() + public function productionReturnsApcAdapter(): void { putenv('APP_ENV=pro'); - $instance = $this->factory->__invoke($this->createSM(), ''); + $instance = ($this->factory)($this->sm, ''); $this->assertInstanceOf(ApcuCache::class, $instance); } /** @test */ - public function developmentReturnsArrayAdapter() + public function developmentReturnsArrayAdapter(): void { putenv('APP_ENV=dev'); - $instance = $this->factory->__invoke($this->createSM(), ''); + $instance = ($this->factory)($this->sm, ''); $this->assertInstanceOf(ArrayCache::class, $instance); } - - /** @test */ - public function adapterDefinedInConfigIgnoresEnvironment() - { - putenv('APP_ENV=pro'); - $instance = $this->factory->__invoke($this->createSM(ArrayCache::class), ''); - $this->assertInstanceOf(ArrayCache::class, $instance); - } - - /** @test */ - public function invalidAdapterDefinedInConfigFallbacksToEnvironment() - { - putenv('APP_ENV=pro'); - $instance = $this->factory->__invoke($this->createSM(RedisCache::class), ''); - $this->assertInstanceOf(ApcuCache::class, $instance); - } - - /** @test */ - public function filesystemCacheAdaptersReadDirOption() - { - $dir = realpath(sys_get_temp_dir()); - /** @var FilesystemCache $instance */ - $instance = $this->factory->__invoke($this->createSM(FilesystemCache::class, ['dir' => $dir]), ''); - $this->assertInstanceOf(FilesystemCache::class, $instance); - $this->assertEquals($dir, $instance->getDirectory()); - } - - /** @test */ - public function memcachedCacheAdaptersReadServersOption() - { - $servers = [ - [ - 'host' => '1.2.3.4', - 'port' => 123, - ], - [ - 'host' => '4.3.2.1', - 'port' => 321, - ], - ]; - /** @var MemcachedCache $instance */ - $instance = $this->factory->__invoke($this->createSM(MemcachedCache::class, ['servers' => $servers]), ''); - $this->assertInstanceOf(MemcachedCache::class, $instance); - $this->assertEquals(count($servers), count($instance->getMemcached()->getServerList())); - } - - private function createSM($cacheAdapter = null, array $options = []) - { - return new ServiceManager(['services' => [ - 'config' => isset($cacheAdapter) ? [ - 'cache' => [ - 'adapter' => $cacheAdapter, - 'options' => $options, - ], - ] : [], - AppOptions::class => new AppOptions(), - ]]); - } }