Skip to content

Commit

Permalink
fix: Add caching for ObjectMapperTable.
Browse files Browse the repository at this point in the history
  • Loading branch information
priyadi committed Feb 4, 2024
1 parent fd0df5c commit fb9d6a3
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 20 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# CHANGELOG

## 0.6.1

* fix: Add caching for `ObjectMapperTable`.

## 0.6.0

* style: Remove remnants.
Expand Down
14 changes: 12 additions & 2 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
use Rekalogika\Mapper\Command\TryPropertyCommand;
use Rekalogika\Mapper\CustomMapper\Implementation\ObjectMapperTableFactory;
use Rekalogika\Mapper\CustomMapper\Implementation\PropertyMapperResolver;
use Rekalogika\Mapper\CustomMapper\Implementation\WarmableObjectMapperTableFactory;
use Rekalogika\Mapper\MainTransformer\MainTransformer;
use Rekalogika\Mapper\Mapper;
use Rekalogika\Mapper\MapperInterface;
use Rekalogika\Mapper\Mapping\Implementation\CachingMappingFactory;
use Rekalogika\Mapper\Mapping\Implementation\WarmableMappingFactory;
use Rekalogika\Mapper\Mapping\Implementation\MappingFactory;
use Rekalogika\Mapper\Mapping\MappingFactoryInterface;
use Rekalogika\Mapper\ObjectCache\Implementation\ObjectCacheFactory;
Expand Down Expand Up @@ -194,7 +195,7 @@
->alias(MappingFactoryInterface::class, 'rekalogika.mapper.mapping_factory');

$services
->set('rekalogika.mapper.mapping_factory.caching', CachingMappingFactory::class)
->set('rekalogika.mapper.mapping_factory.caching', WarmableMappingFactory::class)
->decorate('rekalogika.mapper.mapping_factory')
->args([
service('rekalogika.mapper.mapping_factory.caching.inner'),
Expand Down Expand Up @@ -300,6 +301,15 @@
$services
->set('rekalogika.mapper.object_mapper.table_factory', ObjectMapperTableFactory::class);

$services
->set('rekalogika.mapper.object_mapper.table_factory.warmed', WarmableObjectMapperTableFactory::class)
->decorate('rekalogika.mapper.object_mapper.table_factory')
->args([
service('.inner'),
service('kernel')
])
->tag('kernel.cache_warmer');

# other services

$services
Expand Down
46 changes: 46 additions & 0 deletions src/CustomMapper/Implementation/ObjectMapperTableWarmer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Mapper\CustomMapper\Implementation;

use Rekalogika\Mapper\CustomMapper\ObjectMapperTableFactoryInterface;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\VarExporter\VarExporter;

class ObjectMapperTableWarmer implements CacheWarmerInterface
{
public function __construct(
private ObjectMapperTableFactoryInterface $objectMapperTableFactory,
private KernelInterface $kernel,
) {
}

public function isOptional(): bool
{
return false;
}

public function warmUp(string $cacheDir, ?string $buildDir = null): array
{
$mapping = VarExporter::export($this->objectMapperTableFactory->createObjectMapperTable());
file_put_contents($this->getCacheFilePath(), '<?php return ' . $mapping . ';');

return [];
}

private function getCacheFilePath(): string
{
return $this->kernel->getBuildDir() . '/rekalogika_mapper_mapper_table.php';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

declare(strict_types=1);

/*
* This file is part of rekalogika/mapper package.
*
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev>
*
* For the full copyright and license information, please view the LICENSE file
* that was distributed with this source code.
*/

namespace Rekalogika\Mapper\CustomMapper\Implementation;

use Rekalogika\Mapper\CustomMapper\ObjectMapperTable;
use Rekalogika\Mapper\CustomMapper\ObjectMapperTableFactoryInterface;
use Rekalogika\Mapper\Exception\UnexpectedValueException;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\VarExporter\VarExporter;

class WarmableObjectMapperTableFactory implements
ObjectMapperTableFactoryInterface,
CacheWarmerInterface
{
public const CACHE_FILE = 'rekalogika_mapper_mapper_table.php';

private ?ObjectMapperTable $objectMapperTableCache = null;

public function __construct(
private ObjectMapperTableFactoryInterface $decorated,
private KernelInterface $kernel,
) {
}

public function createObjectMapperTable(): ObjectMapperTable
{
if ($this->objectMapperTableCache !== null) {
return $this->objectMapperTableCache;
}

try {
/** @psalm-suppress UnresolvableInclude */
$result = require $this->getCacheFilePath();

if (!$result instanceof ObjectMapperTable) {
throw new UnexpectedValueException();
}

return $this->objectMapperTableCache = $result;
} catch (\Throwable) {
@unlink($this->getCacheFilePath());

return $this->objectMapperTableCache = $this->warmUpAndGetResult();
}
}

private function warmUpAndGetResult(): ObjectMapperTable
{
$this->warmUp($this->kernel->getCacheDir(), $this->kernel->getBuildDir());

return $this->decorated->createObjectMapperTable();
}

public function warmUp(string $cacheDir, ?string $buildDir = null): array
{
$mapping = VarExporter::export($this->decorated->createObjectMapperTable());
file_put_contents($this->getCacheFilePath(), '<?php return ' . $mapping . ';');

return [];
}

public function isOptional(): bool
{
return false;
}

private function getCacheFilePath(): string
{
return $this->kernel->getBuildDir() . '/' . self::CACHE_FILE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\VarExporter\VarExporter;

final class CachingMappingFactory implements
final class WarmableMappingFactory implements
MappingFactoryInterface,
CacheWarmerInterface
{
public const CACHE_FILE = 'rekalogika_mapper_mapping.php';

private ?Mapping $mapping = null;

public function __construct(
Expand All @@ -49,40 +51,31 @@ public function getMapping(): Mapping
return $this->mapping;
}

if ($this->kernel->isDebug()) {
return $this->mapping = $this->warmUpAndGetMapping();
}

if (!file_exists($this->getCacheFilePath())) {
return $this->mapping = $this->warmUpAndGetMapping();
}

try {
/** @psalm-suppress UnresolvableInclude */
$result = require $this->getCacheFilePath();

if (!$result instanceof Mapping) {
throw new \UnexpectedValueException();
}
} catch (\Throwable) {
unlink($this->getCacheFilePath());
@unlink($this->getCacheFilePath());

return $this->mapping = $this->warmUpAndGetMapping();
}

if (!$result instanceof Mapping) {
unlink($this->getCacheFilePath());

return $this->mapping = $this->warmUpAndGetMapping();
}

return $this->mapping = $result;
}

public function isOptional(): bool
{
return true;
return false;
}

public function getCacheFilePath(): string
private function getCacheFilePath(): string
{
return $this->kernel->getBuildDir() . '/rekalogika_mapper_mapping.php';
return $this->kernel->getBuildDir() . '/' . self::CACHE_FILE;
}

public function warmUp(string $cacheDir, ?string $buildDir = null): array
Expand Down

0 comments on commit fb9d6a3

Please sign in to comment.