namespace NATS.Server.JetStream.Cluster; /// /// Topology-aware peer selection for stream/consumer replica placement. /// Go reference: jetstream_cluster.go:7212 selectPeerGroup. /// public static class PlacementEngine { /// /// Selects peers for a new replica group based on available nodes, tags, and cluster affinity. /// Filters unavailable peers, applies cluster/tag/exclude-tag policy, then picks the top N /// peers ordered by available storage descending. /// public static RaftGroup SelectPeerGroup( string groupName, int replicas, IReadOnlyList availablePeers, PlacementPolicy? policy = null) { // 1. Filter out unavailable peers. IEnumerable candidates = availablePeers.Where(p => p.Available); // 2. If policy has Cluster, filter to matching cluster. if (policy?.Cluster is { Length: > 0 } cluster) candidates = candidates.Where(p => string.Equals(p.Cluster, cluster, StringComparison.OrdinalIgnoreCase)); // 3. If policy has Tags, filter to peers that have ALL required tags. if (policy?.Tags is { Count: > 0 } requiredTags) candidates = candidates.Where(p => requiredTags.All(tag => p.Tags.Contains(tag))); // 4. If policy has ExcludeTags, filter out peers with any of those tags. if (policy?.ExcludeTags is { Count: > 0 } excludeTags) candidates = candidates.Where(p => !excludeTags.Any(tag => p.Tags.Contains(tag))); // 5. If not enough peers after filtering, throw InvalidOperationException. var filtered = candidates.ToList(); if (filtered.Count < replicas) throw new InvalidOperationException( $"Not enough peers available to satisfy replica count {replicas}. " + $"Available after policy filtering: {filtered.Count}."); // 6. Sort remaining by available storage descending. var selected = filtered .OrderByDescending(p => p.AvailableStorage) .Take(replicas) .Select(p => p.PeerId) .ToList(); // 7. Return RaftGroup with selected peer IDs. return new RaftGroup { Name = groupName, Peers = selected, }; } } /// /// Describes a peer node available for placement consideration. /// Go reference: jetstream_cluster.go peerInfo — peer.id, peer.offline, peer.storage. /// public sealed class PeerInfo { public required string PeerId { get; init; } public string Cluster { get; set; } = string.Empty; public HashSet Tags { get; init; } = new(StringComparer.OrdinalIgnoreCase); public bool Available { get; set; } = true; public long AvailableStorage { get; set; } = long.MaxValue; } /// /// Placement policy specifying cluster affinity and tag constraints. /// Go reference: jetstream_cluster.go Placement struct — cluster, tags. /// public sealed class PlacementPolicy { public string? Cluster { get; set; } public HashSet? Tags { get; set; } public HashSet? ExcludeTags { get; set; } }