Repository navigation
perf: check each path once per storage-event batch and run paths concurrently - #2072
Merged
Merged
Conversation
…hs concurrently Deleting old object versions (a version prune) sends one OBJECT_DELETED per version. In production on 2026-11-06 a webhook batch averaged 30 events for 10 paths, each event checked one after another (entity lookup + current-object HEAD, ~0.33 s), so a batch took ~10 s and the webhook queue fell behind. - Operations are grouped by path in arrival order. Consecutive deletes of one path collapse to one check, counted as the events it covers (processed or failed). A delete only asks whether the object is still there, so one check answers them all. A create between deletes stays its own step, in order. - `run_runtime_storage_event_operations` takes `max_concurrent_paths` (default 1: unchanged, one path at a time). Above 1, different paths run concurrently; one path's steps stay sequential. A failure the processor raises cancels the rest and fails the batch as itself. - `StorageEventIndexRuntime.max_concurrent_paths` passes it through routing. - `StorageEventOperationProcessor` creates its delete resources under a lock, so concurrent paths share one set. Tests cover the collapse, ordering across a create, failure counts, the concurrency cap, the sequential default, a raised failure, and shared delete resources. Each fails with its guard removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016N9c6ouiT4Wid3arGR41Dv Signed-off-by: phernandez <paul@basicmachines.co>
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A version prune deletes old object versions, and Tigris sends one
OBJECT_DELETEDnotification per version. In production on 2026-11-06 the webhook batches during a prune averaged 30.3 events for 10.3 distinct paths.run_runtime_storage_event_operationshandled every event one after another (entity lookup plus a current-object HEAD, about 0.33 s each), so a batch took about 10 s and the cloud webhook queue fell 30+ minutes behind. That delay hits every workspace's sync and external edits, because they share the queue.What
run_runtime_storage_event_operations(..., max_concurrent_paths=1). The default keeps today's behavior. Above 1, different paths run concurrently while one path's steps stay in order (a create between two deletes still runs between them). A failure the processor chooses to raise cancels the other paths and fails the batch as that exception, as it stopped the sequential loop before.StorageEventIndexRuntime.max_concurrent_pathspasses the setting through project routing.StorageEventOperationProcessorcreates its lazy delete resources under a lock, so concurrent paths share one set.Local Basic Memory keeps the default (one path at a time). Cloud will pass the webhook job's share of the worker's tenant database connection budget, so the fan-out never exceeds connections the job can hold (the cloud #1844 rule).
Tests
New tests in
tests/test_runtime_storage_events.pyandtests/index/test_storage_event_operation_processor.py:ExceptionGroup;Each guard was checked by breaking it: no collapse fails 2 tests, never concurrent fails the cap test, no lock fails the shared-resources test.
tests/test_runtime_storage_events.pyplustests/index/pass (252). Ruff clean;just typecheckreports only the existingpymilvusoptional-dependency imports.🤖 Generated with Claude Code
https://claude.ai/code/session_016N9c6ouiT4Wid3arGR41Dv