JustFlows

La documentation est uniquement en anglais pour le moment. Le reste du site suit votre langue.

Caching

jf-cache drivers, shared plugin cache stores, what is cached per site, headers, CDN purge, stats, clear, and the plugin cache API.

8 minutes de lecture

Justflows ships jf-cache so hot paths skip the database. Redis is not required; a plugin can add a shared store such as Redis when several processes must share the cache. Configure in .env or Tools → Performance suite. Full narrative: docs/CACHE.md in the platform repo.

Drivers

  • filesystem (default) — survives process restart; directory CACHE_DIR.
  • memory — per process only.
  • plugin:<pluginId>.<storeId> — a plugin cache store, shared by every process. Core ships no external driver; an unknown CACHE_DRIVER falls back to filesystem. The old redis value and CACHE_REDIS_URL were removed in 0.4.2.
  • CACHE_ENABLED=0 — always run the producer, never store.

Plugin cache stores

From Justflows 0.4.2, a plugin activated on the main site can offer a store that every process shares, so entries and invalidations reach every worker or machine. Pick it under Tools → Performance suite → Driver, or set CACHE_DRIVER=plugin:<pluginId>.<storeId> in every process's .env. Every process must use the same driver and store settings, which the plugin reads from its own configuration. Tools, Site Health, and Diagnostics show the store's status.

SituationWhat happens
Before the store is registered (startup)The cache is bypassed: reads miss and writes are skipped.
Plugin inactive, or active only on another siteBypassed, shown as Unavailable in Tools and as a Site Health warning.
The store cannot be configuredBypassed, with the plugin's message in Tools and Diagnostics.
A read fails or takes longer than 2 sThat read is a miss.
A write failsThat write is skipped.
A delete, invalidate, or clear failsBypassed until a full clear of the store succeeds (retried at most every 5 s), so no process serves an entry whose invalidation was lost.

Pages keep rendering during an outage; they are just not cached. After switching away from a plugin store and back, use Clear cache now.

Layers

PrefixWhatInvalidated when
page:html:Full public HTMLContent, theme, menu, settings, CSS provider
content:Published items and alternatesContent save/delete
theme:mods:Customizer modsDesign/theme save
menus:NavigationMenu edits
css:provider:Active framework assetsProvider activate/delete
security-headers:configHeader policySecurity save (short TTL)

Every key carries the site id, so one site is never served another's cached page. The filesystem driver writes each site's entries under .cache/<siteId>/. A publish clears that site's folder only, and removing a website removes it.

Preview (?preview) and logged-in editors bypass page cache. Responses may include X-Jf-Cache: hits=… and X-Jf-Page-Cache: HIT|MISS|BYPASS.

Unversioned public assets

Hand-authored scripts and styles under public/ (/js/site-nav.js, /js/site-chrome.js, …) are served with Cache-Control: no-cache rather than a day-long max-age: they sit at stable, unversioned URLs, so a long TTL pinned stale copies after an update. no-cache still keeps the file cached and revalidates cheaply against the ETag (304). Content-hashed admin bundles keep their long cache lifetime.

While browser cache is off (the default on a fresh install), public HTML pages send Cache-Control: no-cache and CDN-Cache-Control: no-store. A CDN in front of the site then does not hold pages, so a change in the admin, such as a new site icon, shows on the next request. Turn browser cache on under Tools → Performance suite to let browsers and the CDN keep pages for JF_BROWSER_CACHE_HTML_MAX_AGE seconds.

Cache-Control per content type and post

Admin → Content Types gives each cacheable type a Cache-Control setting: inherit the site default, never cache (private, no-store), or a validated custom header. A single post or page can override it under Advanced; the override follows drafts, revisions, and translations, and a published post keeps its live policy until the draft is published.

The order is: core privacy rules, then the post, then the content type, then the site default. Private and no-store policies bypass the shared page cache and deployed static pages and are left out of new exports; a public max-age also caps how long the page cache keeps the page. Saving a policy clears the page and content caches and purges the CDN. The built-in Account type is always private and has no override (migration 0046_content_type_cache_control).

CDN purge

When revalidation clears pages, content, menus, theme, CSS, or site context, Justflows also tells the CDN to drop that site's cached pages (https://<hostname>/* for every hostname of the site). Connect the CDN under Admin → Settings → CDN. A CDN failure is logged and never fails the save.

ProviderFields
Bunny.netAccount API key (required), pull zone ID (optional, for a full-zone purge)
  • The connection is saved on the platform site. The API key is encrypted with APP_SECRET, never returned, and shown only by its last four characters.
  • Test connection checks the credentials. Purge this site clears the site at the CDN by hand. Turning the connection off keeps it without purging.
  • A customer site in a multisite installation does not get the connection form. It can still purge its own hostnames through the platform connection.
  • With no connection turned on, every site falls back to BUNNY_API_KEY and BUNNY_PULL_ZONE_ID in .env. Without either, only the server cache is cleared.

Clear and inspect

  • Tools → Clear cache now (no restart).
  • POST /api/cache/clear (administrator).
  • justflows cache clear.
  • GET /api/cache/stats and Tools → Object cache (hits, misses, hit rate, key count).
  • Site Health includes an object-cache check.
  • LOG_LEVEL=debug logs HIT/MISS lines.

API for core and plugins

Preferred: remember(key, ttlSeconds, fn) — read-through with in-flight deduplication. Also get, set, delete, invalidate(prefix), clear. Plugins only see plugin:{id}: keys via ctx.cache. ctx.cache.registerStore({ id, label, create }) offers a backend for the whole cache (needs the cache:store permission, main site only, SDK 0.1.9); see Plugins.

ts
const menu = await ctx.cache.remember("primary", 300, () => loadMenu());

Selective revalidate: CACHE_REVALIDATE_ENABLED and CACHE_REVALIDATE_OBJECTS (pages, content, menus, theme, cssProviders, site). Action cache.revalidated fires when it completes. Related admin routes also exist under /api/performance/*.