Skip to content

Commit

Permalink
perf: object mapper resolver cache prewarming (#216)
Browse files Browse the repository at this point in the history
* perf: object mapper resolver cache prewarming

* rector
  • Loading branch information
priyadi authored Oct 10, 2024
1 parent 1835e7f commit 0c34cdf
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* deps: remove phpstan unused public
* feat: attributes inheritance is now preserved
* chore: rector run
* perf: object mapper resolver cache prewarming

## 1.9.4

Expand Down
30 changes: 30 additions & 0 deletions src/CacheWarmer/WarmableObjectMapperResolverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?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\CacheWarmer;

use Rekalogika\Mapper\CustomMapper\Exception\ObjectMapperNotFoundException;
use Rekalogika\Mapper\ServiceMethod\ServiceMethodSpecification;

interface WarmableObjectMapperResolverInterface
{
/**
* @param class-string $sourceClass
* @param class-string $targetClass
* @throws ObjectMapperNotFoundException
*/
public function warmingGetObjectMapper(
string $sourceClass,
string $targetClass,
): ServiceMethodSpecification;
}
27 changes: 26 additions & 1 deletion src/CustomMapper/Implementation/CachingObjectMapperResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@
namespace Rekalogika\Mapper\CustomMapper\Implementation;

use Psr\Cache\CacheItemPoolInterface;
use Rekalogika\Mapper\CacheWarmer\WarmableCacheInterface;
use Rekalogika\Mapper\CacheWarmer\WarmableObjectMapperResolverInterface;
use Rekalogika\Mapper\CustomMapper\ObjectMapperResolverInterface;
use Rekalogika\Mapper\ServiceMethod\ServiceMethodSpecification;

/**
* @internal
*/
final class CachingObjectMapperResolver implements ObjectMapperResolverInterface
final class CachingObjectMapperResolver implements
ObjectMapperResolverInterface,
WarmableObjectMapperResolverInterface
{
/**
* @var array<class-string,array<class-string,ServiceMethodSpecification>>
Expand Down Expand Up @@ -68,4 +72,25 @@ public function getObjectMapper(

return $this->objectMapperCache[$sourceClass][$targetClass] = $objectMapper;
}

#[\Override]
public function warmingGetObjectMapper(
string $sourceClass,
string $targetClass,
): ServiceMethodSpecification {
$result = $this->objectMapperResolver
->getObjectMapper($sourceClass, $targetClass);

if (!$this->cacheItemPool instanceof WarmableCacheInterface) {
return $result;
}

$cacheKey = hash('xxh128', $sourceClass . $targetClass);
$cacheItem = $this->cacheItemPool->getWarmedUpItem($cacheKey);
$cacheItem->set($result);

$this->cacheItemPool->saveWarmedUp($cacheItem);

return $result;
}
}
33 changes: 32 additions & 1 deletion src/Transformer/Implementation/ObjectMapperTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
namespace Rekalogika\Mapper\Transformer\Implementation;

use Psr\Container\ContainerInterface;
use Rekalogika\Mapper\CacheWarmer\WarmableObjectMapperResolverInterface;
use Rekalogika\Mapper\CacheWarmer\WarmableTransformerInterface;
use Rekalogika\Mapper\Context\Context;
use Rekalogika\Mapper\CustomMapper\ObjectMapperResolverInterface;
use Rekalogika\Mapper\CustomMapper\ObjectMapperTableFactoryInterface;
Expand All @@ -29,7 +31,8 @@

final class ObjectMapperTransformer implements
TransformerInterface,
MainTransformerAwareInterface
MainTransformerAwareInterface,
WarmableTransformerInterface
{
use MainTransformerAwareTrait;

Expand Down Expand Up @@ -94,6 +97,34 @@ public function transform(
);
}

#[\Override]
public function warmingTransform(
Type $sourceType,
Type $targetType,
Context $context,
): void {
$sourceClass = $sourceType->getClassName();
$targetClass = $targetType->getClassName();

if (
($sourceClass === null || !class_exists($sourceClass))
|| ($targetClass === null || !class_exists($targetClass))
) {
return;
}

if ($this->objectMapperResolver instanceof WarmableObjectMapperResolverInterface) {
$this->objectMapperResolver
->warmingGetObjectMapper($sourceClass, $targetClass);
}
}

#[\Override]
public function isWarmable(): bool
{
return true;
}

#[\Override]
public function getSupportedTransformation(): iterable
{
Expand Down

0 comments on commit 0c34cdf

Please sign in to comment.