- Issue created by @eswiderski
- π©πͺGermany jurgenhaas Gottmadingen
This looks more like the field "Cache tags" doesn't support tokens.
- πΊπΈUnited States eswiderski
@jurgenhaas I've actually tried with a fixed tag (without tokens, e.g. "node:77695") too, still no effect. Is there something else I'm doing wrong?
- π©πͺGermany jurgenhaas Gottmadingen
I've done some debugging, and it looks as if something with the cache handling is broken in general. But I'm not a caching expert, and we need some more general research here.
This particular issue is broken because the cache tags get processed through
$tags = array_values(DataTransferObject::buildArrayFromUserInput($this->configuration['tags']));
and that build array from user inputs interprets the given tags as yaml which means that we lose everything before the colon. So, the cache tag being invalidated is just the ID, not thenode:
part.But there is more to it: if tags are given, then this plugin calls
Cache::invalidateTags($tags);
which goes through all invalidators and all bins to invalidate the given tags. I wonder why we then need the cache backend and cache key in the config? Those aren't used in this context.This whole set of raw cache handling (read, write, invalidate) seems to be not correct. Can we find someone who could review the situation and refactor the set of action plugins?
- πΊπΈUnited States eswiderski
@jurgenhaas I was wondering about the key and backend too, agree they seem unnecessary.
- πΊπΈUnited States eswiderski
@jurgenhaas as always, appreciate your tips, which helped to hack something up!
I stripped out all of the references to cache backend and keys in CacheActionBase.php and CacheInvalidate.php. So they basically only operate with tags now. Then I switched the tags processor to a string:
from:protected function getCacheTags(): array { $tags = []; if ($this->configuration['tags'] !== '') { $tags = array_values(DataTransferObject::buildArrayFromUserInput($this->configuration['tags'])); } return $tags; }
to:
protected function getCacheTags(): ?string { $tags = ($this->configuration['tags']); $tags = trim($this->tokenService->replaceClear($this->configuration['tags'] ?? '')); return $tags; }
I'm sure there's probably a better practice approach, but it's working for me. Thanks again!
- πΊπΈUnited States luke.leber Pennsylvania
I think that Jurgen is correct in #4. When invoking the Cache Tags Invalidator Service, that's a high level API that does not need to know / care about which backend is used.
All that needs to be passed to the service is an array of strings like
node:##
and the API should be able to do the rest. - π©πͺGermany jurgenhaas Gottmadingen
I've now created an MR which removes the back-end and key properties from the raw cache invalidate action plugin. It also introduced token support for the tags and explodes the tags that may be concatenated by commas.
Please give it a try.
- Merge request !455Issue #3488848 by eswiderski, jurgenhaas, luke.leber: Cache Raw Invalidate β (Merged) created by jurgenhaas
- π©πͺGermany jurgenhaas Gottmadingen
@eswiderski, @luke.leber any chance for a review on this? I'd like to merge this before we publish the stable 2.1.0 release soon.
- πΊπΈUnited States luke.leber Pennsylvania
I'll put it on my list to do tomorrow.
- πΊπΈUnited States eswiderski
Same here, will try to test asap. Thanks again @jurgenhaas
- πΊπΈUnited States luke.leber Pennsylvania
I was able to successfully test the invalidation action.
uuid: 46349853-db2b-4cfc-822c-9ac6680f2ff1 langcode: en status: true dependencies: module: - eca_base - eca_cache id: process_jfh9njk modeller: bpmn_io label: noname version: '' weight: 0 events: Event_1bq8hvb: plugin: 'eca_base:eca_custom' label: Event_1bq8hvb configuration: event_id: test successors: - id: Activity_087tmd6 condition: '' conditions: { } gateways: { } actions: Activity_087tmd6: plugin: eca_raw_cache_invalidate label: Activity_087tmd6 configuration: tags: test_tag backend: entity key: 'values:node:1' successors: { }
# Set a cache entry to persist for 5 minutes with a tag of "test_tag".
vendor/bin/drush eval "\Drupal::cache()->set('test', 'value', time() + 300, ['test_tag']);" && echo 'Set a cache entry'# Confirm the cache entry is valid.
vendor/bin/drush eval "echo 'The cache entry is...' . (\Drupal::cache()->get('test') ? 'valid' : 'invalid');"# Invalidate the tag via an ECA action.
vendor/bin/drush eca:trigger:custom_event test && echo 'ECA invalidated the tag'# Confirm the cache entry is no longer valid.
vendor/bin/drush eval "echo 'The cache entry is...' . (\Drupal::cache()->get('test') ? 'valid' : 'invalid');"Output should be:
Set a cache entry The cache entry is...valid ECA invalidated the tag The cache entry is...invalid
My only concern here is one of performance. If token substitution happens, but yields an empty string, does that mean that this kicks in?
When empty, then the whole cache is being invalidated.
For larger sites, full cache invalidations can lead to some pretty significant performance degradation, and in some cases denial of service if the ECA workflow runs often enough.
- π©πͺGermany jurgenhaas Gottmadingen
My only concern here is one of performance. If token substitution happens, but yields an empty string, does that mean that this kicks in?
When empty, then the whole cache is being invalidated.
For larger sites, full cache invalidations can lead to some pretty significant performance degradation, and in some cases denial of service if the ECA workflow runs often enough.
That's correct, but that's by design, I guess. Just like with other means that allow you to flush all caches. There are options in the UI as well as e.g. drush that deliberately provide that feature. So does ECA.
With great power comes responsibility, doesn't it. ECA models should be created with care, so that flushing all caches doesn't happen unintentionally. I would expect that enough eyeballs are looking at such ECA models, like they would review custom code which could cause the same issue, especially on those large sites, where this really makes a difference.
@luke.leber thank you so much for the detailed testing.
Now wondering, if we should merge this bug fix or not. The fact that ECA could wipe all caches has been there from day 1.
- πΊπΈUnited States luke.leber Pennsylvania
However! when creating a brand new action (rather than starting with an old one, then patching), I get
[warning] Undefined array key "backend" CacheActionBase.php:80
printed out.I'm setting this back to NW. It looks like
Drupal\eca_cache\Plugin\Action\CacheActionBase::getCacheBackend
may need an update to cope with derivative classes that do not operate on a specific backend.As a result, I'm pretty sure that
Drupal\eca_cache\Plugin\Action::execute
needs to be refactored to do a full cache flush and not exit early viaif (!($cache = $this->getCacheBackend())) { return; }
That said, I'm not 100% sure what the right API calls should be in if tags are empty.
if (empty($tags)) { $cache->invalidateAll(); <-- definitely not this, but I'm not sure what to replace it with! }
- π©πͺGermany jurgenhaas Gottmadingen
Good catch. It looks like the access and execute callbacks need to be overridden in this action plugin. By doing so, I've also added a loop to go through all bins to invalidate all their tags, if they're empty.
- πΊπΈUnited States luke.leber Pennsylvania
This all looks good to me! I re-ran
# Set a cache entry to persist for 5 minutes with a tag of "test_tag". vendor/bin/drush eval "\Drupal::cache()->set('test', 'value', time() + 300, ['test_tag']);" && echo 'Set a cache entry' # Confirm the cache entry is valid. vendor/bin/drush eval "echo 'The cache entry is...' . (\Drupal::cache()->get('test') ? 'valid' : 'invalid');" # Invalidate the tag via an ECA action. vendor/bin/drush eca:trigger:custom_event test && echo 'ECA invalidated the tag' # Confirm the cache entry is no longer valid. vendor/bin/drush eval "echo 'The cache entry is...' . (\Drupal::cache()->get('test') ? 'valid' : 'invalid');"
with...
- A single hard-coded tag
- A single tag that was resolved by a token
- No tags (invalidate everything)
I think this one's good to go! Great stuff!
-
jurgenhaas β
committed 89fbfa0d on 2.1.x
Issue #3488848 by jurgenhaas, eswiderski, luke.leber: Cache Raw...
-
jurgenhaas β
committed 89fbfa0d on 2.1.x
- π©πͺGermany jurgenhaas Gottmadingen
Thank you so much for all the careful testing and the great feedback, really much appreciated.
-
jurgenhaas β
committed fc032d41 on 2.0.x
Issue #3488848 by jurgenhaas, eswiderski, luke.leber: Cache Raw...
-
jurgenhaas β
committed fc032d41 on 2.0.x
- π©πͺGermany jurgenhaas Gottmadingen
Merged and back ported to 2.0.x as well.
Automatically closed - issue fixed for 2 weeks with no activity.