Fix pipelines get stuck in a paused state#5223
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes an issue where pipelines get stuck in a paused state by ensuring callbacks run when the desired pipeline state is reached. It also optimizes pipeline startup by skipping the pause-unpause sequence when no change stream relations are selected.
Key Changes:
- Initialized
usePipelineActionglobally to maintain waiter state across UI contexts - Added optimization to skip PAUSED state when no relations are selected in Change Stream
- Refactored pipeline action handling to use a singleton pattern via
getPipelineAction()
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| js-packages/web-console/src/routes/(system)/(authenticated)/+layout.svelte | Initializes usePipelineAction at the authenticated layout level |
| js-packages/web-console/src/routes/(system)/(authenticated)/(pipelines)/pipelines/[pipelineName]/+layout.svelte | Removed redundant effect that refreshed pipeline list data |
| js-packages/web-console/src/lib/compositions/usePipelineAction.svelte.ts | Core fix: made postPipelineAction a singleton and added optimization to skip pause state when no relations selected |
| js-packages/web-console/src/lib/compositions/pipelines/usePipelineList.svelte.ts | Added debug logging and removed unused import |
| js-packages/web-console/src/lib/components/pipelines/table/AvailableActions.svelte | Updated to use getPipelineAction() instead of usePipelineAction() |
| js-packages/web-console/src/lib/components/pipelines/list/Actions.svelte | Updated to use getPipelineAction() instead of usePipelineAction() |
| js-packages/web-console/src/lib/components/pipelines/editor/TabChangeStream.svelte | Added hasSelectedRelations() helper function to check if pipeline has selected relations |
| js-packages/web-console/src/lib/components/layout/pipelines/PipelineEditLayout.svelte | Updated to use getPipelineAction() and removed unused variables |
|
|
||
| export const usePipelineList = (preloaded?: { pipelines: PipelineThumb[] }) => { | ||
| if (preloaded && !pipelines) { | ||
| console.log('setting in usePipelineList:', preloaded, pipelines) |
There was a problem hiding this comment.
Debug logging statement should be removed before merging to production. This appears to be temporary debugging code that was left in.
| console.log('setting in usePipelineList:', preloaded, pipelines) |
| let postPipelineAction: (pipeline_name: string, action: PipelineAction, callbacks?: { | ||
| onPausedReady?: (pipelineName: string) => Promise<void>; | ||
| }) => Promise<{ | ||
| waitFor: () => Promise<boolean>; |
There was a problem hiding this comment.
The module-level postPipelineAction variable lacks documentation explaining why it needs to be a singleton and how the initialization pattern works. Consider adding a comment explaining that this is initialized once by usePipelineAction() and reused by getPipelineAction() to maintain waiter state across UI contexts.
| const pipelineAction = usePipelineAction() | ||
|
|
||
| const api = usePipelineManager() | ||
| const { updatePipelines } = useUpdatePipelineList() |
There was a problem hiding this comment.
The updatePipeline function was removed from destructuring but may still be needed elsewhere in the file. Verify that removing this doesn't break any functionality, as the original code imported both updatePipelines and updatePipeline.
|
I tagged @mihaibudiu for review because he is the one that is more familiar with the language. By now I forgot everything about how typescript works. |
mihaibudiu
left a comment
There was a problem hiding this comment.
I don't know how to test this, and there are no tests, so I can only hope that it addresses the issues enumerated.
| untrack(() => pipelineActionCallbacks.add('', 'delete', forgetCurrentTab)) | ||
| return () => { | ||
| pipelineActionCallbacks.remove('', 'start_paused', forgetCurrentTab) | ||
| pipelineActionCallbacks.remove('', 'delete', forgetCurrentTab) |
| import { useContextDrawer } from '$lib/compositions/layout/useContextDrawer.svelte' | ||
| import { getConfig } from '$lib/services/pipelineManager' | ||
| import { invalidateAll } from '$app/navigation' | ||
| import { usePipelineAction } from '$lib/compositions/usePipelineAction.svelte' |
There was a problem hiding this comment.
I don't know how this file works
how lovely, using parens and plus in file names.
There was a problem hiding this comment.
I can quickly go through it when you have the time. It's the syntax of the SvelteKit file-based router that resolves the URL in the browser to the Svelte page
| return { | ||
| postPipelineAction: async ( | ||
| // We initialize a global state that will be reused across all calls to `getPipelineAction`. | ||
| // This allows keeping the same waiters alive while switching UI context |
There was a problem hiding this comment.
I don't know who the waiters are or what switching UI context means, but perhaps I have missed too many reviews of this code to understand
| predicate: (ps) => { | ||
| const p = ps.find((p) => p.name === pipeline_name) | ||
| if (!p) { | ||
| throw new Error('Pipeline not found in pipelines list') |
There was a problem hiding this comment.
is this the right thing to do?
can the users delete the pipelines (e.g., using the sdk) while this is happening?
| return null | ||
| } | ||
| if ( | ||
| (['Paused', 'AwaitingApproval'] satisfies PipelineStatus[]).findIndex( |
There was a problem hiding this comment.
you really like to write code that is hard to understand
| if (p.status === 'Stopped') { | ||
| return { value: false } | ||
| } | ||
| throw new Error( |
There was a problem hiding this comment.
so if any of these errors happens no callbacks are run. is this what you expect?
|
@Karakatiza666 please add tests. |
…and leaving the page Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
…cted in change stream Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
…a bug Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
b34e712 to
2f9fc42
Compare
In the first commit I fixed that callbacks that are supposed to run when desired pipeline state after an action is reached, don't.
In the second commit I added an optimization to start the pipeline directly if no relations are selected in the change stream.
Fix #4822: skip the PAUSED state if we don't need to listen for any changes
#5218 should be evaluated, tested and merged some time after this PR.