Developer notes
How a request runs
Section titled “How a request runs”init.phpruns while the add-ons load, at priority 100. The session and storefront are known; language, currency, route and user are not.Request::bypassReason()looks at the URL and the session. Unknown means bypass.Request::key()builds an HMAC (with the store’scrypt_key) of host, scheme, storefront, company, normalised URL, what decides the language (session choice, browser language), the session currency, device class, WebP support and crawler flag.- A valid file is sent, with the visitor’s form token put in, and the request ends. The other add-ons never load.
- On a miss,
before_dispatch(priority 99999) decides whether the render may be stored and starts an output buffer. Block cache is off for that render, so every product of the page passes throughget_products_post. - The
completehook checks the response and stores it.
Language is never guessed: the same inputs give the same core result, so the inputs form the key. sl and currency
in a URL always bypass, because core must write the choice to the session.
What must be true to store a page
Section titled “What must be true to store a page”Dispatch on the list and section on; start of request: no merchant-listed session key, no advertising parameter, no
unknown cookie; end of request: status 200, index.tpl, HTML content type, complete document, no notification, no PHP
message, session still acceptable, no cookie set except the session cookie, no session id and no visitor IP in the page,
no form token other than the visitor’s, no product purged during the render, no Recently viewed block for a visitor
with history.
Response headers are not stored, except Content-Security-Policy, X-Frame-Options, Strict-Transport-Security,
Referrer-Policy, Permissions-Policy and X-Content-Type-Options.
If your add-on writes to the session
Section titled “If your add-on writes to the session”Any session key that is not on the list stops the cache for that visitor, and the admin page names the key. That is the safe result. If the key has no effect on pages, list it in Additional safe session keys.
If your add-on prints per-visitor content
Section titled “If your add-on prints per-visitor content”Print it from AJAX or JavaScript after load. What the core 4.21 Full page cache needs also works here. Do not read a cookie in a template: a visitor with that cookie never creates a stored page, but does receive one.
Add-ons that must see every request
Section titled “Add-ons that must see every request”schemas/kv_full_page_cache/compat.php lists two groups:
late:access_restrictions,kv_bot_country_blocker. Pages are sent inbefore_dispatch, after all add-ons have loaded.off:age_verification. The cache stays off.
Pseudo-cron style work that runs on storefront page views does not run on a cache hit.
Purges
Section titled “Purges”db_query_executed watches writes. schemas/kv_full_page_cache/invalidation.php lists product tables (the statement must
name product_id, otherwise all pages are dropped), shared tables whose product rows count as product changes, and global tables. Purges run once at the end of the request. Writes
that bypass db_* are not seen; the page lifetime covers them.
On a stored product page view the add-on still records the recently viewed list and popularity. Other server side work of a product page does not run, the same as under the core Varnish cache.
var/kv_full_page_cache/generation current generationvar/kv_full_page_cache/g<generation>/aa/<key>.kvc magic line, JSON meta line, gzip bodyvar/kv_full_page_cache/warm.json warmer progressTables: ?:kv_fpc_entries, ?:kv_fpc_tags, ?:kv_fpc_purges, ?:kv_fpc_stats.
Classes (Tygh\Addons\KvFullPageCache): Engine, Request, Store, Invalidator, Warmer, Stats, Dashboard,
Conflicts, Config, License\Client, Upgrade\Synchronizer.
Hooks used
Section titled “Hooks used”db_query_executed, before_dispatch, dispatch_before_display, render_block_pre, get_products_post,
get_product_data_post, complete, clear_cache_post, update_product_amount. All exist with the same arguments in 4.17.2 and 4.21.2.
addon.xml uses priority 100 on purpose: everything loaded after it is skipped on a hit. init.php loads func.php
itself, because core loads it after init.php and a query in between already fires db_query_executed.