Skip to content

ChainAdapter uses default lifetime instead of ttl when saving in get() function #59947

Open
@magicW

Description

@magicW

Symfony version(s) affected

5.4.45

Description

I have a ChainAdapter (Apcu & Redis) with a default lifetime of 86400. When i save an cacheItem with a special ttl, there is no problem. But when I have a second VM without a value in the apcu, the chainAdapter will get the value from Redis and then save it to the chain Adapter (see get-Method of ChainAdapter). The Problem ist that in this case there won't be used the ttl, nore the default lifetime.

How to reproduce

I wrote a test to make the case visible:

<?php
declare(strict_types=1);

namespace Tests\Functional;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;


class ChainAdapterTest extends TestCase
{
    public function testCachesExpirationAfterGet()
    {
        $adapter1 = new FilesystemAdapter('test', 60);
        $adapter2 = new FilesystemAdapter('test2',80);

        $cache = new ChainAdapter([$adapter1, $adapter2], 100);
        $testItemKey = 'key';

        $saved = $cache->save($cache->getItem($testItemKey)->expiresAfter(2)->set('value'));
        $this->assertTrue($saved);
        $this->assertTrue($adapter1->hasItem($testItemKey));
        $this->assertTrue($adapter2->hasItem($testItemKey));

        $adapter1->clear();
        $this->assertFalse($adapter1->hasItem($testItemKey));
        $this->assertTrue($cache->hasItem($testItemKey));
        $this->assertTrue($adapter2->hasItem($testItemKey));

        $cache->getItem($testItemKey)->get(); // Here the ChainAdapter is saving from Adapter 2 to Adapter 1 with the default lifetime of chainAdapter instead of the used ttl

        $this->assertTrue($adapter1->hasItem('key'));
        $this->assertTrue($adapter2->hasItem('key'));

        sleep(3);

        $this->assertFalse($adapter2->getItem('key')->isHit());
        $this->assertFalse($adapter2->hasItem('key'));
        $this->assertFalse($adapter1->getItem('key')->isHit());
        $this->assertFalse($adapter1->hasItem('key'));
    }

}

Possible Solution

I think it is not very easy to solve the problem. I had the idea of ​​storing the lifetime with the key, but I think that is not particularly performant if you always do this.

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions