Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Cache] remove implicit dependency on symfony/filesystem #33922

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
merged 1 commit into from
Oct 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 9 additions & 22 deletions src/Symfony/Component/Cache/Adapter/FilesystemTagAwareAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\FilesystemTrait;
use Symfony\Component\Filesystem\Filesystem;

/**
* Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls.
Expand All @@ -29,20 +28,15 @@
class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface
{
use FilesystemTrait {
doSave as doSaveCache;
doDelete as doDeleteCache;
doSave as private doSaveCache;
doDelete as private doDeleteCache;
}

/**
* Folder used for tag symlinks.
*/
private const TAG_FOLDER = 'tags';

/**
* @var Filesystem|null
*/
private $fs;

public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
{
$this->marshaller = $marshaller ?? new DefaultMarshaller();
Expand All @@ -57,7 +51,6 @@ protected function doSave(array $values, ?int $lifetime, array $addTagData = [],
{
$failed = $this->doSaveCache($values, $lifetime);

$fs = $this->getFilesystem();
// Add Tags as symlinks
foreach ($addTagData as $tagId => $ids) {
$tagFolder = $this->getTagFolder($tagId);
Expand All @@ -67,23 +60,25 @@ protected function doSave(array $values, ?int $lifetime, array $addTagData = [],
}

$file = $this->getFile($id);
$fs->symlink($file, $this->getFile($id, true, $tagFolder));

if (!@symlink($file, $this->getFile($id, true, $tagFolder))) {
@unlink($file);
$failed[] = $id;
}
}
}

// Unlink removed Tags
$files = [];
foreach ($removeTagData as $tagId => $ids) {
$tagFolder = $this->getTagFolder($tagId);
foreach ($ids as $id) {
if ($failed && \in_array($id, $failed, true)) {
continue;
}

$files[] = $this->getFile($id, false, $tagFolder);
@unlink($this->getFile($id, false, $tagFolder));
}
}
$fs->remove($files);

return $failed;
}
Expand All @@ -96,15 +91,12 @@ protected function doDelete(array $ids, array $tagData = []): bool
$ok = $this->doDeleteCache($ids);

// Remove tags
$files = [];
$fs = $this->getFilesystem();
foreach ($tagData as $tagId => $idMap) {
$tagFolder = $this->getTagFolder($tagId);
foreach ($idMap as $id) {
$files[] = $this->getFile($id, false, $tagFolder);
@unlink($this->getFile($id, false, $tagFolder));
}
}
$fs->remove($files);

return $ok;
}
Expand Down Expand Up @@ -137,11 +129,6 @@ protected function doInvalidate(array $tagIds): bool
return true;
Copy link
Member Author

@nicolas-grekas nicolas-grekas Oct 9, 2019

Choose a reason for hiding this comment

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

doInvalidate leaks inodes by not clearing the directory of invalidated tags, but this cannot be fixed with the current storage layout. We'd need a file listing item files instead of symlinks, as suggested in #33924. /cc @andrerom makes sense?

Copy link
Contributor

Choose a reason for hiding this comment

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

File representing cache tag where you append cache keys?

Could do that, but then:

  • more work (with race) to clean up relationship when tags are removed from an item _(unless we continue to view that as eventually consistent)
  • can it hit file limits if it only appends and never cares if cache key is already there?
  • on invalidation probably need to rename like with redis to be able to iterate and clear without race possibilities

So can work, but might present its own set of challenges.
Would it be better than replacing symlinks with just simple files that contain the cache key as value?

Copy link
Member Author

Choose a reason for hiding this comment

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

(continued in #33924 (comment))

}

private function getFilesystem(): Filesystem
{
return $this->fs ?? $this->fs = new Filesystem();
}

private function getTagFolder(string $tagId): string
{
return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
Expand Down