Skip to content

feat(governance): add id-based workflow instance states endpoint with optional task-transition filter#30164

Open
yan-3005 wants to merge 1 commit into
mainfrom
workflow-instance-states-by-instance-id-endpoint
Open

feat(governance): add id-based workflow instance states endpoint with optional task-transition filter#30164
yan-3005 wants to merge 1 commit into
mainfrom
workflow-instance-states-by-instance-id-endpoint

Conversation

@yan-3005

@yan-3005 yan-3005 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • New endpoint: GET /v1/governance/workflowInstanceStates/workflowInstanceId/{workflowInstanceId} — id-based lookup for stage transitions of a single workflow instance.
  • Fixes a latent silent-empty bug: the existing name-based endpoint filters by entityFQNHash(workflowDefinitionName, instanceId) and returns empty after a WorkflowDefinition rename. Id-based query bypasses the hash by reading the workflowInstanceId column directly (indexed).
  • Optional filter ?onlyTaskTransitions=true narrows the response to stages driven by a user-task transition (generic across any workflow with task nodes; identified by <stageName>_transitionId in stage.variables).
  • Existing name-based endpoint left unchanged for backwards compatibility.

Why now

UI needs to render an activity timeline on the task detail panel (Requested → Assigned → Approved → Granted → Revoked) from a single API call, without knowing workflow-definition names and without breaking when the definition is renamed. Task payload already carries workflowInstanceId (UUID) — this endpoint consumes it directly.

API contract

GET /v1/governance/workflowInstanceStates/workflowInstanceId/{workflowInstanceId}
    ?onlyTaskTransitions=true|false   (default: false)
  • Default: every stage the workflow entered (raw).
  • onlyTaskTransitions=true: only rows whose stage.variables contains <stageName>_transitionId. Written by user-task nodes when a user resolves the task.

Test plan

  • mvn -pl openmetadata-service test -Dtest=WorkflowInstanceStateResourceTest → 4 tests pass.
  • mvn spotless:check -pl openmetadata-service,openmetadata-integration-tests → clean.
  • Full IT run of test_WorkflowInstanceStatesByInstanceIdEndpoint in a stack-up environment.
  • Manual: create a workflow, trigger an entity through it, hit both endpoints, verify default matches name-based endpoint, verify onlyTaskTransitions=true returns strict subset.

🤖 Generated with Claude Code

Greptile Summary

This PR adds direct workflow-instance history lookup with optional task-transition filtering. The main changes are:

  • A new ID-based workflow-instance-state endpoint.
  • Optional filtering by stage transition variables.
  • Unit and integration coverage for the new API.

Confidence Score: 4/5

The open-task integration path fails before a transition is recorded, and instance history retrieval has no response bounds.

  • The integration test expects _transitionId while the task is still open.
  • Long-running instances can make the endpoint load and serialize an excessive number of states.
  • Direct ID filtering and timestamp ordering are preserved by the repository query.

WorkflowDefinitionResourceIT.java and WorkflowInstanceStateResource.java

Important Files Changed

Filename Overview
openmetadata-service/src/main/java/org/openmetadata/service/resources/governance/WorkflowInstanceStateResource.java Adds direct instance lookup and task-transition filtering, but returns the complete history without bounds.
openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/WorkflowDefinitionResourceIT.java Adds endpoint coverage but expects a transition before the open approval task has been resolved.
openmetadata-service/src/test/java/org/openmetadata/service/resources/governance/WorkflowInstanceStateResourceTest.java Adds mocked coverage for default retrieval, filtering, null stage data, and empty results.

Reviews (1): Last reviewed commit: "Add id-based workflow instance states en..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Context used:

  • Context used - CLAUDE.md (source)
  • Context used - AGENTS.md (source)

…sition filter

Adds GET /v1/governance/workflowInstanceStates/workflowInstanceId/{workflowInstanceId}
returning the full stage-transition timeline for a workflow instance keyed by UUID.

Why:
- Existing name-based endpoint filters via entityFQNHash(workflowDefinitionName,
  instanceId). Renaming a WorkflowDefinition invalidates historical hashes and
  silently returns empty results. Id-based query bypasses the hash entirely by
  reading the workflowInstanceId column directly.
- Task payloads carry workflowInstanceId (UUID). Callers should not have to
  resolve workflowDefinitionId -> name via a second round-trip, and should not
  break when a workflow definition is renamed.

Filter:
- Default response returns every stage the workflow entered (generic - works
  for any workflow definition).
- Pass onlyTaskTransitions=true to narrow to stages driven by a user-task
  transition. Fingerprint: stage.variables contains <stageName>_transitionId,
  written by user-task nodes when the user resolves the task. Applies to any
  workflow with task nodes; not DAR-specific.

Existing name-based endpoint left unchanged for backwards compatibility.

Tests:
- Unit: WorkflowInstanceStateResourceTest (4 tests: default returns all,
  filter narrows, malformed rows filtered without crash, empty result).
- IT: test_WorkflowInstanceStatesByInstanceIdEndpoint in
  WorkflowDefinitionResourceIT - spins up a tag-approval workflow, extracts
  the resulting task's workflowInstanceId, hits both default and filtered
  variants of the id-based endpoint, asserts default == name-based endpoint
  and filtered is a strict subset containing only stages with the
  <stageName>_transitionId fingerprint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 17, 2026 06:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

@github-actions

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

Comment on lines +6704 to +6708
assertTrue(
filteredData.size() > 0,
"filtered response should include at least the currently-open user-task stage");

for (int i = 0; i < filteredData.size(); i++) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Open Task Has No Transition Yet

The test queries the filtered history while approvalTask is still open. Its _transitionId is persisted only when the task is resolved and the stage ends, so the filter removes the only task stage and filteredData is empty. Resolve the task before this request, or expect no task transitions while it remains open.

Context Used: CLAUDE.md (source)

new OperationContext(Entity.WORKFLOW_DEFINITION, MetadataOperation.VIEW_ALL);
ResourceContextInterface resourceContext = ReportDataContext.builder().build();
authorizer.authorize(securityContext, operationContext, resourceContext);
List<WorkflowInstanceState> states = repository.listAllStatesForInstance(workflowInstanceId);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Instance History Is Unbounded

This endpoint loads and serializes every state for the instance without a limit or time range. A long-running or looping workflow can accumulate enough rows to create a slow response and significant service memory pressure; retain the existing endpoint's pagination or timestamp bounds for this ID-based lookup.

Context Used: CLAUDE.md (source)

@gitar-bot

gitar-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown
Code Review ✅ Approved

Implements an ID-based lookup for workflow instance states to improve UI timeline rendering and prevent issues with workflow definition renames. The implementation includes an optional task-transition filter and maintains compatibility with the existing name-based endpoint.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants