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])); }
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])); }
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])); }