Problem/Motivation
When creating a cache.$bin_name
service, documentation for the cache API implies (but does not assert) that the service arguments:
should be set to [$bin_name]
.
However, nothing in the code enforces this, and it's entirely possible to configure a cache service with service name and bin name different e.g:
services:
cache.foo:
class: Drupal\Core\Cache\CacheBackendInterface
tags:
- { name: cache.bin, default_backend: cache.backend.memory }
factory: cache_factory:get
arguments: [foo_bar]
This service will register fine, and appear to work fine, but will suffer from undefined behaviour; for example, its default_backend
will not be respected.
The problem can be demonstrated with the following class:
namespace Drupal\cacheproblem;
class CacheProblem {
public function __construct(CacheBackendInterface $cacheBackend) {
$this->cacheBackend = $cacheBackend;
}
public function test() {
print "Previously:\tupdate=" . $this->cacheBackend->get('update') . "\n";
$string = date('c');
$this->cacheBackend->set('update', $string);
print "Cached update:\t$string\n";
print "Now set to:\tupdate=" . $this->cacheBackend->get('update') . "\n";
}
}
With the correct memory
backend, this should not remember cached values between requests i.e. all calls should be the same as the first one.
With cache.foo
and arguments: [foo]
This response reflects the correct behaviour:
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=
Cached update: 2017-01-20T15:30:18+00:00
Now set to: update=2017-01-20T15:30:18+00:00
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=
Cached update: 2017-01-20T15:30:23+00:00
Now set to: update=2017-01-20T15:30:23+00:00
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=
Cached update: 2017-01-20T15:30:28+00:00
Now set to: update=2017-01-20T15:30:28+00:00
The cache never "warms up", because it's correctly in memory.
With cache.foo
and arguments: [foo_bar]
This response reflects incorrect/undefined behaviour, when the first argument does not match the service name:
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=
Cached update: 2017-01-20T15:29:34+00:00
Now set to: update=2017-01-20T15:29:34+00:00
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=2017-01-20T15:29:34+00:00
Cached update: 2017-01-20T15:29:38+00:00
Now set to: update=2017-01-20T15:29:38+00:00
$ drush php-eval '(new Drupal\cacheproblem\CacheProblem(\Drupal::cache("foo")))->test();'
Previously: update=2017-01-20T15:29:38+00:00
Cached update: 2017-01-20T15:29:54+00:00
Now set to: update=2017-01-20T15:29:54+00:00
The cache has (incorrectly) warmed up between requests, because it is now storing the data in a cache_foo_bar
SQL table, not in memory:
mysql> SELECT * FROM cache_foo_bar;
+--------+---------------------------+--------+----------------+------------+------+----------+
| cid | data | expire | created | serialized | tags | checksum |
+--------+---------------------------+--------+----------------+------------+------+----------+
| update | 2017-01-20T15:44:41+00:00 | -1 | 1484927081.763 | 0 | | 0 |
+--------+---------------------------+--------+----------------+------------+------+----------+
1 row in set (0.00 sec)
Proposed resolution
How this can be resolved isn't clear, but behaviour should be consistent and undefined behaviour warned about:
* Either the DI container needs to spot that the configuration is inconsistent (if that's even possible) and abort
* Or the cache & backend integration needs to be impervious to the DI service name.
Remaining tasks
1. Work out what the tasks are!
User interface changes
None.
API changes
None (this is undefined behaviour.)
Data model changes
None.