Grain directory architecture
The grain directory maps a grain identity to an activation address. It is on the critical path when a caller has no usable cached address and when the runtime creates, moves, or removes an activation. Placement chooses a silo; the directory coordinates which activation address is authoritative.
Orleans uses LocalGrainDirectory by default. DistributedGrainDirectory is experimental and must be enabled explicitly.
Default: LocalGrainDirectory
Section titled “Default: LocalGrainDirectory ”LocalGrainDirectory partitions registrations over the membership ring. Hashing a grain identity selects the silo whose local LocalGrainDirectoryPartition is authoritative for that key. This follows the broad consistent-hashing distributed-hash-table model described by Chord, adapted to Orleans membership and activation semantics. Each silo also keeps non-authoritative cache entries to avoid repeated remote lookups.
The default directory preserves these invariants:
- a directory key is derived from the grain identity, not its current location;
- the membership view determines the authoritative owner;
- local cache entries are hints and can be invalidated;
- registration detects competing single-activation addresses;
- a failed or deactivated silo’s addresses are removed or rejected; and
- partition ownership transfers as the membership ring changes.
Message forwarding and invalidation repair stale caches. Forwarding is bounded and is not an application-level retry policy.
Source: LocalGrainDirectory and LocalGrainDirectoryPartition.
Directory selection
Section titled “Directory selection”The runtime resolves a directory per grain type. The unnamed default resolves to LocalGrainDirectory unless the silo has explicitly replaced it. A named implementation of IGrainDirectory can be registered and selected using grain-type metadata.
Custom directories own their consistency, availability, and cleanup behavior. They should define what concurrent registration means, how failed silos are removed, and whether stale reads are possible. The surrounding message router cannot turn an eventually consistent custom directory into a strongly consistent one.
Experimental: DistributedGrainDirectory
Section titled “Experimental: DistributedGrainDirectory ”CoreHostingExtensions.AddDistributedGrainDirectory opts into a view-synchronous directory marked with compiler warning ORLEANSEXP003:
It is not the default. The experimental status allows its API and protocol to evolve.
The implementation divides the hash ring into configurable ranges, analogous to the virtual-node partitioning described by Dynamo. GrainDirectoryOptions.PartitionsPerSilo defaults to 1, not 30. A partition normally serves requests locally. During a membership view change, old and new owners coordinate range locks, snapshots, and ownership transfer. The design applies the virtually synchronous methodology for dynamic service replication and has similarities to Vertical Paxos and primary-backup replication.
Requests and responses carry view information. A range cannot serve a request under an incompatible ownership view. If an orderly transfer is impossible, the new owner recovers registrations by querying active silos rather than assuming the failed owner’s state.
API: CoreHostingExtensions.AddDistributedGrainDirectory and GrainDirectoryOptions. Implementation: hosting registration and DistributedGrainDirectory.
Tradeoffs
Section titled “Tradeoffs”| Property | Default LocalGrainDirectory | Experimental DistributedGrainDirectory |
|---|---|---|
| Status | Default | Opt-in, ORLEANSEXP003 |
| Ownership | Membership consistent-hash ring | Versioned ranges over membership views |
| Normal lookup | Owner partition plus per-silo cache | Owner partition plus view coordination |
| View change | Partition split/merge and cache repair | Sealed ranges and snapshot transfer |
| Recovery emphasis | Duplicate detection and invalidation | Explicit range recovery |
| Configuration | Existing default behavior | GrainDirectoryOptions.PartitionsPerSilo, default 1 |
More partitions can improve ownership granularity but increase transfer and coordination work. This page documents the mechanism; any production rollout of an experimental component should include compatibility, failure, and load testing.
