Skip to content

fix(workflows): skip PipelineServiceClient initialization during migrate#27522

Merged
yan-3005 merged 1 commit intomainfrom
ram/hotfix-migrate-pipeline-client
Apr 20, 2026
Merged

fix(workflows): skip PipelineServiceClient initialization during migrate#27522
yan-3005 merged 1 commit intomainfrom
ram/hotfix-migrate-pipeline-client

Conversation

@yan-3005
Copy link
Copy Markdown
Contributor

Why this change is needed

OpenMetadata uses Flowable as its BPMN workflow engine, which manages its own set of database tables (ACT_RE_, ACT_HI_, etc.) completely separate from the Flyway-managed schema.

Before PR #27234, the webserver initialized WorkflowHandler with DB_SCHEMA_UPDATE_TRUE, which meant Flowable ran its DDL (CREATE TABLE, CREATE INDEX, etc.) every time the server started. If the server crashed mid-startup while DDL was half-complete, some tables would be partially created. On the next restart, Flowable would try to run the same DDL again and blow up on "table already exists" errors, leaving the server unable to start at all.

PR #27234 fixed this in three steps. First, it moved the webserver to DB_SCHEMA_UPDATE_FALSE so Flowable never runs DDL at server startup. Second, it moved Flowable schema initialization into the migrate CLI, which is already the designated place for all database schema work. Third, it wrapped Flowable's DDL in an idempotent layer so that re-running migrate would not fail if the schema was already partially applied.

What the regression was

The migrate CLI now calls WorkflowHandler.initialize(config, true). The WorkflowHandler constructor, regardless of whether it is running in migration or runtime mode, was unconditionally calling initializeExpressionMap, which builds two objects: an IngestionPipelineMapper and a PipelineServiceClient. The PipelineServiceClient is created via reflection using the class name from config.

In the Collate CI environment, the configured PipelineServiceClient class (io.getcollate.clients.pipeline.argo.ArgoServiceClient) is not available on the migrate container's classpath. This caused a ClassNotFoundException wrapped in a PipelineServiceClientException, which propagated out of the migrate command and caused it to exit with code 1. The Flowable schema itself was never the problem and the data migrations had already completed successfully at that point.

What the fix does

The PipelineServiceClient and IngestionPipelineMapper are only needed at workflow execution time, when Flowable resolves BPMN expression variables like ${PipelineServiceClient} in task definitions. During migration, WorkflowHandler only needs to run Flowable's DDL upgrade and then shut down. No BPMN is ever executed.

The fix guards initializeExpressionMap with if (!isMigrationContext) so that in migration mode the expression map is simply left empty. An empty expression map produces a valid DefaultExpressionManager that Flowable accepts without complaint. The schema upgrade runs and completes, and the migrate command exits cleanly.

This follows the same pattern already used elsewhere in the constructor where isMigrationContext controls setAsyncExecutorActivate and setEnableHistoryCleaning.

How to reproduce before this fix

cd /path/to/OpenMetadata
docker compose -f docker/development/docker-compose.yml build --no-cache execute-migrate-all
docker compose -f docker/development/docker-compose.yml up -d mysql
docker rm execute_migrate_all 2>/dev/null
export PIPELINE_SERVICE_CLIENT_CLASS_NAME=io.getcollate.clients.pipeline.argo.ArgoServiceClient
docker compose -f docker/development/docker-compose.yml up execute-migrate-all

You will see "Running Flowable schema upgrade." followed immediately by the PipelineServiceClientException and exit code 1. After the fix the same command completes with exit code 0.

Test coverage

A new test migrationModeDoesNotLoadPipelineServiceClient was added to WorkflowHandlerSchemaUpdateTest. It configures PipelineServiceClientFactory to throw a RuntimeException simulating a missing class, then calls WorkflowHandler.initialize(config, true) and asserts that it completes without throwing and that createPipelineServiceClient was never called.

@yan-3005 yan-3005 added the safe to test Add this label to run secure Github workflows on PRs label Apr 19, 2026
@yan-3005 yan-3005 self-assigned this Apr 19, 2026
@yan-3005 yan-3005 added the safe to test Add this label to run secure Github workflows on PRs label Apr 19, 2026
Copilot AI review requested due to automatic review settings April 19, 2026 13:06
@gitar-bot
Copy link
Copy Markdown

gitar-bot Bot commented Apr 19, 2026

Code Review ✅ Approved

Workflow pipeline service client initialization is now skipped during migration to prevent unnecessary resource allocation. No issues found.

Options

Display: compact → Showing less information.

Comment with these commands to change:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Prevents migrate executions from failing due to missing runtime-only workflow dependencies by skipping PipelineServiceClient/expression-map initialization in migration context.

Changes:

  • Guard WorkflowHandler expression-map initialization so it only runs in runtime mode (not during migration).
  • Add a regression test ensuring migration mode does not attempt to construct a PipelineServiceClient (and therefore won’t fail if the configured class isn’t on the migrate classpath).

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
openmetadata-service/src/main/java/org/openmetadata/service/governance/workflows/WorkflowHandler.java Skips initializeExpressionMap when isMigrationContext is true to avoid loading runtime-only pipeline client classes during migrations.
openmetadata-service/src/test/java/org/openmetadata/service/governance/workflows/WorkflowHandlerSchemaUpdateTest.java Adds coverage to ensure migration initialization does not call PipelineServiceClientFactory.createPipelineServiceClient.

@sonarqubecloud
Copy link
Copy Markdown

@github-actions
Copy link
Copy Markdown
Contributor

🟡 Playwright Results — all passed (20 flaky)

✅ 3667 passed · ❌ 0 failed · 🟡 20 flaky · ⏭️ 89 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 478 0 3 4
🟡 Shard 2 650 0 3 7
🟡 Shard 3 654 0 5 1
🟡 Shard 4 633 0 1 27
🟡 Shard 5 610 0 1 42
🟡 Shard 6 642 0 7 8
🟡 20 flaky test(s) (passed on retry)
  • Features/CustomizeDetailPage.spec.ts › Database - customization should work (shard 1, 2 retries)
  • Pages/Customproperties-part1.spec.ts › no duplicate card after update (shard 1, 1 retry)
  • Pages/UserCreationWithPersona.spec.ts › Create user with persona and verify on profile (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 2, 1 retry)
  • Features/EntitySummaryPanel.spec.ts › should edit display name from entity summary panel (shard 2, 1 retry)
  • Features/ExploreQuickFilters.spec.ts › tier with assigned asset appears in dropdown, tier without asset does not (shard 2, 1 retry)
  • Features/RestoreEntityInheritedFields.spec.ts › Validate restore with Inherited domain and data products assigned (shard 3, 1 retry)
  • Features/RestoreEntityInheritedFields.spec.ts › Validate restore with Inherited domain and data products assigned (shard 3, 2 retries)
  • Features/RestoreEntityInheritedFields.spec.ts › Validate restore with Inherited domain and data products assigned (shard 3, 1 retry)
  • Flow/CustomizeWidgets.spec.ts › My Data Widget (shard 3, 1 retry)
  • Flow/SchemaTable.spec.ts › schema table test (shard 3, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/Glossary.spec.ts › Add and Remove Assets (shard 5, 1 retry)
  • Pages/HyperlinkCustomProperty.spec.ts › should show No Data placeholder when hyperlink has no value (shard 6, 1 retry)
  • Pages/Lineage/DataAssetLineage.spec.ts › verify create lineage for entity - Spreadsheet (shard 6, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify lineage schema filter selection (shard 6, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: searchIndex (shard 6, 1 retry)
  • Pages/Lineage/PlatformLineage.spec.ts › Verify domain platform view (shard 6, 1 retry)
  • Pages/ServiceEntity.spec.ts › Announcement create, edit & delete (shard 6, 1 retry)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@yan-3005 yan-3005 enabled auto-merge (squash) April 19, 2026 15:04
@yan-3005 yan-3005 disabled auto-merge April 20, 2026 03:17
@yan-3005 yan-3005 merged commit aca0290 into main Apr 20, 2026
65 of 120 checks passed
@yan-3005 yan-3005 deleted the ram/hotfix-migrate-pipeline-client branch April 20, 2026 06:07
@github-actions
Copy link
Copy Markdown
Contributor

Changes have been cherry-picked to the 1.12.6 branch.

github-actions Bot pushed a commit that referenced this pull request Apr 20, 2026
yan-3005 added a commit that referenced this pull request Apr 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs To release Will cherry-pick this PR into the release branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants