From 9bd3b5efffd9e16c9a556726caf5d79821c25af4 Mon Sep 17 00:00:00 2001 From: Ondrej Vlach Date: Thu, 18 Jan 2024 15:21:41 +0100 Subject: [PATCH] feat: add CachedQRCodeProvider --- README.md | 1 + composer.json | 1 + composer.lock | 2 +- config/packages/cache.yaml | 2 +- config/services.yaml | 7 +++- .../CacheableQRCodeGeneratorInterface.php | 12 ++++++ src/Service/CachedQRCodeGenerator.php | 39 +++++++++++++++++++ src/Service/Remote/UsetrenoQRCodeProvider.php | 15 +++++-- 8 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 src/Service/CacheableQRCodeGeneratorInterface.php create mode 100644 src/Service/CachedQRCodeGenerator.php diff --git a/README.md b/README.md index fe8ffcd..dfb5e0d 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,4 @@ TODO: ----- - [ ] Chybí speciální slovník nebo vypnutí slovníku pro testy - [ ] V reálný aplikaci bych použil Mockery, nicméně tady mě to přijde zbytečný +- [ ] Nastavení cache ideálně v memcached/redis etc. diff --git a/composer.json b/composer.json index 2cee8c0..5ee109a 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "php-http/httplug": "*", "symfony/asset": "7.0.*", "symfony/asset-mapper": "7.0.*", + "symfony/cache": "7.0.*", "symfony/console": "7.0.*", "symfony/dotenv": "7.0.*", "symfony/flex": "^2", diff --git a/composer.lock b/composer.lock index f2b53bd..140508e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "dda7db8ccac14db47a72f26e4769dac8", + "content-hash": "15e05e23293f0f945b50f450fe8213c3", "packages": [ { "name": "composer/semver", diff --git a/config/packages/cache.yaml b/config/packages/cache.yaml index 6899b72..23dcfb1 100644 --- a/config/packages/cache.yaml +++ b/config/packages/cache.yaml @@ -1,7 +1,7 @@ framework: cache: # Unique name of your app: used to compute stable namespaces for cache keys. - #prefix_seed: your_vendor_name/app_name + prefix_seed: ovlach/symfony_example_app # The "app" cache stores to the filesystem by default. # The data in this cache should persist between deploys. diff --git a/config/services.yaml b/config/services.yaml index 06e08fd..f96070f 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -40,9 +40,14 @@ services: $username: '%app.usetreno.username%' $password: '%app.usetreno.password%' + App\Service\CachedQRCodeGenerator: + arguments: + $innerGenerator: '@App\Service\Remote\UsetrenoQRCodeProvider' + $cacheDuration: 'PT60S' + App\Service\CurrencyListerInterface: '@App\Service\StaticCurrencyLister' App\Service\QRCodeQROptionsProviderInterface: '@App\Service\QRCodeQROptionsDefaultProvider' - App\Service\QRCodeGeneratorInterface: '@App\Service\Remote\UsetrenoQRCodeProvider' + App\Service\QRCodeGeneratorInterface: '@App\Service\CachedQRCodeGenerator' # add more service definitions when explicit configuration is needed # please note that last definitions always *replace* previous ones diff --git a/src/Service/CacheableQRCodeGeneratorInterface.php b/src/Service/CacheableQRCodeGeneratorInterface.php new file mode 100644 index 0000000..9b80ac1 --- /dev/null +++ b/src/Service/CacheableQRCodeGeneratorInterface.php @@ -0,0 +1,12 @@ +cacheDuration = new \DateInterval($cacheDuration); + } + + public function generateQRCodeFromEntity(QRCode $entity): string + { + $key = $this->innerGenerator->getCacheKey($entity); + return $this->cache->get($key, function(ItemInterface $c) use ($entity) { + $this->logger->debug("cache miss for key " . $c->getKey(), [ + 'entity' => $entity, + ]); + + $c->expiresAfter($this->cacheDuration); + + return $this->innerGenerator->generateQRCodeFromEntity($entity); + }); + } +} diff --git a/src/Service/Remote/UsetrenoQRCodeProvider.php b/src/Service/Remote/UsetrenoQRCodeProvider.php index bd59053..379beb8 100644 --- a/src/Service/Remote/UsetrenoQRCodeProvider.php +++ b/src/Service/Remote/UsetrenoQRCodeProvider.php @@ -4,13 +4,12 @@ declare(strict_types=1); namespace App\Service\Remote; use App\Entity\QRCode\QRCode; -use App\Service\QRCodeGeneratorInterface; +use App\Service\CacheableQRCodeGeneratorInterface; use App\Service\Remote\Edge\QRCodeEntityConverter; -use App\Service\Remote\Exception\AuthorizeException; use App\Service\Remote\Exception\UsetrenoQRCodeException; use Psr\Log\LoggerInterface; -class UsetrenoQRCodeProvider implements QRCodeGeneratorInterface +class UsetrenoQRCodeProvider implements CacheableQRCodeGeneratorInterface { const QRCODE_API = 'https://topapi.top-test.cz/chameleon/api/v1/qr-code/create-for-bank-account-payment'; const QRCODE_METHOD = 'POST'; @@ -86,4 +85,14 @@ class UsetrenoQRCodeProvider implements QRCodeGeneratorInterface return $data->data->base64Data; } + + public function getCacheKey(QRCode $entity): string + { + $edgeEntity = $this->codeEntityConverter->convert($entity); + $encodedEntity = json_encode($edgeEntity); + if ($encodedEntity === false) { + throw new \RuntimeException("Can't serialize edge entity"); + } + return base64_encode($encodedEntity); + } }