Problem/Motivation
For the https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Cache%21C... it is automatically detected if apc_fetch is available and then the apcu backend used.
This leads to stale caches when the cache is:
a) cleared via cli
b) apc.enable_cli = 0 (hence apc_fetch not available as function)
because then only the consistent backend is cleared, but the timestamp of the APC counter is not updated.
The caches will remain stale until any write on the cache fast chained backend.
Proposed resolution
We need to do a little more extensive check and use a Null or Memory Backend as fast chained cache when:
- ini_get(apc.enabled) == 1 AND apc_fetch is not available.
Therefore proposed code would be:
// Auto-Detect a possible fast backend.
if (!isset($fast_service_name)) {
if (function_exists('apc_fetch')) {
$fast_service_name = 'cache.backend.apcu';
}
// If APC is enabled, but not usable here, this means the non-cli
// request uses the apcu backend with a high probability, therefore ensure
// that timestamps are updated.
else if (ini_get('apc.enabled') == 1) {
$fast_service_name = 'cache.backend.memory';
}
}
That should solve this nicely.
This kind of detection has been used in a different way in Zend Framework:
https://github.com/krakjoe/apcu/issues/43#issuecomment-24978761
Remaining tasks
- Discuss
- Write patch
User interface changes
- None
API changes
- None
| Comment | File | Size | Author |
|---|---|---|---|
| #4 | 0001-Issue-2427861-Make-FastChainedBackend-compatible-and.patch | 1.44 KB | fgm |
Comments
Comment #1
fabianx commentedComment #2
berdirInteresting idea.
I haven't had problems with that so far, not sure if that is because I have it enabled or because a real request quickly does set data that leads to an invalidate.
This won't actually help with the installer problem, because it still leads to a lot of invalidate calls. I'm wondering if we can optimize that too, maybe in a different issue. Similar to cache tags, so that we don't send an invalidate repeatedly, until a get() happens again, or something like that.
Comment #3
berdiranother note, based on my comment in #2423591: Optimize config entity import.
The costly part is the markAsOutdated(), using memory backend would still result in all those queries.
Comment #4
fgmRolled patch as suggested. Not sure the test bots cover such cases, though.
Comment #5
fabianx commentedLooks great to me!
Comment #6
fabianx commentedBerdir: Can you review / RTBC that one?
Comment #7
wim leersThanks for the patch, @fgm! :)
Comment #8
berdirThis makes sense to me as well.
Comment #9
webchickLooks good to me, sending to catch.
Comment #10
effulgentsia commentedI'm not so sure about this:
cache.backend.memoryis only defined indevelopment.services.yml, but CLI can be used on production sites too.ChainedFastBackendcapable of being constructed with $fast_backend = NULL (not NullBackend), to cover other code flows where a single site can sometimes have the fast backend available and sometimes not, and therefore, also need that timestamp updated?Comment #11
fabianx commented1. Oh it was moved back again? It was at some point in core.services.yml ...
2. Possibly - however it might be a larger change ...
2) might indeed be cleaner - unless there is any use case where we do not want timestamps to be updated.
@Berdir: Can you think of any such use case?
Comment #12
gappleI don't think enable_cli=0 will actually cause any issues as
function_exists('apc_fetch')still returns true as long as the APCu extension exists, even if not enabled. As a result, the ChainedFastBackendFactory still returns a ChainedFastBackend and updates to lastWriteTimestamp are still written to the consistent backend.Since APC is disabled
cache.backend.apcuessentially acts as a null cache for CLI requests.PHP 5.6 + APC 4.0.7
Comment #13
xjm(Saving proposed issue credit for discussion and triage participants at LA.)
Comment #14
jhedstromGot added back to
core.services.ymlin #2501117: Add static caching for PermissionsHashGenerator::generate().Comment #16
fabianx commentedPer #12 this issue seems not to be a problem as if its disabled it acts as a NULL backend, which is fine.