Problem/Motivation
orchestra_token, orchestra_instance, orchestra_variable and orchestra_work_item are declared without persistent_cache, which defaults to TRUE, so their loads go through the persistent entity cache bin (memcache, redis or the database, depending on the site).
These are not read-mostly rows. The engine reads a token's state, decides from it (advance, park, consume, fire a join) and writes that decision back, often in the same millisecond. A stale read there does not merely display something old, it produces a wrong write: a token consumed with no successor, an instance completed while the entity it drives stays behind. A transient cache inconsistency becomes permanent corruption.
The exposure is real on any site whose cache bins live outside the database transaction (a shared memcache or redis server): cache writes and tag invalidations do not participate in commit or rollback, and concurrent workers (a web request, a queue worker draining an advance, an operator acting on a task) read and write the same rows.
There is also little to weigh against it. Each of these types is a single base table with a handful of columns, no revisions and no translations, so a load is one cheap query, while writes happen on nearly every step: the cache is churned as fast as it is filled.
Proposed resolution
Set persistent_cache: FALSE on the four runtime entity types. The per-request static cache still applies, only the persistent bin is bypassed: ContentEntityStorageBase::getFromPersistentCache() and setPersistentCache() both return early on the flag.
Leave orchestra_workflow_version cached: its snapshots are immutable once written, which is what a persistent cache is for. orchestra_incident is an open question, it is mutated but not in the advance path.
Whether an advance should additionally hold a per-instance lock and re-read state inside it is a separate concern, worth a follow-up if the advance path proves unguarded; the module already locks in WorkItemManager and WorkflowVersionManager.
Remaining tasks
- Add the flag to the four runtime entity types.
- Decide on orchestra_incident.
- Kernel coverage asserting the storage does not write these types to the persistent bin.
User interface changes
None.
API changes
None. Entity loads keep their signature and their per-request caching.
Data model changes
None, persistent_cache is a definition flag, not schema.
Issue fork orchestra-3613466
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #4
mably commented