Skip to content

fix(webapp): keep paused environments paused when concurrency limits are pushed - #4625

Merged
matt-aitken merged 2 commits into
mainfrom
fix/paused-env-concurrency-limit-clamp
Aug 14, 2026
Merged

fix(webapp): keep paused environments paused when concurrency limits are pushed#4625
matt-aitken merged 2 commits into
mainfrom
fix/paused-env-concurrency-limit-clamp

Conversation

@claude

@claude claude Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Requested by Matt Aitken · Slack thread

Before: you pause an environment, then a deploy lands (or a background worker is created, or an admin changes the concurrency/burst-factor). The environment starts picking up runs again even though the dashboard still shows it as paused.

After: a paused environment stays paused until it is resumed, no matter what else pushes its concurrency limit.

Pausing an environment sets paused in the database and writes a 0 env concurrency limit into the run queue — the 0 is the only thing that actually stops dequeueing. Any caller that pushed the limit without an explicit value (finalizeDeployment, createBackgroundWorker, the two admin environment routes) rewrote the real limit and silently un-paused the environment.

✅ Checklist

  • I have followed every step in the contributing guide
  • The PR title follows the convention.
  • I ran and tested the code works

Testing

apps/webapp/test/pauseEnvironment.server.test.ts gains two containerTest cases that wire a real RunEngine (real Redis) in place of the stubbed app singleton and assert the actual run-queue env limit:

  • pause a PRODUCTION env → limit is 0 → run the real FinalizeDeploymentService → limit is still 0, plus a control on a running env in the same test proving that deploy path really does push the limit (so the 0 can't just mean "nothing happened").
  • pause → resume → the real limit is restored, so the clamp can't regress resuming.

Both cases fail on main (expected 17 to be +0 and expected +0 to be 17) and pass with this change. pnpm run typecheck --filter webapp is clean.


Changelog

Fix paused environments starting to run work again after a deploy.


How

The clamp lives in the shared updateEnvConcurrencyLimits helper in apps/webapp/app/v3/runQueue.server.ts, so every present and future caller is covered: when no explicit limit is passed and the environment is paused, 0 is written instead of the stored maximum. An explicitly-passed limit still wins, which is what pausing itself relies on. The resume path now passes the post-update environment state (its in-memory copy was read before the un-pause and would otherwise be clamped back to 0), and the helper no longer mutates the caller's environment object — that aliasing made a pause followed by a resume on the same object write 0 twice. The existing !paused guards in allocateConcurrency and the queue-level guard in createBackgroundWorker are left in place as defence in depth, and queue-level TaskQueue.paused behaviour is untouched.

…are pushed

`updateEnvConcurrencyLimits` is the only enforcement of an environment pause: pausing
writes a 0 env concurrency limit to the run queue, which is what stops dequeueing.
Callers that push the limit without an explicit value (finalizing a deployment,
creating a background worker, the admin concurrency/burst-factor routes) rewrote the
real limit, silently resuming an environment the dashboard still showed as paused.

Clamp the pushed limit to 0 when the environment is paused and no explicit limit is
given, so every caller is covered. An explicit limit still wins. Resuming now passes
the post-update state, and the helper no longer mutates the caller's environment
object (which made a pause + resume on the same object write 0 twice).

Co-Authored-By: Claude <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 65b2152

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@matt-aitken
matt-aitken marked this pull request as ready for review August 14, 2026 19:07

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

…currency limits

The clamp added in the previous commit read `paused` off the environment object the caller
passed, which is captured when the request authenticates and can be read from a replica. A
stale `paused: false` still silently resumes a paused environment, and a stale `paused: true`
writes 0 over a limit that was just restored - leaving the environment stalled with
`paused: false` and nothing to put the limit back.

Resolve `paused` and `maximumConcurrencyLimit` for the environment id inside
`updateEnvConcurrencyLimits` when no explicit limit is given, and let callers hand in the
client they wrote with so the read is primary- and transaction-consistent. The explicit-limit
path is unchanged: pausing and billing-limit converge still decide the value with no read.

Move the RunQueue limit cases into their own test file so the pre-existing suite keeps the
shared engine stub instead of a file-level mock, and cover the resumed-while-in-flight
ordering.

Co-Authored-By: Claude <noreply@anthropic.com>
@matt-aitken
matt-aitken merged commit 69f396f into main Aug 14, 2026
37 checks passed
@matt-aitken
matt-aitken deleted the fix/paused-env-concurrency-limit-clamp branch August 14, 2026 21:12
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.

2 participants