public RoundBasedRegister(IIntercomMessageHub intercomMessageHub, IBallotGenerator ballotGenerator, ISynodConfigurationProvider synodConfigProvider, LeaseConfiguration leaseConfig, ILogger logger) { this.logger = logger; this.synodConfigProvider = synodConfigProvider; this.leaseConfig = leaseConfig; this.intercomMessageHub = intercomMessageHub; readBallot = ballotGenerator.Null(); writeBallot = ballotGenerator.Null(); listener = intercomMessageHub.Subscribe(); listener.Where(m => m.Equals(ConsensusMessages.LeaseRead)).Subscribe(OnReadReceived); listener.Where(m => m.Equals(ConsensusMessages.LeaseWrite)).Subscribe(OnWriteReceived); ackReadStream = listener.Where(m => m.Equals(ConsensusMessages.LeaseAckRead)); nackReadStream = listener.Where(m => m.Equals(ConsensusMessages.LeaseNackRead)); ackWriteStream = listener.Where(m => m.Equals(ConsensusMessages.LeaseAckWrite)); nackWriteStream = listener.Where(m => m.Equals(ConsensusMessages.LeaseNackWrite)); WaitBeforeNextLeaseIssued(leaseConfig); }
public BallotGenerator(LeaseConfiguration config) { this.config = config; lastBallotTimestamp = new BallotTimestamp { MessageNumber = 0, Timestamp = DateTime.UtcNow }; }
public void TwoBallotsGeneratedWithinSafetyPeriod_HaveDifferentMessageNumber() { var identity = new byte[] { 0 }; var leaseConfig = new LeaseConfiguration { ClockDrift = TimeSpan.FromMilliseconds(500) }; var ballotGenerator = new BallotGenerator(leaseConfig); var ballot1 = ballotGenerator.New(identity); Thread.Sleep((int)leaseConfig.ClockDrift.TotalMilliseconds / 10); var ballot2 = ballotGenerator.New(identity); Assert.GreaterOrEqual(leaseConfig.ClockDrift, ballot2.Timestamp - ballot1.Timestamp); Assert.AreNotEqual(ballot1.MessageNumber, ballot2.MessageNumber); }
public LeaseProvider(IRoundBasedRegister register, IBallotGenerator ballotGenerator, LeaseConfiguration config, ISynodConfigurationProvider synodConfigProvider, ILogger logger) { ValidateConfiguration(config); localNode = synodConfigProvider.LocalNode; this.logger = logger; this.config = config; this.ballotGenerator = ballotGenerator; this.register = register; leaseRenewWaitTimeout = TimeSpan.FromMilliseconds(10); renewGateway = new SemaphoreSlim(1); leaseTimer = new Timer(state => ScheduledReadOrRenewLease(), null, TimeSpan.FromMilliseconds(-1), TimeSpan.FromMilliseconds(-1)); }
private void ValidateConfiguration(LeaseConfiguration config) { if (config.NodeResponseTimeout.TotalMilliseconds * 2 > config.MessageRoundtrip.TotalMilliseconds) { throw new Exception($"{nameof(config.NodeResponseTimeout)}[{config.NodeResponseTimeout.TotalMilliseconds} msec] " + "should be at least 2 times shorter than " + $"{nameof(config.MessageRoundtrip)}[{config.MessageRoundtrip.TotalMilliseconds} msec]"); } if (config.MaxLeaseTimeSpan - config.MessageRoundtrip.MultiplyBy(2) - config.ClockDrift <= TimeSpan.Zero) { throw new Exception($"{nameof(config.MaxLeaseTimeSpan)}[{config.MaxLeaseTimeSpan.TotalMilliseconds} msec] " + "should be longer than " + $"(2 * {nameof(config.MessageRoundtrip)}[{config.MessageRoundtrip.TotalMilliseconds} msec] " + $"+ {nameof(config.ClockDrift)}[{config.ClockDrift.TotalMilliseconds} msec])"); } }
private void WaitBeforeNextLeaseIssued(LeaseConfiguration config) => Task.Delay(config.ClockDrift).ContinueWith(_ => StartIntercomMessageHub());