--- src/lib.rs
+++ src/lib.rs
@@ -202,6 +202,7 @@
tasks: RefCell<HashMap<u64, Py<PyAny>>>,
next: Cell<u64>,
sends: Cell<usize>,
+ eager_started: Cell<usize>,
stopping: Cell<bool>,
date: RefCell<Vec<u8>>,
date_at: Cell<u64>,
@@ -620,7 +621,9 @@
.bind(py)
.call_method0(pyo3::intern!(py, "get_task_factory"))?
.is_none()
+ && self.eager_started.get() < 128
{
+ self.eager_started.set(self.eager_started.get() + 1);
self.task_type
.bind(py)
.call((coro,), Some(self.task_options.bind(py)))?
@@ -1019,6 +1022,13 @@
s.flush(py, &c)?;
} else {
return Err(PyValueError::new_err("Unsupported ASGI message"));
+ }
+ // Completing a response is a cooperative boundary. Do not delay scope
+ // cleanup after its bytes are already sent. Eager dispatch has its own
+ // per-callback budget, while unfinished producers retain the send budget.
+ if self.request.borrow().complete {
+ s.sends.set(0);
+ return Ok(s.done.clone_ref(py));
}
let n = s.sends.get() + 1;
s.sends.set(n);
@@ -1231,6 +1241,7 @@
tasks: RefCell::new(HashMap::new()),
next: Cell::new(0),
sends: Cell::new(0),
+ eager_started: Cell::new(0),
stopping: Cell::new(false),
date: RefCell::new(Vec::new()),
date_at: Cell::new(0),
@@ -1249,6 +1260,7 @@
fn poll(&self, py: Python<'_>) -> PyResult<()> {
let s = &self.state;
s.sends.set(0);
+ s.eager_started.set(0);
for (token, mask) in s.poller.events()? {
if token == 0 {
if s.stopping.get() {