Skip to content

docs: proposal — allocation capacity gating, expiry, and finalization - #47

Open
frrist wants to merge 1 commit into
mainfrom
proposal/allocation-capacity-and-expiry
Open

docs: proposal — allocation capacity gating, expiry, and finalization#47
frrist wants to merge 1 commit into
mainfrom
proposal/allocation-capacity-and-expiry

Conversation

@frrist

@frrist frrist commented Jul 29, 2026

Copy link
Copy Markdown
Member

Summary

Design proposal for two gaps in the blob allocate/accept flow, plus the lifecycle model that ties them together.
Document: docs/proposals/allocation-capacity-and-expiry.md.

  • Capacity-aware allocation: deny blob/allocate above a configurable occupancy threshold, with per-backend monitors (statfs for flatfs, declared capacity + periodic bucket scan for MinIO/S3) and pending-byte accounting from pdp_piece_uploads.
  • Real allocation expiry: configurable TTL enforced at allocate, upload, and accept; today Expires is hardcoded to 24h and nothing reads it.
  • Finalize-at-accept (recommended): blob/accept stamps the allocation record (AcceptedAt), making it the durable per-space storage ledger; the janitor then deletes pending+expired records on a single-store rule.
    Includes a race analysis versus the acceptance-aware-janitor alternative and why the latter was rejected.

Why these two features travel together

They are the two halves of making "an allocation reserves space" true, and the dependency runs one direction: capacity gating is incorrect without expiry, while expiry stands alone.

For the capacity gate to work for a reservation system it must count outstanding reservations (Used + Pending + size > threshold × Total), otherwise a burst of allocations all pass the check against the same free space and collectively overshoot it.
But once reservations count against capacity, they must be able to die: every abandoned upload otherwise parks its check_size in pdp_piece_uploads forever, Pending grows monotonically, and the node ends up denying all allocations while sitting on an empty disk.
That is the guaranteed steady state, not a tail risk — clients abandon uploads routinely.
This is the standard admission-control + lease pattern: an admission test over a finite resource requires grants that expire, or the resource leaks.

The reverse motivation is weaker: expiry alone is correct but only cleans up cheap metadata and closes the content/retrieve authorization hole for never-fulfilled allocations.
The asymmetry is why the phasing puts expiry first (phase 1) and capacity gating on top of it (phase 2).

No wire/libforge schema changes; coordination points for the upload service are called out in the doc (§9).

Review focus

  • §6 janitor design and the finalization recommendation
  • §12 open questions (strict vs lenient accept at the deadline edge; whether the upload PUT should also gate on capacity)

🤖 Generated with Claude Code

Design proposal covering:
- capacity-aware blob/allocate (per-backend monitors for flatfs/MinIO,
  configurable occupancy threshold, named receipt failure)
- real allocation expiry (configurable TTL enforced at allocate, upload,
  and accept) with a periodic janitor
- finalizing allocations at blob/accept (AcceptedAt field) so cleanup is
  a single-store decision

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@frrist
frrist requested a review from alanshaw as a code owner July 29, 2026 22:42
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.

1 participant