diff --git a/CHANGELOG.md b/CHANGELOG.md index 8346299..a56e80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## Unreleased + +- Tax rates, customer groups and currency rates as cache entries in the local files: no select per request for them. A tax rule, rate, class or group save cleans the tax entries; a rate import cleans the currency entries. +- A process keeps the entries it read in memory until they expire; a worker answers them without the include. + ## 0.2.0-rc7 - Promote entries that Mage-OS stores through its compression decorator to the local files; the lifetime rule reads the packed record as the frontend answers it. diff --git a/dev/README.md b/dev/README.md index 31eefb3..0a097f1 100644 --- a/dev/README.md +++ b/dev/README.md @@ -27,6 +27,9 @@ Production installs use the default-enabled optimizations. These switches suppor | `view_config` | Reuse of theme/area view XML as PHP data. | Yes | | `guest_tax_factor` | Reuse of guest tax-factor calculations. | Yes | | `placeholder_url` | Cached placeholder URLs, including theme and transport identity. | Yes | +| `tax_rates` | Tax rates and applied rates per rate request from the cache, for requests that are not customer-specific. | Yes | +| `customer_groups` | Customer groups by id from the cache, with their excluded websites. | Yes | +| `currency_rates` | Currency rates from the cache; a rate import cleans them. | Yes | These switches do not enable PHP class preload; that requires `opcache.preload` at FPM startup. diff --git a/src/FastBoot/Plugin/Customer/GroupFromCache.php b/src/FastBoot/Plugin/Customer/GroupFromCache.php new file mode 100644 index 0000000..854997a --- /dev/null +++ b/src/FastBoot/Plugin/Customer/GroupFromCache.php @@ -0,0 +1,65 @@ +feature->on(self::SWITCH)) { + return $proceed($id); + } + $key = self::KEY . (int)$id; + $cached = $this->cache->load($key); + $data = is_string($cached) ? json_decode($cached, true) : null; + if (is_array($data)) { + $group = $this->groupFactory->create() + ->setId($data['id']) + ->setCode($data['code']) + ->setTaxClassId($data['tax_class_id']) + ->setTaxClassName($data['tax_class_name']); + if ($data['exclude_website_ids']) { + $group->setExtensionAttributes($this->extensionFactory->create(GroupInterface::class)->setExcludeWebsiteIds($data['exclude_website_ids'])); + } + + return $group; + } + $group = $proceed($id); + $this->cache->save(json_encode([ + 'id' => $group->getId(), + 'code' => $group->getCode(), + 'tax_class_id' => $group->getTaxClassId(), + 'tax_class_name' => $group->getTaxClassName(), + 'exclude_website_ids' => $group->getExtensionAttributes()?->getExcludeWebsiteIds() ?? [], + ]), $key, [ConfigCache::CACHE_TAG, Tag::TAX]); + + return $group; + } +} diff --git a/src/FastBoot/Plugin/Directory/CurrencyRatesFromCache.php b/src/FastBoot/Plugin/Directory/CurrencyRatesFromCache.php new file mode 100644 index 0000000..9926fa0 --- /dev/null +++ b/src/FastBoot/Plugin/Directory/CurrencyRatesFromCache.php @@ -0,0 +1,63 @@ +rate('rate', $currencyFrom, $currencyTo, static fn() => $proceed($currencyFrom, $currencyTo)); + } + + public function aroundGetAnyRate(Currency $subject, callable $proceed, $currencyFrom, $currencyTo) + { + return $this->rate('any', $currencyFrom, $currencyTo, static fn() => $proceed($currencyFrom, $currencyTo)); + } + + public function afterSaveRates(Currency $subject, $result) + { + $this->cache->clean([Tag::CURRENCY]); + + return $result; + } + + private function rate(string $kind, $currencyFrom, $currencyTo, callable $compute) + { + $from = strtoupper($currencyFrom instanceof CurrencyModel ? (string)$currencyFrom->getCode() : (string)$currencyFrom); + $to = strtoupper($currencyTo instanceof CurrencyModel ? (string)$currencyTo->getCode() : (string)$currencyTo); + if ($from === $to || !$this->feature->on(self::SWITCH)) { + return $compute(); + } + $key = self::KEY . $kind . '_' . $from . '_' . $to; + $cached = $this->cache->load($key); + $entry = is_string($cached) ? json_decode($cached, true) : null; + if (is_array($entry) && array_key_exists('rate', $entry)) { + return $entry['rate']; + } + $rate = $compute(); + $this->cache->save(json_encode(['rate' => $rate], JSON_PRESERVE_ZERO_FRACTION), $key, [ConfigCache::CACHE_TAG, Tag::CURRENCY]); + + return $rate; + } +} diff --git a/src/FastBoot/Plugin/Tax/ForgetRates.php b/src/FastBoot/Plugin/Tax/ForgetRates.php new file mode 100644 index 0000000..b7903c2 --- /dev/null +++ b/src/FastBoot/Plugin/Tax/ForgetRates.php @@ -0,0 +1,33 @@ +cache->clean([Tag::TAX]); + + return $result; + } + + public function afterDelete($subject, $result) + { + $this->cache->clean([Tag::TAX]); + + return $result; + } +} diff --git a/src/FastBoot/Plugin/Tax/RatesFromCache.php b/src/FastBoot/Plugin/Tax/RatesFromCache.php new file mode 100644 index 0000000..906b819 --- /dev/null +++ b/src/FastBoot/Plugin/Tax/RatesFromCache.php @@ -0,0 +1,73 @@ +entry('info', $request, static fn(): array => $proceed($request)); + } + + public function aroundGetCalculationProcess(Calculation $subject, callable $proceed, $request, $rates = null): array + { + if ($rates !== null) { + return $proceed($request, $rates); + } + + return $this->entry('process', $request, static fn(): array => $proceed($request)); + } + + private function entry(string $kind, $request, callable $compute): array + { + if (!$this->feature->on(self::SWITCH) || (int)$this->userContext->getUserType() === UserContextInterface::USER_TYPE_CUSTOMER) { + return $compute(); + } + $key = self::KEY . $kind . '_' . md5(implode('|', [ + $this->storeManager->getStore($request->getStore())->getId(), + implode(',', (array)$request->getProductClassId()), + $request->getCustomerClassId(), + $request->getCountryId(), + $request->getRegionId(), + $request->getPostcode(), + ])); + $cached = $this->cache->load($key); + if (is_string($cached)) { + $value = json_decode($cached, true); + if (is_array($value)) { + return $value; + } + } + $value = $compute(); + $this->cache->save(json_encode($value, JSON_PRESERVE_ZERO_FRACTION), $key, [ConfigCache::CACHE_TAG, Tag::TAX]); + + return $value; + } +} diff --git a/src/FastBoot/Test/Unit/Plugin/Customer/GroupFromCacheTest.php b/src/FastBoot/Test/Unit/Plugin/Customer/GroupFromCacheTest.php new file mode 100644 index 0000000..5eafa49 --- /dev/null +++ b/src/FastBoot/Test/Unit/Plugin/Customer/GroupFromCacheTest.php @@ -0,0 +1,90 @@ +createStub(CacheInterface::class); + $cache->method('load')->willReturnCallback(fn(string $id) => $this->entries[$id] ?? false); + $cache->method('save')->willReturnCallback(function (string $data, string $id) { + $this->entries[$id] = $data; + + return true; + }); + $feature = $this->createStub(Feature::class); + $feature->method('on')->willReturn(true); + $groups = $this->createStub(GroupInterfaceFactory::class); + $groups->method('create')->willReturnCallback(fn(): GroupInterface => $this->group()); + $extensions = $this->createStub(ExtensionAttributesFactory::class); + $extensions->method('create')->willReturnCallback(static fn(): GroupExtension => new GroupExtension()); + + return new GroupFromCache($cache, $feature, $groups, $extensions); + } + + /** A group data object that keeps what its setters receive. */ + private function group(): GroupInterface + { + return new class extends DataObject implements GroupInterface { + public function getId() { return $this->getData('id'); } + public function setId($id) { return $this->setData('id', $id); } + public function getCode() { return $this->getData('code'); } + public function setCode($code) { return $this->setData('code', $code); } + public function getTaxClassId() { return $this->getData('tax_class_id'); } + public function setTaxClassId($taxClassId) { return $this->setData('tax_class_id', $taxClassId); } + public function getTaxClassName() { return $this->getData('tax_class_name'); } + public function setTaxClassName($taxClassName) { return $this->setData('tax_class_name', $taxClassName); } + public function getExtensionAttributes() { return $this->getData('extension_attributes'); } + public function setExtensionAttributes(\Magento\Customer\Api\Data\GroupExtensionInterface $extensionAttributes) { return $this->setData('extension_attributes', $extensionAttributes); } + }; + } + + public function testAGroupWithExcludedWebsitesComesBackWholeFromTheEntry(): void + { + $plugin = $this->plugin(); + $subject = $this->createStub(GroupRepositoryInterface::class); + $calls = 0; + $proceed = function () use (&$calls): GroupInterface { + $calls++; + $group = $this->group()->setId(3)->setCode('Wholesale')->setTaxClassId(5)->setTaxClassName('Retail Customer'); + + return $group->setExtensionAttributes((new GroupExtension())->setExcludeWebsiteIds([2])); + }; + $plugin->aroundGetById($subject, $proceed, 3); + $group = $plugin->aroundGetById($subject, $proceed, 3); + self::assertSame(1, $calls); + self::assertSame(3, $group->getId()); + self::assertSame('Wholesale', $group->getCode()); + self::assertSame(5, $group->getTaxClassId()); + self::assertSame('Retail Customer', $group->getTaxClassName()); + self::assertSame([2], $group->getExtensionAttributes()->getExcludeWebsiteIds()); + } + + public function testAGroupWithoutExcludedWebsitesCarriesNoExtensionAttributes(): void + { + $plugin = $this->plugin(); + $subject = $this->createStub(GroupRepositoryInterface::class); + $proceed = fn(): GroupInterface => $this->group()->setId(0)->setCode('NOT LOGGED IN')->setTaxClassId(3)->setTaxClassName('Retail Customer'); + $plugin->aroundGetById($subject, $proceed, 0); + $group = $plugin->aroundGetById($subject, $proceed, 0); + self::assertSame('NOT LOGGED IN', $group->getCode()); + self::assertNull($group->getExtensionAttributes()); + } +} diff --git a/src/FastBoot/Test/Unit/Plugin/Directory/CurrencyRatesFromCacheTest.php b/src/FastBoot/Test/Unit/Plugin/Directory/CurrencyRatesFromCacheTest.php new file mode 100644 index 0000000..ee82da4 --- /dev/null +++ b/src/FastBoot/Test/Unit/Plugin/Directory/CurrencyRatesFromCacheTest.php @@ -0,0 +1,54 @@ +cache = $this->createMock(CacheInterface::class); + $this->cache->method('load')->willReturnCallback(fn(string $id) => $this->entries[$id] ?? false); + $this->cache->method('save')->willReturnCallback(function (string $data, string $id) { + $this->entries[$id] = $data; + + return true; + }); + $feature = $this->createStub(Feature::class); + $feature->method('on')->willReturn(true); + + return new CurrencyRatesFromCache($this->cache, $feature); + } + + public function testARateAndAMissingRateAreEntriesAndARateImportCleansThem(): void + { + $plugin = $this->plugin(); + $subject = $this->createStub(Currency::class); + $calls = 0; + $proceed = function () use (&$calls) { + $calls++; + + return $calls === 1 ? '0.8500' : false; + }; + self::assertSame('0.8500', $plugin->aroundGetRate($subject, $proceed, 'EUR', 'usd')); + self::assertSame('0.8500', $plugin->aroundGetRate($subject, $proceed, 'eur', 'USD')); + self::assertFalse($plugin->aroundGetAnyRate($subject, $proceed, 'EUR', 'GBP')); + self::assertFalse($plugin->aroundGetAnyRate($subject, $proceed, 'EUR', 'GBP')); + self::assertSame(2, $calls); + self::assertSame(1, $plugin->aroundGetRate($subject, static fn() => 1, 'EUR', 'EUR')); + self::assertCount(2, $this->entries); + $this->cache->expects(self::once())->method('clean')->with([Tag::CURRENCY]); + $plugin->afterSaveRates($subject, null); + } +} diff --git a/src/FastBoot/Test/Unit/Plugin/Tax/RatesFromCacheTest.php b/src/FastBoot/Test/Unit/Plugin/Tax/RatesFromCacheTest.php new file mode 100644 index 0000000..bac77c1 --- /dev/null +++ b/src/FastBoot/Test/Unit/Plugin/Tax/RatesFromCacheTest.php @@ -0,0 +1,95 @@ + */ + private array $entries = []; + private array $tags = []; + + private function plugin(bool $on = true, int $userType = UserContextInterface::USER_TYPE_GUEST): RatesFromCache + { + $cache = $this->createStub(CacheInterface::class); + $cache->method('load')->willReturnCallback(fn(string $id) => $this->entries[$id] ?? false); + $cache->method('save')->willReturnCallback(function (string $data, string $id, array $tags) { + $this->entries[$id] = $data; + $this->tags[$id] = $tags; + + return true; + }); + $feature = $this->createStub(Feature::class); + $feature->method('on')->willReturn($on); + $store = $this->createStub(StoreInterface::class); + $store->method('getId')->willReturn(1); + $stores = $this->createStub(StoreManagerInterface::class); + $stores->method('getStore')->willReturn($store); + + $user = $this->createStub(UserContextInterface::class); + $user->method('getUserType')->willReturn($userType); + + return new RatesFromCache($cache, $feature, $stores, $user); + } + + private function request(string $country = 'NL', int $productClass = 2): DataObject + { + return new DataObject(['store' => 1, 'product_class_id' => $productClass, 'customer_class_id' => 3, 'country_id' => $country, 'region_id' => 0, 'postcode' => '*']); + } + + public function testTheRateInfoOfARequestKeyIsComputedOnceAndTaggedForTaxSaves(): void + { + $plugin = $this->plugin(); + $subject = $this->createStub(Calculation::class); + $calls = 0; + $proceed = function () use (&$calls): array { + $calls++; + + return ['process' => [['id' => 'NL', 'percent' => 21.0, 'rates' => [['code' => 'NL', 'title' => 'BTW', 'percent' => 21.0, 'position' => 1, 'priority' => 1]]]], 'value' => 21.0]; + }; + $first = $plugin->aroundGetRateInfo($subject, $proceed, $this->request()); + $second = $plugin->aroundGetRateInfo($subject, $proceed, $this->request()); + self::assertSame(1, $calls); + self::assertSame($first, $second); + self::assertSame(21.0, $second['value']); + self::assertContains(Tag::TAX, $this->tags[array_key_first($this->tags)]); + $plugin->aroundGetRateInfo($subject, $proceed, $this->request('DE')); + self::assertSame(2, $calls, 'Another destination is another entry'); + } + + public function testGivenRatesAnOffSwitchAndACustomerRequestBypassTheCache(): void + { + $subject = $this->createStub(Calculation::class); + $calls = 0; + $proceed = function () use (&$calls): array { + $calls++; + + return []; + }; + $plugin = $this->plugin(); + $plugin->aroundGetCalculationProcess($subject, $proceed, $this->request(), [['code' => 'x']]); + $plugin->aroundGetCalculationProcess($subject, $proceed, $this->request(), [['code' => 'x']]); + self::assertSame(2, $calls); + self::assertSame([], $this->entries); + $off = $this->plugin(false); + $off->aroundGetCalculationProcess($subject, $proceed, $this->request()); + $off->aroundGetCalculationProcess($subject, $proceed, $this->request()); + self::assertSame(4, $calls); + $customer = $this->plugin(true, UserContextInterface::USER_TYPE_CUSTOMER); + $customer->aroundGetRateInfo($subject, $proceed, $this->request()); + $customer->aroundGetRateInfo($subject, $proceed, $this->request()); + self::assertSame(6, $calls, 'A customer request keeps its own address out of the entries'); + self::assertSame([], $this->entries); + } +} diff --git a/src/FastBoot/Test/Unit/_files/customer-group-generated.php b/src/FastBoot/Test/Unit/_files/customer-group-generated.php new file mode 100644 index 0000000..ebdb35e --- /dev/null +++ b/src/FastBoot/Test/Unit/_files/customer-group-generated.php @@ -0,0 +1,39 @@ +_get('exclude_website_ids'); + } + + public function setExcludeWebsiteIds($excludeWebsiteIds) + { + return $this->setData('exclude_website_ids', $excludeWebsiteIds); + } + } +} + +if (!class_exists(GroupInterfaceFactory::class)) { + class GroupInterfaceFactory + { + public function create(array $data = []): GroupInterface + { + throw new \LogicException('The test stubs the factory'); + } + } +} diff --git a/src/FastBoot/etc/di.xml b/src/FastBoot/etc/di.xml index 1779d7e..0bf2428 100644 --- a/src/FastBoot/etc/di.xml +++ b/src/FastBoot/etc/di.xml @@ -7,7 +7,13 @@ FASTBOOT_SCOPES FASTBOOT_CONFIG_UNCHANGED_ FASTBOOT_WEBSITE_STORES_ - PRODUCT_LISTING_SORT_BY_ATTRIBUTES + FASTBOOT_TAX_RATE_ + FASTBOOT_GROUP_ + FASTBOOT_CURRENCY_RATE_ + + + GraphCommerce\FastBootCache\Model\Tag::TAX + GraphCommerce\FastBootCache\Model\Tag::CURRENCY @@ -53,6 +59,28 @@ + + + + + + + + + + + + + + + + + + + + + + GraphCommerce\FastBoot\Console\StatusCommand diff --git a/src/FastBoot/etc/module.xml b/src/FastBoot/etc/module.xml index c069bc5..6ea29ec 100644 --- a/src/FastBoot/etc/module.xml +++ b/src/FastBoot/etc/module.xml @@ -6,6 +6,10 @@ + + + + diff --git a/src/FastBootCache/Model/Feature.php b/src/FastBootCache/Model/Feature.php index 09dd5d2..486dc80 100644 --- a/src/FastBootCache/Model/Feature.php +++ b/src/FastBootCache/Model/Feature.php @@ -15,7 +15,7 @@ class Feature { private ?array $switches = null; - private const CACHED = ['schema_array' => true,'cache_files' => true,'system_config_array' => true,'view_config' => true,'parsed_queries' => true,'validated_queries' => true,'scopes_cache' => true,'website_stores' => true,'deploy_config_unchanged' => true,'placeholder_url' => true,'guest_tax_factor' => true]; + private const CACHED = ['schema_array' => true,'cache_files' => true,'system_config_array' => true,'view_config' => true,'parsed_queries' => true,'validated_queries' => true,'scopes_cache' => true,'website_stores' => true,'deploy_config_unchanged' => true,'placeholder_url' => true,'guest_tax_factor' => true,'tax_rates' => true,'customer_groups' => true,'currency_rates' => true]; public function __construct( private readonly DeploymentConfig $deploymentConfig, diff --git a/src/FastBootCache/Model/PhpFiles.php b/src/FastBootCache/Model/PhpFiles.php index 7fc9d8e..1851d89 100644 --- a/src/FastBootCache/Model/PhpFiles.php +++ b/src/FastBootCache/Model/PhpFiles.php @@ -12,6 +12,9 @@ class PhpFiles { private ?string $root = null; + + /** @var array the entries this process read or wrote, by index path */ + private array $loaded = []; public const LOADED_LIFETIME = 0; // Unknown backend lifetimes must never be extended. public function __construct(private Filesystem $filesystem, private Version $version, private DeploymentConfig $deploymentConfig, private Release $release) { @@ -44,6 +47,9 @@ public function read(string $group, string $id): mixed return null; } $index = $this->path($group, $id); + if (isset($this->loaded[$index]) && ($this->loaded[$index]['expires'] === null || $this->loaded[$index]['expires'] > microtime(true))) { + return $this->loaded[$index]['value']; + } $record = is_file($index) ? json_decode((string)@file_get_contents($index), true) : null; if (!is_array($record) || !isset($record['hash']) || !is_string($record['hash']) || !preg_match('/^[a-f0-9]{64}$/D', $record['hash']) || !array_key_exists('expires', $record) || ($record['expires'] !== null && !is_numeric($record['expires'])) || ($record['expires'] !== null && $record['expires'] <= microtime(true))) { return null; @@ -65,8 +71,21 @@ public function read(string $group, string $id): mixed @unlink($file); return null; } + $this->remember($index, $value['value'], $record['expires'] === null ? null : (float)$record['expires']); return $value['value']; } + + /** + * A worker process answers the entry from memory until it expires; the index path carries + * the version, so a bump leaves the memory behind. + */ + private function remember(string $index, mixed $value, ?float $expires): void + { + if (count($this->loaded) >= 512) { + $this->loaded = []; + } + $this->loaded[$index] = ['value' => $value, 'expires' => $expires]; + } public function write(string $group, string $id, mixed $value, ?int $lifeTime = null, ?string $expectedVersion = null): void { if ($this->release->id() === null) { @@ -126,7 +145,10 @@ public function write(string $group, string $id, mixed $value, ?int $lifeTime = if (!is_dir(dirname($index)) && !@mkdir(dirname($index), 0700, true) && !is_dir(dirname($index))) { return; } - $this->atomic($index, json_encode(['hash' => $hash,'expires' => $lifeTime === null ? null : microtime(true) + $lifeTime], JSON_THROW_ON_ERROR)); + $expires = $lifeTime === null ? null : microtime(true) + $lifeTime; + if ($this->atomic($index, json_encode(['hash' => $hash,'expires' => $expires], JSON_THROW_ON_ERROR))) { + $this->remember($index, $value, $expires); + } } finally { flock($lock, LOCK_UN); fclose($lock); @@ -162,11 +184,13 @@ private static function exportable(mixed $value, int $depth = 0): bool } public function remove(string $group, string $id): void { + unset($this->loaded[$this->path($group, $id)]); @unlink($this->path($group, $id)); } /** Remove obsolete indexes only. Blobs stay reusable and bounded until release cleanup/FPM restart. */ public function sweep(): void { + $this->loaded = []; $root = $this->namespaceDirectory().'/indexes'; foreach (glob($root.'/*', GLOB_ONLYDIR) ?: [] as $dir) { $this->removeDirectory($dir); diff --git a/src/FastBootCache/Model/Tag.php b/src/FastBootCache/Model/Tag.php new file mode 100644 index 0000000..ebcb35a --- /dev/null +++ b/src/FastBootCache/Model/Tag.php @@ -0,0 +1,14 @@ + true], $b->read('CONFIG', 'a/b')); self::assertSame('different', $b->read('CONFIG', 'a_b')); $b->sweep(); - self::assertNull($a->read('CONFIG', 'a/b')); self::assertNull($b->read('CONFIG', 'a/b')); + self::assertNull($this->files('a')->read('CONFIG', 'a/b'), 'A sweep comes with a version bump, so another process reads under a new path'); } public function testPublicationGenerationAndExpiryAreRespected(): void { @@ -81,4 +81,19 @@ public function testAdmissionIsBoundedAndObjectsAreNeverExported(): void $f->write('CONFIG', 'object', new \stdClass()); self::assertNull($f->read('CONFIG', 'object')); } + + public function testAProcessAnswersAnEntryFromMemoryUntilItExpiresOrIsRemoved(): void + { + $files = $this->files('v1'); + $files->write('G', 'kept', ['a' => 1]); + $files->write('G', 'brief', ['b' => 2], 1); + $this->remove($this->var.'/fastboot'); + self::assertSame(['a' => 1], $files->read('G', 'kept'), 'The memory of this process answers after the files are gone'); + self::assertSame(['b' => 2], $files->read('G', 'brief')); + usleep(1100000); + self::assertNull($files->read('G', 'brief'), 'An expired entry leaves the memory'); + $files->remove('G', 'kept'); + self::assertNull($files->read('G', 'kept')); + self::assertNull($this->files('v1')->read('G', 'kept'), 'Another process reads the files'); + } } diff --git a/src/FastBootGraphQl/Plugin/CacheId/GuestTaxFactor.php b/src/FastBootGraphQl/Plugin/CacheId/GuestTaxFactor.php index ec216b2..053ce62 100644 --- a/src/FastBootGraphQl/Plugin/CacheId/GuestTaxFactor.php +++ b/src/FastBootGraphQl/Plugin/CacheId/GuestTaxFactor.php @@ -4,6 +4,7 @@ namespace GraphCommerce\FastBootGraphQl\Plugin\CacheId; use GraphCommerce\FastBootCache\Model\Feature; +use GraphCommerce\FastBootCache\Model\Tag; use Magento\CustomerGraphQl\CacheIdFactorProviders\CustomerTaxRateProvider; use Magento\Framework\App\Cache\Type\Config as ConfigCache; use Magento\Framework\App\CacheInterface; @@ -21,7 +22,7 @@ class GuestTaxFactor { private const SWITCH = 'guest_tax_factor'; - public const TAG = 'FASTBOOT_TAX'; + public const TAG = Tag::TAX; private const KEY = 'FASTBOOT_TAX_FACTOR_'; diff --git a/src/FastBootGraphQl/Plugin/Tax/ForgetTaxFactors.php b/src/FastBootGraphQl/Plugin/Tax/ForgetTaxFactors.php deleted file mode 100644 index 61a7f8c..0000000 --- a/src/FastBootGraphQl/Plugin/Tax/ForgetTaxFactors.php +++ /dev/null @@ -1,33 +0,0 @@ -cache->clean([GuestTaxFactor::TAG]); - - return $result; - } - - public function afterDelete($subject, $result) - { - $this->cache->clean([GuestTaxFactor::TAG]); - - return $result; - } -} diff --git a/src/FastBootGraphQl/etc/di.xml b/src/FastBootGraphQl/etc/di.xml index d5f092f..b81f447 100644 --- a/src/FastBootGraphQl/etc/di.xml +++ b/src/FastBootGraphQl/etc/di.xml @@ -40,18 +40,6 @@ - - - - - - - - - - - -