예제 #1
0
        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
        }
예제 #2
0
        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);
        }