Skip to content

feat: expose read-only views of live hashrings via Builder.RingFor - #6

Open
ecordell wants to merge 1 commit into
mainfrom
ring-view
Open

ecordell wants to merge 1 commit into
mainfrom
ring-view

Conversation

@ecordell

Copy link
Copy Markdown
Contributor

Problem

Applications that route work by hashring key need to know which member owns a key before they dial. One example is a batch: to group the items by owner, the caller must query the ring. The ring lives inside the balancer, and gRPC constructs balancers lazily and internally, so callers had no way to reach it.

The concrete motivation is object-based dispatch in SpiceDB: a Check dispatch carries up to 100 resource IDs, and routing by object requires the dispatcher to group those IDs by ring owner before it sends one RPC per owner.

Change

The builder is the rendezvous point, because the application already holds it. RingFor(target) returns a stable RingView handle with these properties:

  • Callers can get a view before any balancer exists for the target.
  • A view returns ErrNoRing until its balancer publishes a ring.
  • A view follows ring replacements (ReplicationFactor changes).
  • A view shows membership changes as they happen.
  • A view empties again when its balancer closes.

A view reads the same ring object that the picker routes with, so callers and the picker agree on ownership. The one exception is a membership change that races the query, which costs locality for that one request, never delivery.

RingFor is a new method on the Builder interface. That breaks external implementers of the interface. Callers of NewBuilder are unaffected.

Tests

Six new tests cover the view lifecycle: before the balancer exists, against the live ring, across membership changes, across ring replacement, after Close, and across two targets. The suite passes with -race.

Applications that route work by hashring key need to know which member
owns a key before they dial. One example is a batch: to group the
items by owner, the caller must query the ring. The ring lives inside
the balancer, and gRPC constructs balancers lazily and internally, so
callers had no way to reach it.

The builder is the rendezvous point. RingFor(target) returns a stable
RingView handle with these properties:

- Callers can get a view before any balancer exists for the target.
- A view returns ErrNoRing until its balancer publishes a ring.
- A view follows ring replacements (ReplicationFactor changes).
- A view shows membership changes as they happen.
- A view empties again when its balancer closes.

A view reads the same ring object that the picker routes with, so
callers and the picker agree on ownership. The one exception is a
membership change that races the query.
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