public async Task <CoordinatorExitReason> StartEventLoopAsync() { Stopwatch rebalanceTimer = new(); while (!coordinatorToken.IsCancellationRequested) { if (disconnectedTimer.IsRunning && disconnectedTimer.Elapsed > sessionTimeout) { zooKeeperService.SessionExpired(); await CleanUpAsync(); return(CoordinatorExitReason.SessionExpired); } if (events.TryTake(out CoordinatorEvent coordinatorEvent)) { switch (coordinatorEvent) { case CoordinatorEvent.SessionExpired: zooKeeperService.SessionExpired(); await CleanUpAsync(); return(CoordinatorExitReason.SessionExpired); case CoordinatorEvent.NoLongerCoordinator: await CleanUpAsync(); return(CoordinatorExitReason.NoLongerCoordinator); case CoordinatorEvent.PotentialInconsistentState: await CleanUpAsync(); return(CoordinatorExitReason.PotentialInconsistentState); case CoordinatorEvent.FatalError: await CleanUpAsync(); return(CoordinatorExitReason.FatalError); case CoordinatorEvent.RebalancingTriggered: if (events.Any()) { // skip this event. All other events take precedence over rebalancing // there may be multiple rebalancing events, so if the events collection // consists only of rebalancing events then we'll just process the last one } else if (!rebalanceTimer.IsRunning || rebalanceTimer.Elapsed > minimumRebalancingInterval) { await CancelRebalancingIfInProgressAsync(); rebalanceTimer.Reset(); rebalanceTimer.Start(); logger.Info(clientId, "Coordinator - Rebalancing triggered"); rebalancingTask = Task.Run(async() => await TriggerRebalancing(rebalancingCts.Token)); } else { // if enough time has not passed since the last rebalancing just readd it events.Add(CoordinatorEvent.RebalancingTriggered); } break; default: await CleanUpAsync(); return(CoordinatorExitReason.PotentialInconsistentState); } } await WaitFor(TimeSpan.FromSeconds(1)); } if (coordinatorToken.IsCancellationRequested) { await CancelRebalancingIfInProgressAsync(); await zooKeeperService.CloseSessionAsync(); return(CoordinatorExitReason.Cancelled); } return(CoordinatorExitReason.PotentialInconsistentState); // if this happens then we have a correctness bug }
public async Task <FollowerExitReason> StartEventLoopAsync() { // it is possible that rebalancing has been triggered already, so check // if any resources have been assigned already and if so, add a RebalancingTriggered event await CheckForRebalancingAsync(); while (!followerToken.IsCancellationRequested) { if (disconnectedTimer.IsRunning && disconnectedTimer.Elapsed > sessionTimeout) { zooKeeperService.SessionExpired(); await CleanUpAsync(); return(FollowerExitReason.SessionExpired); } if (events.TryTake(out FollowerEvent followerEvent)) { switch (followerEvent) { case FollowerEvent.SessionExpired: zooKeeperService.SessionExpired(); await CleanUpAsync(); return(FollowerExitReason.SessionExpired); case FollowerEvent.IsNewLeader: await CleanUpAsync(); return(FollowerExitReason.PossibleRoleChange); case FollowerEvent.PotentialInconsistentState: await CleanUpAsync(); return(FollowerExitReason.PotentialInconsistentState); case FollowerEvent.FatalError: await CleanUpAsync(); return(FollowerExitReason.FatalError); case FollowerEvent.RebalancingTriggered: if (events.Any()) { // skip this event. All other events take precedence over rebalancing // there may be multiple rebalancing events, so if the events collection // consists only of rebalancing events then we'll just process the last one } else { await CancelRebalancingIfInProgressAsync(); logger.Info(clientId, "Follower - Rebalancing triggered"); rebalancingTask = Task.Run(async() => await RespondToRebalancing(rebalancingCts.Token)); } break; default: await CleanUpAsync(); return(FollowerExitReason.PotentialInconsistentState); } } await WaitFor(TimeSpan.FromSeconds(1)); } if (followerToken.IsCancellationRequested) { await CleanUpAsync(); await zooKeeperService.CloseSessionAsync(); return(FollowerExitReason.Cancelled); } return(FollowerExitReason.PotentialInconsistentState); }