Skip to content

feat: per-server deployment concurrency#2

Open
aladdinb1 wants to merge 18 commits intocanaryfrom
feat/concurrent-deployments
Open

feat: per-server deployment concurrency#2
aladdinb1 wants to merge 18 commits intocanaryfrom
feat/concurrent-deployments

Conversation

@aladdinb1
Copy link
Copy Markdown
Collaborator

Summary

  • Adds per-server deploymentConcurrency (default 1, max 10) — limits how many deployments run in parallel per target server. The queue is target-aware so other servers are unaffected
  • Local Dokploy host: configurable via Server dropdown → "Deployment Concurrency" entry (between GPU Setup and Update Server, mirroring the GPU Setup pattern)
  • Remote servers: configurable via Setup Server dialog → new "Deployments" tab
  • Schema additions: server.deploymentConcurrency and webServerSettings.deploymentConcurrency (both int, default 1)
  • Refactored deployment queue into grouped-queue + queue-router + queue-manager to support per-server worker pools
  • 4 new test files covering grouped queue, router, manager, and integration scenarios

Test plan

  • Unit tests pass (__test__/queues/*)
  • UI: setting concurrency=2 on remote server applies immediately (no service restart)
  • E2E parallel-deploy proof on Hetzner remote: Alpha + Beta deployed simultaneously, both started 4ms apart, finished 1ms apart, identical 61.32s durations (sequential would be ~122s wall time)
  • Both Docker swarm services healthy on Remote Test daemon after parallel deploy

aladdinb1 and others added 8 commits April 23, 2026 01:49
…time-configurable

esbuild.config.ts inlines every key from .env.production into the bundle via
'define'. That's fine for build-time constants, but deployment concurrency
and the shutdown drain grace window are operator knobs that must be tunable
from docker-compose env / systemd unit / shell without rebuilding. If one
of these accidentally ends up in .env.production, its value gets baked in
and the runtime env var is silently ignored.

Moved the skip list into a named set so the intent is explicit and adding
more runtime-only keys later is a one-line change.
Attaching a bare `.then()` to a pending queue-creation promise leaves a
dangling chain with no error handler. In the happy path this never fires,
but under Node's default strict-throw policy for unhandled rejections a
future change to `concurrencyProvider` that lets an exception escape would
take the process down on the handler-registration path. Chain a no-op
`.catch` so any rejection is absorbed; getOrCreate's own catch has already
unregistered the slot so the next enqueue retries cleanly.
Bring the local host in line with the remote-server experience: an operator
can tune how many deployments the Dokploy host runs in parallel from
Settings -> Web Server, no rebuild or service restart required.

- Adds deploymentConcurrency to webServerSettings (default 1) + migration.
- settings.updateDeploymentConcurrency tRPC mutation persists the value and
  pushes it into the live deploymentQueueManager for LOCAL_TARGET on the
  same tick.
- ChangeConcurrencyModal accepts serverId: string | null. String targets the
  remote path (unchanged); null routes through the new local mutation/query.
- queueSetup concurrencyProvider now reads webServerSettings for LOCAL_TARGET
  (DEPLOYMENT_QUEUE_CONCURRENCY env var stays as the cold-boot default when
  no row exists yet).
@autofix-troubleshooter
Copy link
Copy Markdown

Hi! I'm the autofix logoautofix.ci troubleshooter bot.

It looks like you correctly set up a CI job that uses the autofix.ci GitHub Action, but the autofix.ci GitHub App has not been installed for this repository. This means that autofix.ci unfortunately does not have the permissions to fix this pull request. If you are the repository owner, please install the app and then restart the CI workflow! 😃

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.

3 participants