Conversation
Adds ConnectionGroupMember.IsSenderOf(object?) and ConnectionGroupExtensions.FindMember, so that a handler for an event forwarded by a connection group (ServerMaintenanceEvent, ConnectionFailed, ...) can say which member it came from, without exposing the member's connection. See #3249.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed resolution for #3249: let a subscriber to an event forwarded by a connection group say which member the event came from, without making
ConnectionGroupMember.Multiplexerpublic.Why not make
MultiplexerpublicThe group owns each member's connection. It attaches the connection when the member connects, and clears it when the member is removed. Making
Multiplexerpublic would turn an identity comparison into a contract on a fullConnectionMultiplexer, one that callers could dispose, close, or send commands to (bypassing group routing), or keep after the group has moved on. It also throws once the member is detached.What this adds
ConnectionGroupMember.IsSenderOf(object? sender): whethersenderis this member, or the connection the member currently holds. It isfalsefor the group itself, fornull, and for a member that has been removed.ConnectionGroupExtensions.FindMember(this IConnectionGroup group, object? sender): the member an event came from, ornull. It lives inStackExchange.Redis.Availability, alongsideIConnectionGroup, so no new usings are needed.Both are additive.
IConnectionGroupis a public interface, so it is left untouched: adding members to it would break implementers, and default interface methods are not available on every target.ConnectionGroupMemberis sealed.This applies to every event the group forwards from its members, not only
ServerMaintenanceEvent:ConnectionFailed,ConnectionRestored,ErrorMessage,HashSlotMoved,ConfigurationChanged, etc., all arrive with the member's own connection assender.Usage
The case from the issue:
Or, to attribute rather than filter:
The active member can change at any time, including just after such a check; that is inherent, and documented.
A note on
MOVINGServer-native maintenance notifications (including
MOVING) are currently disabled inside a multi-group connection; see Which deployments send these. That has been the case since #3191, which shipped in 3.3.0. So the specific scenario in the issue should not arise today. The docs say that restriction is expected to be lifted, though, and Azure's pub/sub maintenance events, which are not subject to it, already arrive throughServerMaintenanceEventinside a group. Either way, how the library reacts to a notification remains an internal detail; this only lets callers know that it happened, and where.Changes
IsSenderOfonConnectionGroupMember, and a newConnectionGroupExtensionswithFindMember.GetMembernow usesIsSenderOf, so there is one definition. It also no longer goes through theMultiplexergetter, which throws when nothing is attached.GroupMemberSenderUnitTestsuses two in-process servers and the real forwarding path. It covers:ActiveMember?.IsSenderOfpicks out exactly one member;docs/Failover.mdhas a new section, "Which member raised an event".The full repo builds clean with
/p:CI=true; unit and group tests pass on net10.0, and the new tests pass on net8.0.Checklist