Skip to content

feat(queue): display queued deployment status in service UI - #5422

Closed
imrja8 wants to merge 6 commits into
Dokploy:canaryfrom
imrja8:feat/visual-deployment-queue
Closed

imrja8 wants to merge 6 commits into
Dokploy:canaryfrom
imrja8:feat/visual-deployment-queue

Conversation

@imrja8

@imrja8 imrja8 commented Sep 11, 2026 •

Copy link
Copy Markdown
Collaborator

What is this PR about?

Follow up to #4774, which I closed after it grew beyond the original intent. I decided to split it into two focused PRs.

The problem

When a user triggers multiple deployments quickly (rapid GitHub pushes, clicking deploy while one is already running), the system queues them internally but shows nothing in the UI. The user only sees the currently running deployment. There is no indication that others are waiting. This leads to confusion, users clicking deploy again thinking it did not work, and no way to know what the system is actually doing behind the scenes.

What this PR does

Makes the queue visible. After this change:

  1. Every queued deployment appears immediately in the deployment list with a blue "Queued" status dot, so users know something is waiting
  2. Deploy and rebuild buttons stay in a loading state while a deployment is queued, not just while running, so users know their click registered
  3. The "Cancel Queues" button only shows up when there are actually queued items, instead of always being visible
  4. If a queued deployment gets cancelled before it starts, the log viewer shows "Deployment was cancelled while queued" instead of the internal queue waiting message
  5. Cancelled queue entries can be deleted from the deployment history

How it works

The key change is that deployment database records are now created at enqueue time (with status: "queued") instead of when the worker starts executing. This is what makes them show up in the list. When the worker picks up a job, the record transitions from queued to running.

Three enqueue helpers (enqueueApplicationDeployment, enqueueComposeDeployment, enqueuePreviewDeployment) replace all direct myQueue.add calls and handle the record creation, status updates, and error recovery in one place.

Log filenames now use millisecond precision to prevent collisions when multiple records are created in quick succession.

On server restart, any deployments left in a queued state are cleaned up since the in memory queue no longer has those jobs.

What is NOT in this PR

Individual deployment kill behavior and PID based process cancellation, that is Part 2. The global deployments dashboard page is not updated as it was outside the original file scope.

Existing behavior

Nothing changes for the existing flow. When a deployment is triggered normally, it goes through the same code path as before. The queued state is purely additive.

Checklist

  • You created a dedicated branch based on the canary branch.
  • You have read the suggestions in the CONTRIBUTING.md file
  • You have tested this PR in your local instance. If you have not tested it yet, please do so before submitting.

Issues related (if applicable)

Supersedes #4774

Screenshots

Project Dashboard [Running, Queued, Cancelled (idle) states] - Click to OPEN/CLOSE
Project Dashboard states

1. Running state: On going deployment state for service
running

2. Queued state: Pending deployment state for service
queued

3. Cancelled (Idle) state: Canclled deployment (before build) state for service
idle

Button Loading (Running | Queued) States - Click to OPEN/CLOSE

Running state Deploy/Redeploy button (Pre-existing: loading state to prevent multiple redeploys while running)
Running state button

Queued state Deploy/Redeploy button (Added in this PR: loading state extends to queued status to prevent multiple rapid enqueues, unless triggered via webhook)
Queued state button

RetriggerConfidence Score: 5/5

The PR appears safe to merge; the previously reported queue races and aggregate-status problems are resolved in the current code.

Summary

  • Adds queued states to deployment and service schemas, migration, UI indicators, and controls.
  • Centralizes application, Compose, and preview enqueue behavior around record creation and failure recovery.
  • Atomically claims queued records and serializes enqueue/cancellation per service.
  • Recomputes aggregate service status when deployments complete, fail, or lose a claim.
  • Cancels stale queued and running records before the HTTP server accepts requests.
  • Both previous findings were properly resolved: cancelled records cannot be reclaimed, enqueue and cancellation are serialized, active sibling deployments preserve aggregate status, and startup cleanup completes before listening.

Reviews (5) · Last reviewed commit: "fix: close 4 race conditions in queued d..."

- Add "queued" status to deploymentStatus, applicationStatus enums
- Create deployment records at enqueue time for immediate UI visibility
- Show blue dot for queued deployments, loading state on deploy buttons
- Cancel queued deployments cleanly with proper DB + queue cleanup
- Extract shared helpers: resolveQueuedDeployment, enqueueDeployment
- Use millisecond-precision timestamps in log filenames to prevent collisions
- Fix preview deployment grouping in in-memory queue
- Add per-app try/catch in GitHub webhook handler
@imrja8
imrja8 requested a review from Siumauricio as a code owner September 11, 2026 17:26
Comment thread packages/server/src/services/deployment.ts Outdated
Comment thread packages/server/src/utils/startup/cancel-deployments.ts
…quests

Atomic claim in resolveQueuedDeployment only transitions deployments
still in queued status, so a cancelled record cannot be set back to
running. Move initCancelDeployments before server.listen so no HTTP
requests can arrive during stale-record cleanup.
@imrja8
imrja8 force-pushed the feat/visual-deployment-queue branch from 6885306 to 337f47b Compare September 11, 2026 17:43
- Atomic WHERE status = 'queued' claim prevents cancelled jobs from running
- initCancelDeployments before server.listen prevents startup cancelling live requests
- getActiveDeploymentStatus helper preserves queued/running status when deployments remain
- Per-service mutex prevents enqueue/cancel interleaving

Extracted shared helpers to eliminate 40+ lines of duplication across services.
@imrja8 imrja8 closed this Sep 12, 2026
@imrja8
imrja8 deleted the feat/visual-deployment-queue branch September 12, 2026 06:01
@imrja8
imrja8 restored the feat/visual-deployment-queue branch September 12, 2026 06:01
@imrja8 imrja8 reopened this Sep 12, 2026
…eployments

- Add priority ordering to getActiveDeploymentStatus (running > queued)
- Recompute aggregate status after startup cleanup instead of forcing idle
- Update DB records and recompute status in cleanAllDeploymentQueue
- Add status recomputation to per-service queue cleanup functions
- Centralize terminal status updates in processDeploymentJob with service lock
- Create updateServiceStatusFromActiveDeployments helper to eliminate duplication
- Remove dead code: unreachable if (!deploymentId) blocks
- Fix unused imports and formatting for biome compliance
@imrja8

imrja8 commented Sep 12, 2026

Copy link
Copy Markdown
Collaborator Author

Closing this since it only covers self-hosted.

Cloud uses a separate Inngest pipeline and needs its own queue visibility work.

I’m closing this in favor of PR #4146 effort, will work with author.

@imrja8 imrja8 closed this Sep 12, 2026
@imrja8
imrja8 deleted the feat/visual-deployment-queue branch September 12, 2026 08:39
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.

1 participant