mirror of
https://github.com/tiennm99/DocsGPT.git
synced 2026-10-14 04:15:35 +00:00
fix: minor pooling issue
This commit is contained in:
1 parent
9cae9482f8
commit
16e0ef6d17
2 files changed
+48
No files matched your search
@@ -130,6 +130,13 @@ class DelegatedEmbeddings:
|
||||
vectors = result.get(timeout=timeout)
|
||||
except Exception as exc:
|
||||
self._failed_at = time.monotonic()
|
||||
# Drop the proof with the worker that supplied it. ``_verified``
|
||||
# short-circuits ahead of the probe gate, so leaving it set means
|
||||
# the gate only ever covers a worker that was never healthy --
|
||||
# while the case that actually happens is a healthy one being
|
||||
# redeployed or OOM-killed. Every caller would then pay the full
|
||||
# timeout, together, on every wave once the cooldown lapses.
|
||||
self._verified = False
|
||||
raise RuntimeError(
|
||||
f"Embedding request to the Celery worker timed out or failed ({exc}). "
|
||||
f"A worker must be consuming the {queue!r} queue for retrieval to "
|
||||
|
||||
@@ -288,6 +288,47 @@ class TestTheConcurrentFirstWave:
|
||||
embeddings.embed_query("q")
|
||||
lock.__enter__.assert_not_called()
|
||||
|
||||
def test_a_proven_worker_that_dies_is_gated_again(self, not_in_worker):
|
||||
"""The proof must not outlive the worker that supplied it.
|
||||
|
||||
A worker that is redeployed or OOM-killed is the failure that actually
|
||||
happens in production, and it is the one the probe gate stopped
|
||||
covering: ``_verified`` short-circuits ahead of it. The wave in flight
|
||||
when the worker dies cannot be saved -- every caller is already past
|
||||
the check -- but every wave after it must be gated again.
|
||||
"""
|
||||
warm = threading.Event()
|
||||
warm.set()
|
||||
healthy = self._blocking_celery(warm, [[0.4]])
|
||||
embeddings = DelegatedEmbeddings("granite-311m")
|
||||
with patch.dict(
|
||||
"sys.modules", {"application.celery_init": MagicMock(celery=healthy)}
|
||||
):
|
||||
embeddings.embed_query("warm")
|
||||
assert embeddings._verified is True
|
||||
|
||||
# No cooldown, so anything that gates the second wave can only be the
|
||||
# probe -- which engages only because the failure cleared _verified.
|
||||
with patch(
|
||||
"application.vectorstore.embeddings_delegated._FAILURE_COOLDOWN", 0.0
|
||||
), patch("application.vectorstore.embeddings_delegated._PROBE_WAIT", 0.05):
|
||||
dying = threading.Event()
|
||||
died = self._blocking_celery(dying, TimeoutError("worker went away"))
|
||||
self._race(died, embeddings, dying)
|
||||
# The wave that was already in flight all dispatched, as it must.
|
||||
assert died.send_task.call_count == 8
|
||||
assert embeddings._verified is False
|
||||
|
||||
again = threading.Event()
|
||||
still_dead = self._blocking_celery(again, TimeoutError("still gone"))
|
||||
values, errors = self._race(still_dead, embeddings, again)
|
||||
|
||||
assert values == []
|
||||
assert len(errors) == 8
|
||||
# One probe pays the timeout; the other seven fail fast.
|
||||
assert still_dead.send_task.call_count == 1
|
||||
assert sum("still unanswered" in str(e) for e in errors) == 7
|
||||
|
||||
|
||||
class TestTheResultIsForgotten:
|
||||
"""A query vector must not outlive the query that asked for it.
|
||||
|
||||
Reference in new issue
Block a user