apache / apache/asyncband

Add capacity reservation to bounded MPMC senders

Open
#297 1 comment 0 reactions 0 assignees View on GitHub
enhancement good first issue help wanted
Dominant language
Rust
Stars
269
Forks
38
Avg merge
16h 44m
Merged PRs (30d)
102

Description

## Motivation

The bounded MPMC queue added in #265 provides `send` and `try_send`, but lacks the capacity reservation API already available on bounded MPSC. Callers should be able to wait for space before constructing a message, or keep ownership of a message while racing a capacity wait against cancellation.

## Proposed API

Add `BoundedSender::reserve`, `BoundedSender::try_reserve`, and a borrowed `mpmc::Permit<'_, T>`, following the existing MPSC API:

```rust
pub async fn reserve(&self) -> Result, SendError<()>>;
pub fn try_reserve(&self) -> Result, TrySendError<()>>;

// On Permit<'_, T>:
pub fn send(self, value: T) -> Result<(), SendError>;
```

## Contract

- Queued messages, held permits, and capacity granted to pending waiters together must not exceed the configured capacity. A notification alone does not reserve a slot: the current MPMC wake-and-retry protocol needs explicit capacity ownership.
- Grant capacity in wait-queue order, as bounded MPSC does. New sends and reservations must not steal already granted capacity.
- Dropping an unused permit or cancelling a granted reservation returns capacity exactly once and allows another sender to progress. Cancelled sends must release their waiting resources before dropping the unsent payload.
- A permit reserves space, not message order. Messages become ordered when they are actually enqueued.
- When the last receiver is dropped, pending reservations fail with `SendError<()>`; sending through an existing permit returns the unsent value. A permit does not keep receivers alive.
- `send(value)` keeps its current cancellation contract: cancelling a pending send drops the unsent value. Reservation lets the caller wait without moving that value into the wait future.

## Implementation and validation

Use the [bounded MPSC implementation](https://github.com/apache/asyncband/tree/9319ab49dfe24807840dcdbb6694e7f72cb66873/asyncband/src/mpsc/bounded) as the behavioral reference. A simple mutex-based capacity model is sufficient; account for multiple competing receivers without copying the unique-receiver assumptions.

Add deterministic coverage for exact capacity with mixed sends and permits, grant ordering, cancellation before and after a grant, unused-permit drop, last-receiver disconnection, and `Permit::send` error ownership. Include an example that constructs a message only after reservation succeeds, and run the applicable `cargo x` checks.

Unbounded reservations, owned permits, batch reservations, and performance optimization are outside this issue. Follow-up to #211 and #265; part of #206.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading the bounded MPSC implementation at asyncband/src/mpsc/bounded and the bounded MPMC sender added in #265. Trace the sender, wait-queue, and permit entry points, then add deterministic coverage for capacity, ordering, cancellation, disconnection, and Permit::send ownership. Include the reservation example and run the applicable cargo x checks.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.