After updating to 8.2.1 from 8.1.10 on our Acquia Cloud based site, the log files began filling with error like:
Warning: apcu_store(): Unable to allocate memory for pool. in Drupal\Core\Cache\ApcuBackend->set()...
The settings.conf initially had memcache (dev branch which works with Acquia) configure with:
$settings['memcache']['servers'] = $conf['memcache_servers'];
$settings['memcache']['key_prefix'] = $conf['memcache_key_prefix'];
$settings['memcache']['bins'] = ['default' => 'default'];
// Use memcache as the default bin
$settings['cache']['default'] = 'cache.backend.memcache';
In debugging, this was converted to just:
$settings['cache']['default'] = 'cache.backend.database';
This did not stop the errors.
Notes:
- Acquia Cloud has apcu enabled but only allocates 8M to it.
- The error did not immediately appear after clearing cache but only after some normal web access (multiple users).
- Once it started, any request would start creating multiple entries in the log.
The expected behavior is what is documented in the Cache Api Configuration documentation. This says the settings default cache method should be used and not ChainedFastCache which uses APCu.
A way to "reproduce" this, is to just make the cache.backend.database mechanism the default in a Dev site's settings.php. Then run the following code in the devel php page (assumes devel / kint modules enabled):
kint(Drupal::cache('bootstrap'));
This will show that the cache class used is the ChainedFastCache class and not the expected DB Cache class.
The source of this problem was tracked down to the logic change made in the CacheFactory code for this issue:
CacheFactory::get() should not use default cache backend before cache bin defaults
This makes it so the settings file cannot override the default_backend service settings. This is not the documented behaviour.
The 'quick' fix for this was to define the cache mechanisms for each specific bin in addition to the default one. E.g.:
# https://docs.acquia.com/article/drupal-8-cache-backend
$settings['cache']['default'] = 'cache.backend.database';
# Force common chainedfast bins to use database.
$settings['cache']['bins']['discovery'] = 'cache.backend.database';
$settings['cache']['bins']['bootstrap'] = 'cache.backend.database';
$settings['cache']['bins']['render'] = 'cache.backend.database';
$settings['cache']['bins']['data'] = 'cache.backend.database';
$settings['cache']['bins']['config'] = 'cache.backend.database';
Not sure if the best solution is to roll back the logic change in the CacheFactory or update the documentation.
Comment | File | Size | Author |
---|---|---|---|
#23 | 2820580-22.patch | 2.04 KB | anavarre |
| |||
#22 | interdiff-16-22.txt | 1.7 KB | anavarre |
#22 | 2820580-22.patch | 0 bytes | anavarre |
#16 | interdiff-14-16.txt | 1.57 KB | anavarre |
#16 | 2820580-16.patch | 1.96 KB | anavarre |
Comments
Comment #2
dawehnerThis really reminds me of #2751847: Throw exception if the same service is injected twice in ChainedFastBackend
Comment #3
Wim LeersFirst, note that the Acquia Cloud
apcu_store()
errors are a separate matter, one we cannot fix here. See #2800605: Warn/inform users when the hosting environment has a too low limit of APCU cache + #2765271: Rationalize use of the 'discovery' cache bin, since it's stored in the limited size APCu by default for that.AFAICT this is because the
cache.bootstrap
service definition looks like this:Specifically, this part:
default_backend: cache.backend.chainedfast
. However,$settings['cache']['bins']…
should definitely override this.So, let's look at
\Drupal\Core\Cache\CacheFactory
. We see this:(Note that this is computed by
\Drupal\Core\Cache\ListCacheBinsPass
.)Specifically, this part:
. This confirms that$settings
takes precedence overdefault_backend: …
.But if we then look at the code that should make that happen:
We first look for a bin-specific override in
$settings
. If that is not set, we look atdefault_backend: …
in service definitions. If that is also not set, we use the default backend from$settings
.So, this is a slightly different order compared to what you expect. And also compared to what the documentation for
$defaultBinBackends
suggests.This was changed in #2753989: CacheFactory::get() should not use default cache backend before cache bin defaults, and it intentionally introduced this behavior. See the CR at https://www.drupal.org/node/2754947 for the full explanation. It's indeed now necessary to explicitly override a certain cache bin.
So we should update the documentation, both the docs for
\Drupal\Core\Cache\CacheFactory::$defaultBinBackends
and those at https://api.drupal.org/api/drupal/core!core.api.php/group/cache/8.2.x#co....Patch attached.
Comment #4
Wim LeersComment #5
BerdirDocs are OK I think.
Only question is if we need a better way to override the used fast backend or some other way to disable that completely even if you have apcu theoretically available? That seems pretty hard right now, the only way to do so is the constructor argument for \Drupal\Core\Cache\ChainedFastBackendFactory::__construct, for which you'd have to alter the service definition?
Comment #6
Wim LeersThis is needed so rarely, I think those people can alter the service definitions. In any case, separate issue.
Overriding individual cache bins' backends seems good enough for this case.
Comment #7
catchDocs look good to me.
Comment #8
cilefen CreditAttribution: cilefen as a volunteer commentedThere are a few typos:
"For example APCu or Memcache." is not a sentence.
There is a plurality mismatch with "mappings" and "takes".
Comment #9
Wim LeersComment #10
hardikpandya CreditAttribution: hardikpandya at Iksula commentedMaking text changes.
Comment #11
hardikpandya CreditAttribution: hardikpandya at Iksula commentedI could apply the patch, so no reroll is needed.
I have applied the patch that includes the suggested changes in the above comment.
Comment #14
anavarreReroll against 8.4.x
Comment #15
BerdirThis is a bit hard to understand, was a long sentence before and now it is twice as long.
Why don't we just keep this, and add a Note: below the example that sets the default, something like:
Note: The default does not override a default backend set on the service definition, only a bin-specific configuration overrides that. This is used to use the chainedfast backend for the boostrap, discovery and config bins.
Comment #16
anavarreTried to simplify the text as suggested in #15.
Sorry, didn't really know what to do with this.
Comment #18
Wim LeersComment #19
larowlanSuggest
The text in the current patch is still a bit disjointed.
Comment #20
moshe weitzman CreditAttribution: moshe weitzman commentedOh no, stuck on wording. C'est la vie.
Comment #22
anavarreTried to incorporate the feedback from #19 but IDK which part of the patch is still disjointed. Maybe add your suggestions directly?
Comment #23
anavarreHmm.
Comment #33
smustgrave CreditAttribution: smustgrave at Mobomo commentedFeedback from #19 appears to be addressed in #23. Patch #23 also still applies
Comment #34
Amber Himes MatzWording in #23 seems clear to me. +1 RTBC
Not sure what's going on with the test failure though.
Comment #35
Amber Himes MatzShoot, actually it does look like the patch failed to apply, see https://www.drupal.org/pift-ci-job/1007356. Needs a re-roll.
Comment #36
Amber Himes MatzYes @smustgrave is correct that the patch still applies. Sorry, I misunderstood the test results page. I've added a re-test for Drupal 9.5 so that we can get a passing test. Let's see how that goes.
The comment changes look good, we just need passing tests. Setting back to RTBC which hopefully will stick after the test run.
Comment #38
larowlanCrediting @Berdir and @cilefen for feedback that changed the patch.
Not crediting myself for a wording nit-pick that put this back 5 years. Tempted to credit @moshe weitzman for his prediction of said outcome 🧙🔮😉.
Not crediting @smustgrave and @Amber Himes Matz even though their efforts here revived a dead issue, but I do love your work fellow #bugsmashers. I have however credited you both on this fortnight's bugsmash triage meta for said efforts.
Committed to 10.1.x and backported all the way to 9.4.x to keep things consistent as there's no risk of disruption with a docs only patch.