Skip to content

Cache Management

Flow ID: SY-07 | Module(s): job, helpers | Complexity: Low

Business Overview

Cache management ensures the application's file-based cache does not grow unbounded and can be selectively or fully cleared. Two complementary jobs handle this: one for on-demand or scheduled full/partial cache clearing, and another that monitors disk usage and auto-purges when a configurable size limit is exceeded. These jobs only act on file-based caching; Redis-backed deployments skip the size-monitoring job entirely.

Cache Tier Architecture

The application uses a 4-tier cache architecture:

┌─────────────────────────────────────────────────────────────────┐
│ L0: InMemory (per-request)                                      │
│   Static arrays within services. Lifetime = single PHP request. │
│   No serialization cost. Used for repeated lookups.             │
├─────────────────────────────────────────────────────────────────┤
│ L1: APCu / SHM (pod-local)                                     │
│   Shared memory on the same server. Fast, but not distributed.  │
│   Lost on PHP-FPM restart. Used for hot config and registry.    │
├─────────────────────────────────────────────────────────────────┤
│ L2: File / Redis (distributed)                                  │
│   Configurable via APP_CACHE_L2_ADAPTER (FileAdapter or Redis). │
│   Default TTL: 86400s (1 day). Survives restarts.               │
│   Search TTL: 43200s (12h). SEO TTL: 864000s (10 days).        │
├─────────────────────────────────────────────────────────────────┤
│ Session: Redis (7-day TTL)                                      │
│   Customer session data. Shared across pods in clustered envs.  │
└─────────────────────────────────────────────────────────────────┘

L2 TTL defaults:

CategoryTTLDescription
Default86,400s (1 day)Most cached data
Search43,200s (12 hours)Search results and facets
SEO864,000s (10 days)Meta tags, canonical URLs, sitemap data

PSCache wrapper: The Pscache library provides dependency tracking and language-aware cache keys (keys are suffixed with the active language abbreviation, e.g., /el/, /en/). This ensures multilingual content is cached separately per language.

Healthz endpoint: The application health check endpoint verifies both L1 and L2 cache health, returning degraded status if either tier is unavailable.

Development mode: When development mode is active, all cache expiration is set to TTL = -1 (disabled), effectively bypassing all caching layers.

Cache Invalidation Groups

10+ module invalidation groups are available via clearCache():

GroupModels/Keys Cleared
products13 product-related models (pricing, stock, attributes, variations, etc.)
searchsearch_model, lines_model
seometatags_model, seo_lib
cmscategories_model, subcontent_model
blogblog_category_model, blog_author_model, blog_tags_model, blog_model
slidersslideshow_group_model, sliders_model, slide_model
mapsmaps_model
promopromo_model
settingssettings, registry, registry_model, transporters_model, cookies_model
product_bundlesproduct_bundle_storage_model
cloudflareSpecial: calls clearCloudflareCache() (Cloudflare zone purge)
allFull purge via Pscache::delete_all()

Architecture

AdvClearSiteCache (job)        AdvClearCacheOnLimit (job)
       |                               |
       v                               v
JobClearCacheTrait             Check cache_l2_adapter
       |                         (FileAdapter only)
       v                               |
clearCache() helper                    v
  (pscache_helper)             du -s -k on cache path
       |                               |
       v                               v
clearPsCacheArray()            If over limit -> clearCache()
       |                               |
       v                               v
  Pscache                         Pscache
  delete_all() or                 delete_all()
  delete_group()

Key Components

ComponentPathRole
AdvClearSiteCacheecommercen/job/libraries/AdvClearSiteCache.phpJob: clears specific or all cache groups
AdvClearCacheOnLimitecommercen/job/libraries/AdvClearCacheOnLimit.phpJob: monitors file cache size, clears when over limit
JobClearCacheTraitecommercen/job/libraries/JobClearCacheTrait.phpShared trait providing clearCache() delegation
clearCache()ecommercen/helpers/pscache_helper.phpHelper: routes cache option to model-group clearing
clearPsCacheArray()ecommercen/helpers/pscache_helper.phpHelper: deletes all or specific cache groups via Pscache
clearCloudflareCache()ecommercen/helpers/pscache_helper.phpHelper: purges Cloudflare CDN cache via zone API
Pscacheapplication/libraries/Pscache.phpCache library wrapping PSR-6 CachePool
Client stubsapplication/modules/job/libraries/ClearSiteCache.php, ClearCacheOnLimit.phpEmpty extension points for client overrides

Code Flow

AdvClearSiteCache

  1. Entry: executeCommand(['cache' => $option]) where $option is an optional cache group name.
  2. Delegation: Calls $this->clearCache($option) via JobClearCacheTrait.
  3. Trait logic: If no option provided, defaults to 'all'.
  4. Helper dispatch: Calls global clearCache($option) from pscache_helper.php.
  5. Group resolution: A switch statement maps the option string to an array of model group names:
    • 'maps' -> ['maps_model']
    • 'cms' -> ['categories_model', 'subcontent_model']
    • 'blog' -> ['blog_category_model', 'blog_author_model', 'blog_tags_model', 'blog_model']
    • 'sliders' -> ['slideshow_group_model', 'sliders_model', 'slide_model']
    • 'promo' -> ['promo_model']
    • 'product_categories_vendors' -> ['product_category_model', 'vendors_model']
    • 'settings' -> ['settings', 'registry', 'registry_model', 'transporters_model', 'cookies_model']
    • 'seo' -> ['metatags_model', 'seo_lib']
    • 'products' -> 13 product-related models
    • 'search' -> ['search_model', 'lines_model']
    • 'product_bundles' -> ['product_bundle_storage_model']
    • 'cloudflare' -> Special path: calls clearCloudflareCache() directly (Cloudflare zone purge)
    • 'all' (default) -> Empty array, which triggers Pscache::delete_all()
  6. Cache deletion: clearPsCacheArray($models) calls either $pscache->delete_all() (when models is empty) or iterates and calls $pscache->delete_group(group: $model) for each model.

AdvClearCacheOnLimit

  1. Entry: executeCommand([]) -- no options.
  2. Adapter check: Reads cache_l2_adapter config. If not FileAdapter::class, logs info and returns (no-op for Redis).
  3. Size measurement: Executes du -s -k <cache_path> via shell exec() to get cache directory size in KB.
  4. Limit comparison: Compares measured size against getCacheSizeLimit() (config cache_l2_size_limit, in GB, converted to KB for comparison).
  5. Conditional clear: If size exceeds limit, calls $this->clearCache() (via trait -> full cache purge).
  6. Logging: Logs current cache size in GB and whether action was taken.

Data Model

No database tables are involved. Cache operates on the filesystem (or Redis, but the limit job only monitors files).

Config KeySourceDescription
cache_l2_adapterapplication/config/cache.phpAdapter FQCN (FileAdapter or RedisAdapter)
cache_l2_connectionapplication/config/cache.phpFile path or Redis connection string
cache_l2_size_limitapplication/config/cache.phpMax cache size in GB (default: 5)
cache_l2_default_expiresapplication/config/cache.phpDefault TTL in seconds (default: 86400)

Configuration

Environment Variables

VariableDefaultDescription
APP_CACHE_L2_ADAPTERFileAdapter::classCache adapter class
APP_CACHE_L2_CONNECTION../cache/Cache storage path
APP_CACHE_L2_SIZE_LIMIT5Size limit in GB (5 standard, 10 for dedicated)
APP_CACHE_L2_PREFIX''Cache key prefix

Job Options

JobOptionTypeRequiredDescription
AdvClearSiteCachecachestringNoCache group to clear (e.g., products, settings, all)
AdvClearCacheOnLimit(none)----No options; auto-detects adapter and path

Cache Group Names

Valid values for the cache option: maps, cms, blog, sliders, promo, product_categories_vendors, settings, seo, products, search, product_bundles, cloudflare, all.

Client Extension Points

  • Job override: Create ClearSiteCache or ClearCacheOnLimit in application/modules/job/libraries/ extending the Adv* base class to add custom cache groups or logic.
  • Cache group mapping: The clearCache() helper in pscache_helper.php can be overridden in client repos by defining the function before the helper loads.
  • Cloudflare integration: Clients with Cloudflare can use the cloudflare cache option to purge CDN cache via the Cloudflare library.

Business Rules

  1. File adapter only: AdvClearCacheOnLimit is a no-op when cache_l2_adapter is not FileAdapter. It silently logs and returns.
  2. Default is full purge: When no cache group is specified, AdvClearSiteCache clears all cached data.
  3. Size limit in GB: The cache_l2_size_limit config is in GB. Default is 5 GB globally; dedicated clients may use 10 GB.
  4. Shell dependency: AdvClearCacheOnLimit depends on the du command being available in the system PATH.
  5. Language-scoped path: Cache path includes the language abbreviation suffix (e.g., ../cache/el/).
  6. Development mode: In development, all cache expiration is set to -1 (disabled), so these jobs have limited effect.

Wiki Guide: Cache Guide -- cache adapter configuration and usage patterns