Problem/Motivation

In auto versioning mode, saving an edit to a workflow clears the published-version pointer, and the new version snapshot is materialized lazily: it is cut on the next instance start, or when WorkflowVersionController::list() calls currentVersion() to render the versions page.

As a result, immediately after an edit there is no new revision for running instances to migrate onto, so the Migrate action on the versions list has no target and does not appear. Opening the versions page (or starting a new instance) materializes the revision, after which the action shows up.

This is confusing: an operator who edits a workflow and wants to migrate a running instance may not see the option until some unrelated action resolves the version.

Steps to reproduce

  1. Set versioning to auto.
  2. Start an instance so it pins the current version.
  3. Edit a node's config and save.
  4. Try to migrate the running instance before opening the versions page: the Migrate action is not offered.

Proposed resolution

Make the pending version resolvable or visible consistently right after an edit rather than depending on a page render or a new instance start. Options to weigh: eagerly cut the snapshot on save in auto mode, or have the migrate entry point resolve the current version the way the versions page already does.

Remaining tasks

Decide the approach, implement, add a test.

Issue fork orchestra-3611036

Command icon 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

mably created an issue. See original summary.

mably’s picture

Problem

A workflow version revision is currently materialized (a save on orchestra_workflow_version) as a side effect of reading. resolveVersion() cuts a revision and is reached not only from an instance start and an explicit publish(), but also from WorkflowVersionController::list(): merely loading the versions page calls currentVersion(), which materializes.

Meanwhile the instance-side 'Migrate to current' affordances (InstanceListForm, OrchestraUiController::instanceMigrate()) read the bare pointer via publishedVersion(), which never materializes. In auto mode an edit clears that pointer (invalidate()), so those affordances disappear until an instance start or a versions-page view re-cuts and repopulates the pointer. That is the reported symptom: the Migrate action is missing right after an edit until the versions page cuts the new version.

Invariant

A version revision should be cut only when an instance pins to it: on an instance start or on an explicit migration, never as a side effect of viewing a list or the versions page. Display and gating should compare the live shape's hash to materialized versions' hashes rather than materialize.

Proposed resolution

Manager (WorkflowVersionManager): add cut-free, hash-based queries and keep materialization only on the two pinning events.

  • currentHash(): the live executable-definition hash, reusing the existing executableHash(); no cut.
  • currentVersionId(): memoized per workflow; the latest version revision id when its hash equals currentHash(), else NULL (the live shape is edited but not yet cut). Mirrors the resolveVersion() dedup without the save.
  • isInstanceCurrent(): cut-free and mode-aware; auto compares the instance pinned version to currentVersionId(), manual to the published pointer, off is always current.
  • migrationTarget(): mode-aware resolver used only at a migration action, where materializing is legitimate (auto resolves and cuts the current shape then, manual returns the published version, off returns NULL).

Versions page (WorkflowVersionController::list): stop calling currentVersion() on load; mark a listed version Current by hash match; when no materialized version matches the current shape, show a notice that the current shape is not versioned yet and will be cut on the next start or migration, plus a 'migrate running instances to the current shape' action that cuts on that explicit click.

Instance list and controller: gate the 'Migrate to current' link and mark the current version via isInstanceCurrent() (no cut on render); resolve the migration target via migrationTarget() at the actual migrate click.

Performance

  • Versions page: net faster; removes the save, the revision insert, the key-value write and the per-workflow lock that ran on a GET after an edit, replaced by one sha256 compared to already-loaded revisions' hashes.
  • Instance list: replaces one key-value read per distinct workflow with a memoized currentVersionId() (one cached config load, one version-entity load, one sha256), then integer compares per instance; no per-instance queries and no N+1.
  • executableHash() is pure CPU (sha256 of the JSON of tenant, start node, nodes and flows), memoized per workflow.
  • Instance start and migration are unchanged.

Tests

  • No cut on read: after an edit, loading the versions list and calling isInstanceCurrent() leave the orchestra_workflow_version revision count unchanged.
  • Cut on pin: the revision count increases by exactly one when a new instance starts on the edited shape and when an instance is migrated to current.
  • isInstanceCurrent() truth table across auto, manual and off; migrationTarget() materializes only in auto and only when called.

mably’s picture

Status: Active » Needs review

  • mably committed c7682c60 on 1.x
    task: #3611036 Auto mode: the target version materializes lazily, so the...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.