Skip to content

[Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command #23451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

robfrawley
Copy link
Contributor

@robfrawley robfrawley commented Jul 8, 2017

Q A
Branch? 3.4
Bug fix? no
New feature? yes
BC breaks? no
Deprecations? no
Tests pass? yes
Fixed tickets #21764, #21764 (comment)
License MIT
Doc PR symfony/symfony-docs#8209

As requested in #21764 (comment), this PR adds a prune() method to FilesystemTrait. This placement seems reasonable as it exposes the method in FilesystemAdapter and FilesystemCache.

The return value is a bool representing either a partial or complete failure (when false) or complete success (when true).

Once the API for the prune method is confirmed, I'll introduce a documentation PR, as well.


Stale-detection implementation: The file modification time is used to determine if a cache item should be pruned. This seems reasonable, given the use of touch in the common trait. Interestingly, though, the doFetch method uses the timestamp saved at the top of the file itself to determine the stale state. Should this latter implementation be used for prune as well (or is the current one ok), for example:

foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD) as $file) {
    if ($h = @fopen($file, 'rb')) {
        if ($time >= (int) $expiresAt = fgets($h)) {
            fclose($h);
            if (isset($expiresAt[0])) {
                $okay = (@unlink($file) && !file_exists($file)) && $okay;
            }
        }
    }
}

@robfrawley robfrawley force-pushed the feature-filesystem-cache-prune branch 2 times, most recently from 41d099e to d414259 Compare July 8, 2017 02:42
@robfrawley robfrawley changed the title Add filesystem cache (adapter|simple) prune method [Cache] Add filesystem cache (adapter|simple) prune method Jul 8, 2017
$i = 0;

foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST, \RecursiveIteratorIterator::CATCH_GET_CHILD) as $file) {
// remove empty directories
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty dirs shouldn't be removed: that creates a race condition.

Copy link
Contributor Author

@robfrawley robfrawley Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right; I didn't think about that. I've amended the RecursiveIteratorIterator iterator to use the LEAVES_ONLY mode constant (so only the files are recursed over without any dirs) and removed the inner directory logic entirely from the foreach.

*
* @return int
*/
public function prune($time = null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why allow time configuration?

Copy link
Contributor Author

@robfrawley robfrawley Jul 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is useful in allowing cache entries to be purged starting at an arbitrary time. For example, the developer may need to clear all cache entries that would expire in the next hour, and short of fetching all and iterating over them, this isn't otherwise possible.

More simply, the argument provides fine-tuned control between a call to clear() and prune() by allowing one to purge anywhere in-between those two methods.

Do you see any value in this as explained?

}
}

return $i;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A boolean would be enough IMHO

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not extremely sided one way or another on the return type, but I will point out my motivation and you can instruct whether it adds any value: Generally, prune will (or should) be run in cron or an otherwise scheduled command (outside of a normal request); as such, I figured it may be substantive to allow the user to log the behavior of purge (specifically the number of items removed), which could provide insights into the size, growth, and general behavior of their cache items.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've gone ahead and changed the implementation to return bool for now; please advise if you find value in the above and I can revert; for now, it's as requested!

@robfrawley robfrawley force-pushed the feature-filesystem-cache-prune branch 3 times, most recently from e288617 to d64598a Compare July 8, 2017 09:52
Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay doesn't exist, it's ok :) Maybe $pruned?
Also about the time arg, I personally don't see the need, so I'll let others confirm if this is really useful.


foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD) as $file) {
if ($time >= $file->getMTime()) {
$okay = (@unlink($file) && !file_exists($file)) && $okay;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the first && should be an ||

@robfrawley robfrawley force-pushed the feature-filesystem-cache-prune branch 2 times, most recently from 933fb18 to 5700093 Compare July 8, 2017 11:04
@robfrawley
Copy link
Contributor Author

@nicolas-grekas Just noticed #21764 (comment) where you mentioned adding a PruneableInterface to the cache component: is this something I should include in this PR?

@nicolas-grekas
Copy link
Member

@robfrawley yes please do, that would ease writting the command to prune (all prunable) pools.
But definitely the $time arg should not be in the interface to me.
If you could add the command into that PR, that'd be awesome.

@nicolas-grekas nicolas-grekas added this to the 3.4 milestone Jul 10, 2017
@robfrawley
Copy link
Contributor Author

@nicolas-grekas What bundle should the command exist in?

@nicolas-grekas
Copy link
Member

FrameworkBundle since that's where the other cache:pool commands are I'd say.

@robfrawley
Copy link
Contributor Author

Re: the command. Do you want a complex implementation with a compiler pass that assigns all specially tagged services to a "global cache pruner" abstraction that is then consumed by the command (like the "cache clearer" implementation) or do you want a simple command that just consumes a list of cache pools, grabs 'em from the container, ensures they implement the prunable interface, and calls prune()?

@robfrawley
Copy link
Contributor Author

robfrawley commented Jul 10, 2017

The latter would just look like:

namespace Symfony\Bundle\FrameworkBundle\Command;

use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * Cache pool pruner command.
 */
final class CachePoolPruneCommand extends ContainerAwareCommand
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this
            ->setName('cache:pool:prune')
            ->addArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools')
            ->setDescription('Prune cache pools')
            ->setHelp(<<<'EOF'
The <info>%command.name%</info> command prunes the given cache pools.

    %command.full_name% <cache pool 1> [...<cache pool N>]
EOF
            )
        ;
    }

    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $io = new SymfonyStyle($input, $output);
        $container = $this->getContainer();

        foreach ($input->getArgument('pools') as $id) {
            if (!$container->has($id)) {
                throw new \InvalidArgumentException(sprintf('"%s" cache pool not found in container.', $id));
            }

            if (!($pool = $container->get($id)) instanceof PruneableInterface) {
                throw new \InvalidArgumentException(sprintf('"%s" is not a prunable cache pool.', $id));
            }

            $io->comment(sprintf('Pruning cache pool: <info>%s</info>', $id));
            $pool->prune();
        }

        $io->success('Cache was successfully pruned.');
    }
}

@nicolas-grekas
Copy link
Member

See the cache pool clearer pass and command, it should be similar I guess

@robfrawley
Copy link
Contributor Author

@nicolas-grekas Is the most recent commit the direction you want this to go in? Just want to confirm before finishing up the implementation and ensuring all the required tests are present.

@nicolas-grekas
Copy link
Member

instead of a tag, what about constructing a service locator + array or ids (the pool services), that would be given to the command? I'm not sure I see the need for an intermediary pruner service, WDYT?

@robfrawley
Copy link
Contributor Author

That sounds reasonable. The PR implementation went in this direction as you mentioned mirroring how the "cache clear" functionality was implemented. Having said that, I absolutely agree that a simpler approach would be preferable and that an intermediary pruner service is unnecessary.

But, I'm not intimately familiar with service locators or their best practices. I get the basic concept, that you define a locator, specifying the services it should contain, and then use it like a psr/container. What I'm unsure of is the most appropriate way to dynamically ensure the locator is provided the required arguments (the purgeable pools). Should a compiler pass set the arguments for the service locator? And how does the compiler pass find the pools if not for tags? Is there another way to ensure the locator is passed all purgeable pools?

Basically, how should the service locator be defined to allow dynamically passing all prunable pools to it?

@nicolas-grekas
Copy link
Member

nicolas-grekas commented Jul 12, 2017

Do we need the command to be able to prune one specific pool given as argument? Or is pruning all prunable pools enough? I might think "all of them" is enough, because pruning does remove things that are stale only.
If you agree, then we might use an iterator instead of a locator (new IteratorArgument($listOfPools)).
$listOfPools should be computed by looking at all pools in the compiler pass (via the cache.pool tag) and checking if they implement that interface.

@robfrawley robfrawley force-pushed the feature-filesystem-cache-prune branch 3 times, most recently from 247b365 to 5127fd2 Compare July 12, 2017 22:52
@robfrawley
Copy link
Contributor Author

Give the latest changes a quick once-over. Some items still need to be cleaned up, but I think this is the direction you described. As for passing pools as arguments and using an argument iterator, I don't think those two have to be mutually exclusive. See the command implementation that optionally allows passing pool names. Thoughts? I don't have a strong opinion if you think we should remove the option to do so.

Also, right now the command filters the pools implementing the correct interface; I couldn't figure out how to filter pools during the compiler pass without reflection. If you think that's okay, the logic can be moved to the compiler pass by replacing getCachePoolsIterator with:

/**
 * @param ContainerBuilder $container
 *
 * @return IteratorArgument
 */
private function getCachePoolsIterator(ContainerBuilder $container)
{
    $services = array_filter($this->getConcreteCachePoolServices($container), function ($name) use ($container) {
        $reflection = new \ReflectionClass($container->getDefinition($name)->getClass());

        return $reflection->implementsInterface(PruneableInterface::class);
    });

    return new IteratorArgument(array_combine($services, array_map(function ($id) {
        return new Reference($id);
    }, $services)));
}

@@ -22,4 +22,52 @@ public function createSimpleCache($defaultLifetime = 0)
{
return new FilesystemCache('', $defaultLifetime);
}

public function testPrune()
Copy link
Contributor

@RichardBradley RichardBradley Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this test fail without the other changes?
Looking at FilesystemCache::doContains, I think the cache will already return false for expired entries, whether or not they have been pruned.
If this test passes regardless of whether pruning is working or not, then it's not actually testing the pruning functionality.

(same above)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a valid point; do you have any idea how to better test this functionality?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create a pool with only expired items, then check that prune did empty the dir?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;

/**
* Cache pool pruner command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find "prune" a strange term for this. Is it in common use?

It seems to me that "garbage collection" or "gc" is a more commonly used term for deleting expired items.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are lots of relevant Google hits for "cache prune", so maybe this is just me.

Copy link
Contributor Author

@robfrawley robfrawley Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah; it's a common term. :-) The gc term is common as well, but I think it is much less obvious as to its purpose (especially for those lacking a CS background).

@robfrawley robfrawley force-pushed the feature-filesystem-cache-prune branch from faa5c1a to 2377bb5 Compare July 20, 2017 14:36
$doSet('qux', 'qux-val', new \DateInterval('PT80S'));

$cache->prune();
$this->assertTrue($this->isPruned($cache, 'foo'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to be consistent with the naming, all true/false assertions should be swapped, and isPruned should return true when the key is pruned (it does the opposite right now isn't it?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right; that is due to how it used to be named isHit --- I'll reverse the return now that the name has changed. ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a preference between

return !$cache->getItem($name)->isHit() && !file_exists($getFileMethod->invoke($cache, $name))

and

return !($cache->getItem($name)->isHit() && file_exists($getFileMethod->invoke($cache, $name)))

Copy link
Member

@nicolas-grekas nicolas-grekas Jul 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not the same :)
what about just return !file_exists($getFileMethod->invoke($cache, $name));?
because basically that's what the "prune" method does: clean files

Copy link
Contributor Author

@robfrawley robfrawley Jul 20, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

S*it, you're right. :-( I must be getting tired... I think just checking the file exists is a good call.

$cache->set('qux', 'qux-val', new \DateInterval('PT80S'));

$cache->prune();
$this->assertTrue($this->isPruned($cache, 'foo'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, true/false should be swapped

$pruned = isset($expiresAt[0]) && @unlink($file) && !file_exists($file) && $pruned;
}

fclose($h);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that won't work on Windows, where you cannot unlink a file when all handlers to it are not closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

F*** Windows. :-) But really, I guess just add an else branch?

if ($time >= (int) $expiresAt = fgets($h)) {
    fclose($h);
    $pruned = isset($expiresAt[0]) && @unlink($file) && !file_exists($file) && $pruned;
} else {
    fclose($h);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@robfrawley
Copy link
Contributor Author

Additional changes pushed. If it's an okay time to squash the commits made for your comments into the original commit, let me know (don't want to do so before you can confirm the changes, as it would be harder to do so when squashed, obviously). Thanks for taking the time to so thoroughly review this PR!

Not for this PR, but more generally out of interest (and possibly submission of additional PRs), you've mentioned that other PSR-(6|16) implementations may benefit from implementing PruneableInterface: which ones come to mind for you as benefitting most?

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the work!

@nicolas-grekas
Copy link
Member

which ones come to mind for you as benefitting most?

the PdoAdapter first, then maybe ChainAdapter could propagate, and last to my mind comes the ApcuAdapter, looking for items that have an old $version.'@'.$namespace (but not sure about it esp. since this will be unusable from the command because of different shared memory segments used by the webserver/FPM)

@robfrawley robfrawley changed the title [Cache] Add filesystem cache (adapter|simple) prune method [Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command Jul 20, 2017
…ne command

- added `Symfony\Component\Cache\PruneableInterface` so PSR-6 or PSR-16 cache implementations can declare support
  for manual stale cache pruning
- added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations
- now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and
  supports manual stale cache pruning
- Added `cache:pool:prune` command via `Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand` to allow
  manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool implementations
- Added `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass` compiler pass to fetch
  all cache pools implementing `PruneableInterface` and pass them to the command as an `IteratorArgument` so
  these references are lazy loaded by the command
- updated changelogs as appropriate
@robfrawley
Copy link
Contributor Author

robfrawley commented Jul 22, 2017

@nicolas-grekas I know #23603 is still fluid and unreviewed, but for the purpose of the documentation PR I am working on symfony/symfony-docs#8209, everything in this PR should be fairly solid at this point without any drastic changes, right? (Just want to confirm I'm not wasting effort documenting something that might need to change.)

@nicolas-grekas
Copy link
Member

Thank you @robfrawley.

@nicolas-grekas nicolas-grekas merged commit f0d0c5f into symfony:3.4 Jul 22, 2017
nicolas-grekas added a commit that referenced this pull request Jul 22, 2017
…e) prune method and prune command (robfrawley)

This PR was merged into the 3.4 branch.

Discussion
----------

[Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #21764, #21764 (comment)
| License       | MIT
| Doc PR        | symfony/symfony-docs#8209

As requested in #21764 (comment), this PR adds a `prune()` method to [`FilesystemTrait`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/FilesystemTrait.php). This placement seems reasonable as it exposes the method in [`FilesystemAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php) and [`FilesystemCache`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Simple/FilesystemCache.php).

The return value is a `bool` representing either a partial or complete failure (when `false`) *or* complete success (when `true`).

Once the API for the `prune` method is confirmed, I'll introduce a documentation PR, as well.

---

*Stale-detection implementation:* The file modification time is used to determine if a cache item should be pruned. This seems reasonable, given the use of [`touch` in the common trait](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/FilesystemCommonTrait.php#L90). Interestingly, though, the [`doFetch` method](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Traits/FilesystemTrait.php#L38) uses the timestamp saved at the top of the file itself to determine the stale state. Should this latter implementation be used for `prune` as well (or is the current one ok), for example:

```php
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY, \RecursiveIteratorIterator::CATCH_GET_CHILD) as $file) {
    if ($h = @fopen($file, 'rb')) {
        if ($time >= (int) $expiresAt = fgets($h)) {
            fclose($h);
            if (isset($expiresAt[0])) {
                $okay = (@Unlink($file) && !file_exists($file)) && $okay;
            }
        }
    }
}
```

Commits
-------

f0d0c5f add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command
nicolas-grekas added a commit that referenced this pull request Aug 31, 2017
…ethod (robfrawley)

This PR was merged into the 3.4 branch.

Discussion
----------

[Cache] Add (pdo|chain) cache (adapter|simple) prune method

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        | symfony/symfony-docs#8209

This is additional work toward making more cache implementations use the `PruneableInterface` contract. Specifically, this pull request focuses on `(Pdo|Chain)(Cache|Adapter)`, as suggested by @nicolas-grekas in #23451 (comment).

Commits
-------

b20a237 add (pdo|chain) cache (adapter|simple) prune method
symfony-splitter pushed a commit to symfony/cache that referenced this pull request Aug 31, 2017
…ethod (robfrawley)

This PR was merged into the 3.4 branch.

Discussion
----------

[Cache] Add (pdo|chain) cache (adapter|simple) prune method

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        | symfony/symfony-docs#8209

This is additional work toward making more cache implementations use the `PruneableInterface` contract. Specifically, this pull request focuses on `(Pdo|Chain)(Cache|Adapter)`, as suggested by @nicolas-grekas in symfony/symfony#23451 (comment).

Commits
-------

b20a237 add (pdo|chain) cache (adapter|simple) prune method
@Toflar
Copy link
Contributor

Toflar commented Sep 3, 2017

@nicolas-grekas there's some design issue here when using the TagAwareAdapter because you cannot access the inner $itemsAdapter, you cannot ask for implements PruneableInterface in such a case:

$cache = new TagAwareAdapter(new FilesystemAdapter());
// Does $cache implement Pruneable now?

I figured the easiest way would be to have a PruneableTagAwareAdapter like so:

class PruneableTagAwareAdapter extends TagAwareAdapter implements PruneableInterface
{
    /**
     * @return bool
     */
    public function prune()
    {
        return $this->itemsAdapter->prune();
    }
}

However, the $itemsAdapter property is private so I would need to reimplement everything.
Can we improve this by either making the properties of TagAwareAdapter protected or have it implement PruneableInterface and check itself on $this->itemsAdapter again? Wdyt?

@robfrawley
Copy link
Contributor Author

robfrawley commented Sep 3, 2017

@Toflar Looks like your concern is reasonable, but it is generally better to open a new issue/pr than to comment on a closed one, as it removes visibility of the issue from anyone not directly involved in the existing pr, and not everyone actually follows-up on comments to closed issues/prs. :-)

That said, why not just make the adapter prune-aware instead of adding complexity with an additional interface:

class TagAwareAdapter implements PruneableInterface
{
    /* ... */

    /**
     * @return bool
     */
    public function prune()
    {
        if ($this->itemsAdapter instanceof PruneableInterface) {
            return $this->itemsAdapter->prune();
        }

        return false;
    }
}

@Toflar
Copy link
Contributor

Toflar commented Sep 3, 2017 via email

nicolas-grekas added a commit that referenced this pull request Sep 4, 2017
…lar)

This PR was submitted for the master branch but it was merged into the 3.4 branch instead (closes #24075).

Discussion
----------

Implemented PruneableInterface on TagAwareAdapter

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | See comment on #23451
| License       | MIT
| Doc PR        | Added a comment on symfony/symfony-docs#8209

The `ChainAdapter` already delegates the `prune()` calls. The `TagAwareAdapter` is a wrapping adapter too and should delegate the `prune()` calls just the same.

Commits
-------

b635b62 Implemented PruneableInterface on TagAwareAdapter
This was referenced Oct 18, 2017
private $cacheCommandServiceId;
private $cachePoolTag;

public function __construct($cacheCommandServiceId = 'cache.command.pool_pruner', $cachePoolTag = 'cache.pool')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure this is broken right now as cache.command.pool_pruner doesn't exist.

nicolas-grekas added a commit that referenced this pull request Oct 28, 2017
…ommand service id (kbond)

This PR was merged into the 3.4 branch.

Discussion
----------

[FrameworkBundle] fix CachePoolPrunerPass to use correct command service id

| Q             | A
| ------------- | ---
| Branch?       | 3.4
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #23451 (comment)
| License       | MIT
| Doc PR        | n/a

#23624 broke #23451.

Commits
-------

14c62da fix CachePoolPrunerPass to use correct command service id
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Jan 23, 2018
…dapter|simple) prune method and prune command (robfrawley, javiereguiluz)

This PR was merged into the 3.4 branch.

Discussion
----------

[Cache] Document (filesystem|phpfiles|pdo|chain) cache (adapter|simple) prune method and prune command

This PR documents the changes introduced in symfony/symfony#23451 and symfony/symfony#23603:

- The addition of [`PruneableInterface`](https://github.com/symfony/cache/blob/master/PruneableInterface.php)
- The variouse, concrete [`PruneableInterface::prune()`](https://github.com/symfony/cache/blob/master/PruneableInterface.php#L22) implementations in [`ChainAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/ChainAdapter.php), [`FilesystemAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php), [`PdoAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/PdoAdapter.php), [`PhpFilesAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php),[ `ChainCache`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Simple/ChainCache.php), [`FilesystemCache`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Simple/FilesystemCache.php), [`PdoCache`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Simple/PdoCache.php), [`PhpFilesCache`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Simple/PhpFilesCache.php), and [`TagAwareAdapter`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php).
- The addition of [`CachePoolPruneCommand`](https://github.com/symfony/symfony/blob/master/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php), invokable via `cache:pool:prune`. This command iterates over all services tagged `cache.pool` and calls the [`PruneableInterface::prune()`](https://github.com/symfony/cache/blob/master/PruneableInterface.php#L22) method on those that implement [`PruneableInterface`](https://github.com/symfony/cache/blob/master/PruneableInterface.php)

Additionally, some language changes and cleanup has been implemented for the various cache docs. Of note are the following changes:

- Additional `note` blocks for all caches that implement [`PruneableInterface`](https://github.com/symfony/cache/blob/master/PruneableInterface.php)
- Addition of `prune()` description and usage example on the chain adapter
- Addition of a `tip` about achieving better performance with the filesystem adapter by utilizing `tmpfs` or another ram disk solution
- Fix for an incorrect `use` statement in the PHP array cache adapter code example
- Addition of documentation page for PHP files adapter
- Addition of a "pruning cache items" explanation and example on the main cache pools page

Commits
-------

54a1e62 Typo
1322ffd Typos and wrapped long lines
5bea1e6 Fixed a typo
eb70a36 Wrapped long lines
ea29252 document cache pruning functionality - note the addition of PruneableInterface - note the variouse, concrete PruneableInterface::prune() implementations in ChainAdapter,   FilesystemAdapter, PdoAdapter, PhpFilesAdapter, ChainCache, FilesystemCache, PdoCache,   PhpFilesCache, and TagAwareAdapter. - note the addition of CachePoolPruneCommand, invokable via cache:pool:prune. This command   iterates over all services tagged cache.pool and calls the PruneableInterface::prune()   method on those that implement PruneableInterface - rewording of some adapter text for clarity   - additional note blocks for all caches that implement PruneableInterface   - addition of prune() description and usage example on the chain adapter   - addition of a tip about achieving better performance with the filesystem adapter by utilizing tmpfs or another ram disk solution   - fix for an incorrect use statement in the PHP array cache adapter code example   - addition of documentation page for PHP files adapter   - addition of a "pruning cache items" explanation and example on the main cache pools page
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants