Пример #1
0
		public async Task RunElectionsForever(CancellationToken token) {
			var leaseWrapper = new BlobLeaseWrapper(_blob, 512);

			while (!token.IsCancellationRequested) {
				await GrabLeaseOrWait(leaseWrapper, token);
			}
		}
Пример #2
0
		async Task GrabLeaseOrWait(BlobLeaseWrapper leaseWrapper, CancellationToken token) {
			// Try to acquire the blob lease, otherwise wait for some time before we can try again.
			var leaseId = await TryAcquireLeaseOrWait(leaseWrapper, token);

			if (string.IsNullOrEmpty(leaseId)) {
				return;
			}
			// Create a new linked cancellation token source, so if either the 
			// original token is canceled or the lease cannot be renewed,
			// then the leader task can be canceled.
			using (var cts =
				CancellationTokenSource.CreateLinkedTokenSource(new[] {token})) {
				// Run the leader task.
				var leaderTask = _leaderTask.Invoke(cts.Token, _blob);

				// Keeps renewing the lease in regular intervals. 
				// If the lease cannot be renewed, then the task completes.
				var renew  = KeepRenewingLease(leaseWrapper, leaseId, cts.Token);

				// When any task completes (either the leader task or when it could
				// not renew the lease) then cancel the other task.
				await CancelAllWhenAnyCompletes(leaderTask, renew, cts);
			}
		}
Пример #3
0
		static async Task<string> TryAcquireLeaseOrWait(BlobLeaseWrapper leaseWrapper,
			CancellationToken token) {
			try {
				var leaseId = await leaseWrapper.AcquireLeaseAsync(token);
				if (!string.IsNullOrEmpty(leaseId)) {
					return leaseId;
				}

				await Task.Delay(AcquireAttemptInterval, token);
				return null;
			}
			catch (OperationCanceledException) {
				return null;
			}
		}
Пример #4
0
		static async Task KeepRenewingLease(BlobLeaseWrapper leaseWrapper, string leaseId,
			CancellationToken token) {
			var renewOffset = new Stopwatch();

			while (!token.IsCancellationRequested) {
				try {
					// Immediately attempt to renew the lease
					// We cannot be sure how much time has passed since the lease was actually acquired
					renewOffset.Restart();
					var renewed = await leaseWrapper.RenewLeaseAsync(leaseId, token);
					renewOffset.Stop();

					if (!renewed) {
						return;
					}

					// We delay based on the time from the start of the last renew request to ensure
					var renewIntervalAdjusted = RenewInterval - renewOffset.Elapsed;

					// If the adjusted interval is greater than zero wait for that long
					if (renewIntervalAdjusted > TimeSpan.Zero) {
						await Task.Delay(RenewInterval - renewOffset.Elapsed, token);
					}
				}
				catch (OperationCanceledException) {
					leaseWrapper.ReleaseLease(leaseId);

					return;
				}
			}
		}