MR pipelines page loading spinner stuck when pipeline creation takes longer than expected
Description
Summary
When the ci_pipeline_creation_requests_realtime feature flag is enabled, the merge request pipelines page loading spinner and skeleton loader can get stuck indefinitely on projects where pipeline creation takes long time to complete. The pipeline is created successfully, but the UI remains in a loading state because the WebSocket subscription never receives the status update.
Root Cause
The ciPipelineCreationRequestsUpdated GraphQL subscription is not receiving the SUCCEEDED or FAILED status update from the backend when pipeline creation completes on larger/more complex projects. The subscription correctly receives the initial IN_PROGRESS status, but the completion message never arrives via WebSocket.
Steps to Reproduce
- Enable the
ci_pipeline_creation_requests_realtimefeature flag on a project with complex CI/CD configuration (many includes, extends, or jobs) - Navigate to a merge request's pipelines tab
- Open browser DevTools > Network > WS tab and filter for
cable - Click "Run Pipeline"
- Observe:
- WebSocket receives message with
status: "IN_PROGRESS" - Skeleton loader and loading spinner appear
- Pipeline is created (visible in pipelines table after polling)
- No WebSocket message with
status: "SUCCEEDED"is received - Loading spinner remains indefinitely
- WebSocket receives message with
Expected Behavior
- WebSocket should receive the
SUCCEEDEDstatus update when pipeline creation completes - Loading spinner should disappear
- Skeleton loader should be replaced with the actual pipeline row
Technical Details
- When "Run Pipeline" is clicked,
MergeRequests::CreatePipelineService#execute_asyncis called - A pipeline creation request is stored in Redis with
IN_PROGRESSstatus -
GraphqlTriggers.ci_pipeline_creation_requests_updatedis called, triggering the WebSocket subscription - The frontend receives the
IN_PROGRESSstatus and displays the skeleton loader - Pipeline creation happens asynchronously in
MergeRequests::CreatePipelineWorker - When complete,
Ci::PipelineCreation::Requests.succeededupdates Redis status toSUCCEEDED -
GraphqlTriggers.ci_pipeline_creation_requests_updatedis called again increate_merge_request_pipeline - Issue: On larger projects, this second WebSocket message never reaches the frontend
- The
pipelines.jsonpolling eventually fetches the new pipeline and adds it to the table - But the loading spinner persists because it depends on the WebSocket response to clear
Environment
- Reproduced on GitLab.com (
gitlab-org/gitlabproject) - Feature flag:
ci_pipeline_creation_requests_realtime(introduced in !207190 (merged)) - Only occurs on projects where pipeline creation takes longer (complex CI configurations)
- Works correctly on smaller projects where pipeline creation is fast
Possible Investigation Areas
- WebSocket connection timeout: The WebSocket connection may be timing out or being closed before the completion message is sent on slow pipeline creations
- Redis pub/sub timing: The subscription trigger may be happening before the WebSocket subscription is fully established for the updated data
- ActionCable channel subscription: The channel may not be properly subscribed to receive updates after the initial message
- Load balancer/proxy timeout: Network infrastructure may be closing long-lived WebSocket connections
Related Issues
- Feature flag MR: !207190 (merged)
- Feature issue: #568346 (closed)
- Rollout issue: #576639 (closed)