Skip to content

TaskCompatibility::resolve() lazy-loads $task->run when the passed run has no compatibility marker #636

Description

@vanducng

TaskCompatibility::resolve() loads $task->run even when the caller has already passed that run, provided the run's compatibility is null:

// src/V2/Support/TaskCompatibility.php:15
return self::normalize($task->compatibility)
    ?? self::normalize($run?->compatibility ?? $task->run?->compatibility);

When $run is given and $run->compatibility is null, the inner ?? falls through to $task->run. Every app that sets no worker-compatibility marker hits this path, because both the task and the run carry null.

Effect

RunSummaryProjector::taskWaitingForCompatibleWorker($task, $run) passes the run explicitly. It runs inside the history projection on every task dispatch, activity outcome, timer and watchdog pass. Each call then costs one extra workflow_runs query per task. In an app with Model::preventLazyLoading() enabled outside production, each call also logs or throws a lazy-loading violation for WorkflowTask::run. One short workflow run produced about 60 of them.

Reproduction

  1. Leave workflows.v2.compatibility.current unset (the default).
  2. Load a WorkflowTask fresh from the database, so the run relation is not loaded.
  3. Call TaskCompatibility::resolve($task, $task->run()->first()).
  4. $task->relationLoaded('run') is now true, and a second workflow_runs query ran.

Present on main (baf795ce) and in 2.4.5.

Suggested fix

Use the passed run when there is one, and fall back to the relation only when no run is passed:

?? self::normalize($run !== null ? $run->compatibility : $task->run?->compatibility);

I'll open a PR with this change and a regression test.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    intake:approvedCurrent issue title and body revision is approved for authority intakekind:defectA public product behavior is incorrectpriority:P1High-priority product or release riskstatus:doneDerived from the authoritative closed issue state

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions