Skip to content

Fix autoscale and disable-prefetch for green worker pools#10361

Open
arkadiuszbach wants to merge 3 commits into
celery:mainfrom
arkadiuszbach:fix/green-pool-autoscale
Open

Fix autoscale and disable-prefetch for green worker pools#10361
arkadiuszbach wants to merge 3 commits into
celery:mainfrom
arkadiuszbach:fix/green-pool-autoscale

Conversation

@arkadiuszbach

Copy link
Copy Markdown
Contributor

Summary

Fixes green worker pool capacity tracking for autoscale.

  • Fixes Celery autoscale not working #4003 for gevent and eventlet worker pools; prefork was already working correctly.
  • Fixes gevent num_processes to report configured pool capacity instead of active greenlets.
  • Fixes worker_disable_prefetch behavior for gevent workers, since it relies on pool.num_processes.
  • Keeps green-pool capacity in sync with Celery's pool limit during autoscale grow/shrink.
  • Wakes blocked spawn() waiters when gevent/eventlet pools grow, instead of only mutating semaphore counters.

Why

The autoscaler uses pool.num_processes as the current pool capacity. For gevent, this previously returned len(self._pool), which is the number of tracked/running greenlets rather than configured capacity. That caused autoscale decisions to be based on active work instead of the pool size.

This resolves the long-standing autoscale failure reported in #4003 for gevent and eventlet workers. Prefork already scales correctly, but the green pools had stale/incorrect capacity accounting and did not wake blocked task submissions when autoscale increased the pool size.

worker_disable_prefetch also relies on pool.num_processes when deciding whether the worker can consume more tasks. With gevent, the incorrect active-greenlet count could cause disable-prefetch to make the wrong consume/stop decision.

Both gevent and eventlet pool growth adjusted semaphore counters directly. That updates capacity numerically, but it does not notify tasks already blocked waiting for a pool slot. The fix releases the relevant semaphore slots during grow so blocked submissions can continue immediately.

@arkadiuszbach
arkadiuszbach force-pushed the fix/green-pool-autoscale branch 5 times, most recently from a4217e8 to ab7d9d3 Compare June 18, 2026 12:38
Fix gevent and eventlet worker pools so autoscale grow/shrink keeps
Celery's pool limit and the underlying green-pool capacity in sync.

For gevent, report configured capacity from num_processes instead of
active greenlets. This also fixes worker_disable_prefetch for gevent
workers, which relies on pool.num_processes when deciding whether more
tasks can be consumed.

For both gevent and eventlet, wake spawn waiters when autoscale grows
the pool instead of only changing semaphore counters.
@arkadiuszbach
arkadiuszbach force-pushed the fix/green-pool-autoscale branch from ab7d9d3 to 798a7ca Compare June 18, 2026 12:40
@codecov

codecov Bot commented Jun 18, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.33333% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.34%. Comparing base (379a629) to head (eb9b8d7).
⚠️ Report is 20 commits behind head on main.

Files with missing lines Patch % Lines
celery/concurrency/eventlet.py 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #10361      +/-   ##
==========================================
- Coverage   88.36%   88.34%   -0.02%     
==========================================
  Files         153      153              
  Lines       19787    19793       +6     
  Branches     2296     2298       +2     
==========================================
+ Hits        17484    17487       +3     
- Misses       2004     2007       +3     
  Partials      299      299              
Flag Coverage Δ
unittests 88.32% <58.33%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@auvipy auvipy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

can you please check if the test coverage can be improved?

Copilot AI 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.

Pull request overview

This PR fixes autoscale (and the worker_disable_prefetch decision that depends on it) for the gevent and eventlet worker pools, addressing the long-standing issue #4003. The autoscaler reads pool.num_processes as current capacity; for gevent this previously returned len(self._pool) (active greenlets) rather than the configured pool size, so scaling decisions were based on active work instead of capacity. The change also makes green-pool grow/shrink keep Celery's limit in sync with the pool size and, importantly, wake greenthreads/greenlets already blocked in spawn() when the pool grows, instead of only mutating semaphore counters.

Changes:

  • gevent: num_processes now returns self.limit; grow/shrink keep limit and _pool.size in sync and grow releases the semaphore per new slot to wake blocked spawns.
  • eventlet: grow/shrink replace _pool.resize(...) with explicit sem counter/release() handling plus size/limit sync so blocked spawn() waiters are notified on growth.
  • Tests: expanded gevent/eventlet unit tests for capacity/notify behavior, plus a real-eventlet integration test verifying grow() wakes a blocked spawn() waiter.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
celery/concurrency/gevent.py num_processes returns capacity; grow/shrink sync limit/size and release semaphore to wake waiters.
celery/concurrency/eventlet.py grow/shrink replace resize with direct sem handling and release() to notify blocked waiters.
t/unit/concurrency/test_gevent.py Updated test_pool and added tests for capacity, shrink, num_processes, and autoscaler scaling.
t/unit/concurrency/test_eventlet.py Updated grow/shrink tests and added capacity, autoscaler, and a real-eventlet grow-wakes-waiter test.

assert len(testMap) == 0


class test_TaskPool_eventlet:

@auvipy auvipy left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

should we also consider smoke tests or integration tests for this, beside inproving test coverage?

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.

Celery autoscale not working

3 participants