Skip to content

perf(locks): read bucket lock bodies concurrently and count locks for stats - #728

Open
BryanFRD wants to merge 1 commit into
mainfrom
perf/691-lock-listing
Open

BryanFRD wants to merge 1 commit into
mainfrom
perf/691-lock-listing

Conversation

@BryanFRD

@BryanFRD BryanFRD commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Closes #691

  • list_bucket fetches bodies with buffer_unordered(16) instead of one GET at a time. Errors still propagate, so an unreachable store never answers "no locks".
  • /objects/stats uses count() (key listing, no body reads) instead of list().len().

Key-based pagination, the longer-term part of the issue, is split into #727 since it changes listing order.

Tests

  • Bucket listing returns every lock in path order past two batches of reads.
  • Counting bucket locks reads zero bodies.
  • /objects/stats reports the number of locks held.

cargo test -p lfsx-server and clippy pass. The one lfsx-cli gc test failure locally is from a global tag.gpgsign and is unrelated.

… stats

list_bucket fetched one body per key in series, so a push with locking enabled paid N sequential GETs on verify. Bodies are now fetched 16 at a time, matching the other bucket fan-outs. /objects/stats only needs a number, so it uses count(), which lists keys and opens no body.

Refs #691

Signed-off-by: BryanFRD <bryanferrando59@gmail.com>
@BryanFRD
BryanFRD enabled auto-merge (squash) November 3, 2026 22:31

@ferrfleet-interne ferrfleet-interne 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.

Not approved: failed step(s): verify.

Ready to merge. The code review approved with no blocking findings. Formal verification failed to run, so there is no verification result.

What the change does: bucket lock bodies are now read concurrently (buffer_unordered, capped at 16 reads at once), and the stats endpoint uses the key-only count() instead of list().len(). list() still sorts by path afterwards, so output order is unchanged. The new tests cover ordering past one batch of reads (35 locks), zero body reads when counting, and the lock count on the stats route.

Suggestions

  • server/src/routes.rs:145 (suggestion): count() counts entries, while list() drops any body that fails to decode. A corrupt or foreign .json under .locks/ now shows up in stats.locks but not in GET /locks. That is probably the better tradeoff for a dashboard figure, and no fix is needed. If the two numbers must agree, say in the count() comment that it counts entries, not decodable locks.

Formal verification: the step failed and returned no result, so nothing was checked.

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.

perf(locks): stop reading every lock body in series on bucket backends

1 participant