Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Flysystem Cached Adapter Laravel Package

league/flysystem-cached-adapter

Caching adapter for Flysystem that speeds up filesystem operations by storing metadata (like directory listings and file info) in a cache backend. Reduces repeated calls to slower storage (S3/FTP) and improves performance in read-heavy scenarios.

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require league/flysystem-cached-adapter
    

    Ensure you have a base FlySystem adapter (e.g., league/flysystem-aws-s3-v3, league/flysystem-local) already configured.

  2. Basic Setup

    use League\Flysystem\Cached\CachedAdapter;
    use League\Flysystem\Filesystem;
    use League\Flysystem\Adapter\LocalAdapter;
    
    $adapter = new LocalAdapter('/path/to/storage');
    $cache = new CachedAdapter($adapter, [
        'cache' => new \League\Flysystem\Cached\Storage\Psr6CacheStorage(
            new \Symfony\Component\Cache\Adapter\FilesystemAdapter()
        )
    ]);
    $filesystem = new Filesystem($cache);
    
  3. First Use Case Benchmark file operations (e.g., listContents(), fileExists()) before/after caching to observe performance gains. Example:

    $files = $filesystem->listContents('/');
    // Subsequent calls to `listContents()` will use cached metadata.
    

Implementation Patterns

Common Workflows

  1. Decorating Existing Adapters Wrap any FlySystem adapter (S3, FTP, Rackspace, etc.) with CachedAdapter to cache metadata (e.g., file sizes, timestamps, checksums).

    $s3Adapter = new AwsS3Adapter(...);
    $cachedS3 = new CachedAdapter($s3Adapter, ['cache' => $cache]);
    
  2. Cache Storage Backends

    • PSR-6 Caches: Use any PSR-6 compliant cache (e.g., symfony/cache, stash, predis).
      $cache = new Psr6CacheStorage(new PredisCache());
      
    • Filesystem Cache: Default fallback (stores cache in cache/ directory).
      $cache = new FilesystemCacheStorage('/path/to/cache');
      
  3. Cache Invalidation Manually clear cache for specific files/directories:

    $cache->invalidateMetadata('path/to/file.txt');
    $cache->invalidateMetadata('path/to/directory/');
    

    Or clear all cache:

    $cache->clearCache();
    
  4. Conditional Caching Disable caching for specific operations via config:

    $adapter = new CachedAdapter($baseAdapter, [
        'cache' => $cache,
        'skipCache' => ['delete', 'write*'] // Skip caching for delete/write operations
    ]);
    
  5. Integration with Laravel

    • Service Provider:
      public function register()
      {
          $this->app->singleton('filesystem.cached', function ($app) {
              $adapter = $app['filesystem']->adapter();
              return new CachedAdapter($adapter, [
                  'cache' => new Psr6CacheStorage($app['cache.store'])
              ]);
          });
      }
      
    • Filesystem Disk:
      'disks' => [
          'cached-s3' => [
              'driver' => 'cached',
              'adapter' => 's3',
              'cache' => 'array', // or 'redis', 'file', etc.
          ],
      ],
      
  6. Custom Cache Keys Override cache key generation for complex paths:

    $adapter = new CachedAdapter($baseAdapter, [
        'cache' => $cache,
        'cacheKeyGenerator' => function ($path) {
            return 'custom_prefix_' . md5($path);
        }
    ]);
    

Gotchas and Tips

Pitfalls

  1. Cache Staleness

    • Cached metadata (e.g., file sizes) may become stale if files are modified externally (e.g., via SFTP, cron jobs).
    • Mitigation: Implement a cache TTL (Time-To-Live) or use invalidateMetadata() after external writes.
      $cache->setCacheTTL(3600); // 1-hour cache expiry
      
  2. Write Operation Overhead

    • Caching adds overhead to write, delete, and rename operations because metadata must be updated.
    • Tip: Exclude write-heavy operations from caching (see skipCache config).
  3. Memory Usage

    • PSR-6 caches (e.g., Redis) can consume significant memory for large filesystems.
    • Tip: Use a disk-based cache (e.g., symfony/cache-filesystem) for high-volume systems.
  4. Concurrent Writes

    • Race conditions may occur if multiple processes write to the same file simultaneously.
    • Tip: Use a distributed lock (e.g., symfony/lock) for critical sections.
  5. Cache Key Collisions

    • Custom cacheKeyGenerator functions must avoid collisions (e.g., /path vs /path/).
    • Tip: Normalize paths (e.g., rtrim($path, '/')) in the generator.
  6. Laravel Caching Quirks

    • If using Laravel’s cache, ensure the cache driver is configured to persist across requests (e.g., avoid array driver for production).
    • Tip: Prefer file, redis, or database drivers for production.

Debugging Tips

  1. Verify Cache Hits/Misses Enable debug logging for the cache storage:

    $cache = new Psr6CacheStorage($psr6Cache, [
        'debug' => true
    ]);
    

    Check logs for CACHE_HIT/CACHE_MISS entries.

  2. Inspect Cache Contents Dump the cache storage to verify metadata:

    $cache->getCache()->getItem('path/to/file.txt')->get();
    
  3. Test Cache Invalidation Write a test to ensure invalidateMetadata() works:

    $filesystem->write('test.txt', 'content');
    $filesystem->invalidateMetadata('test.txt');
    $this->assertFalse($filesystem->has('test.txt')); // May not work; test metadata specifically.
    

Extension Points

  1. Custom Cache Storage Implement League\Flysystem\Cached\Storage\CacheStorageInterface for custom backends (e.g., database, custom Redis hashes).

  2. Event Listeners Hook into FlySystem events to invalidate cache dynamically:

    $filesystem->addListener('after.*', function ($event) {
        if ($event->getOperation() === 'write') {
            $this->cachedAdapter->invalidateMetadata($event->getPath());
        }
    });
    
  3. Cache Warmers Pre-load cache for frequently accessed files/directories during low-traffic periods:

    $filesystem->listContents('/');
    $filesystem->listContents('/assets/');
    
  4. Hybrid Caching Combine with league/flysystem-cache for file content caching:

    $adapter = new CachedAdapter(
        new CacheAdapter($baseAdapter, $cache),
        ['cache' => $metadataCache]
    );
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
besmartand-pro/php-quality-config
sentix/ai-chatbot
codifyo/ts-generator-bundle
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor