예제 #1
0
        private async Task <Result <Role> > UpdateRoleAsync(OperationContext context, bool release)
        {
            return(await context.PerformOperationAsync <Result <Role> >(
                       Tracer,
                       async() =>
            {
                // This mutex ensure that Release of master role during shutdown and Heartbeat role acquisition are synchronized.
                // Ensuring that a heartbeat during shutdown doesn't trigger the released master role to be acquired again.
                using (await _roleMutex.AcquireAsync())
                {
                    if (ShutdownStarted)
                    {
                        // Don't acquire a role during shutdown
                        return Role.Worker;
                    }

                    var configuredRole = _configuration.Checkpoint?.Role;
                    if (configuredRole != null)
                    {
                        return configuredRole.Value;
                    }

                    var localMachineName = LocalMachineLocation.ToString();

                    var masterAcquisitonResult = await _masterLeaseKey.UseReplicatedHashAsync(context, _configuration.RetryWindow, RedisOperation.UpdateRole, (batch, key) => batch.AcquireMasterRoleAsync(
                                                                                                  masterRoleRegistryKey: key,
                                                                                                  machineName: localMachineName,
                                                                                                  currentTime: _clock.UtcNow,
                                                                                                  leaseExpiryTime: _configuration.Checkpoint.MasterLeaseExpiryTime,
                                                                                                  // 1 master only is allowed. This should be changed if more than one master becomes a possible configuration
                                                                                                  slotCount: 1,
                                                                                                  release: release
                                                                                                  )).ThrowIfFailureAsync();

                    if (release)
                    {
                        Tracer.Debug(context, $"'{localMachineName}' released master role.");
                        return Role.Worker;
                    }

                    if (masterAcquisitonResult != null)
                    {
                        var priorMachineName = masterAcquisitonResult.Value.PriorMasterMachineName;
                        if (priorMachineName != localMachineName || masterAcquisitonResult.Value.PriorMachineStatus != SlotStatus.Acquired)
                        {
                            Tracer.Debug(context, $"'{localMachineName}' acquired master role from '{priorMachineName}', Status: '{masterAcquisitonResult?.PriorMachineStatus}', LastHeartbeat: '{masterAcquisitonResult?.PriorMasterLastHeartbeat}'");
                        }

                        return Role.Master;
                    }
                    else
                    {
                        return Role.Worker;
                    }
                }
            },
                       Counters[GlobalStoreCounters.UpdateRole]));
        }
예제 #2
0
        public Task <BoolResult> RegisterCheckpointAsync(OperationContext context, string checkpointId, EventSequencePoint sequencePoint)
        {
            return(context.PerformOperationAsync(
                       Tracer,
                       async() =>
            {
                Contract.Assert(sequencePoint.SequenceNumber != null);

                var checkpoint = new RedisCheckpointInfo(checkpointId, sequencePoint.SequenceNumber.Value, _clock.UtcNow, LocalMachineLocation.ToString());
                Tracer.Debug(context, $"Saving checkpoint '{checkpoint}' into the central store.");

                var slotNumber = await _checkpointsKey.UseReplicatedHashAsync(
                    context,
                    _configuration.RetryWindow,
                    RedisOperation.UploadCheckpoint,
                    (batch, key) => batch.AddCheckpointAsync(key, checkpoint, MaxCheckpointSlotCount)).ThrowIfFailureAsync();

                Tracer.Debug(context, $"Saved checkpoint into slot '{slotNumber}'.");
                return BoolResult.Success;
            },
                       Counters[GlobalStoreCounters.RegisterCheckpoint]));
        }
예제 #3
0
        public Task <BoolResult> RegisterCheckpointAsync(OperationContext context, string checkpointId, EventSequencePoint sequencePoint)
        {
            return(context.PerformOperationAsync(
                       Tracer,
                       () =>
            {
                Contract.Assert(sequencePoint.SequenceNumber != null);

                var checkpoint = new RedisCheckpointInfo(checkpointId, sequencePoint.SequenceNumber.Value, _clock.UtcNow, LocalMachineLocation.ToString());
                Tracer.Debug(context, $"Saving checkpoint '{checkpoint}' into the central store.");

                return ExecuteRedisAsync(context, async redisDb =>
                {
                    var slotNumber = await redisDb.ExecuteBatchAsync(context, batch =>
                    {
                        return batch.AddCheckpointAsync(_checkpointsKey, checkpoint, MaxCheckpointSlotCount);
                    }, RedisOperation.UploadCheckpoint);

                    Tracer.Debug(context, $"Saved checkpoint into slot '{slotNumber}' on {GetDbName(redisDb)}.");
                    return BoolResult.Success;
                });
            },
                       Counters[GlobalStoreCounters.RegisterCheckpoint]));
        }