fix(workflows): skip PipelineServiceClient initialization during migrate#27522
fix(workflows): skip PipelineServiceClient initialization during migrate#27522
Conversation
Code Review ✅ ApprovedWorkflow pipeline service client initialization is now skipped during migration to prevent unnecessary resource allocation. No issues found. OptionsDisplay: compact → Showing less information. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
There was a problem hiding this comment.
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
WorkflowHandlerexpression-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. |
|
🟡 Playwright Results — all passed (20 flaky)✅ 3667 passed · ❌ 0 failed · 🟡 20 flaky · ⏭️ 89 skipped
🟡 20 flaky test(s) (passed on retry)
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
|
Changes have been cherry-picked to the 1.12.6 branch. |



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
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.