Skip to content

Add explicit publisher buffer leases - #118

Merged
dallison merged 3 commits into
mainfrom
publisher_leases
Aug 13, 2026
Merged

Add explicit publisher buffer leases#118
dallison merged 3 commits into
mainfrom
publisher_leases

Conversation

@dallison

@dallison dallison commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

Adds explicit publisher buffer leases so a publisher can own multiple unpublished channel slots at the same time. This supports asynchronous producers, external-memory pipelines, and workflows that must reclaim the exact slot reported by a retirement notification.

  • Exposes lease APIs in the C++, C, Python, and Rust clients.
  • Adds ScopedPublisherBufferLease, a move-only C++ RAII wrapper that automatically releases an unpublished lease on scope exit.
  • Supports acquiring any available slot, publishing or releasing it, and reclaiming a specific retired slot.
  • Uses generation-based lease_id tokens so stale leases cannot publish, release, or access metadata after a slot is reused.
  • Supports payload metadata, split buffers, subscriber queues, virtual channels, client reconnection, and shadow-server recovery.
  • Adds server-side capacity accounting for publisher lease budgets and subscriber active-message budgets.
  • Adds configurable channel-wide subscriber limits through max_subscribers.

How to use publisher leases

  1. Configure max_outstanding_slot_leases on the publisher. The default is 1.
  2. Acquire a lease:
    • C++: AcquireScopedBufferLease() (preferred) or AcquireBufferLease().
    • Python/Rust/C: use the corresponding explicit lease API.
  3. Write the payload through the lease buffer and optionally populate its metadata.
  4. Publish the lease, or release it without publishing. Either operation invalidates the lease token.
  5. If exact-slot reuse is needed, enable retirement notifications, read the retired int32_t slot ID from the retirement fd, and call the reclaim API. Reclamation returns a new lease_id.

The existing GetMessageBuffer() / PublishMessage() workflow remains available and unchanged. Applications should choose either the implicit-buffer or explicit-lease workflow for a publisher. Explicit leases do not hold the thread-safe client mutex for the lifetime of the buffer.

For unreliable channels, registration enforces this capacity invariant:

sum(publisher max outstanding leases)
  + sum(subscriber max active messages)
  <= num_slots - 1

This reserves enough headroom for every configured lease and active-message budget. Subscriber queue storage uses its separate queue arena and does not consume this slot budget.

Documentation

See Publisher Buffer Leases for complete C++, C, Python, and Rust examples, lease lifecycle rules, retirement and exact-slot reclamation, capacity accounting, and subscriber limits.

Test plan

  • bazelisk test //...
  • bazelisk test //client:client_test --test_arg=--use_split_buffers
  • Cross-language tests cover multiple outstanding leases, RAII cleanup, metadata, stale-token rejection, release/reclaim behavior, subscriber queue delivery and fallback, split buffers, and shadow recovery.

Reserve lease-aware channel capacity and expose safe multi-slot publishing across C++, C, Python, and Rust clients, including subscriber limits and shadow recovery.
Provide an RAII lease wrapper so unpublished slots are reliably released on early returns and document the preferred lifecycle.
Preserve queue delivery and recovery semantics across leased publish paths while retaining lease capacity accounting and cross-language coverage.
@dallison
dallison marked this pull request as ready for review August 13, 2026 00:31
@dallison
dallison merged commit 8576982 into main Aug 13, 2026
46 checks passed
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