public async Task<bool> TryLockAsync( LockToken token, int tries = 16, // this is NOT retry - it is try int retryTimeoutMilliseconds = 15000, int timeoutMilliseconds = 15000) { if (tries < 1) tries = 1; var blob = await GetBlobAsync(token.ResourceId); for (int i = 0; i < tries; i++) { try { await blob.AcquireLeaseAsync( TimeSpan.FromMilliseconds(timeoutMilliseconds), token.TokenId.ToString("N")); return true; } catch (Exception e) { Trace.TraceInformation("Lock attempt - already locked: {0}", e); // ignore } await Task.Delay(TimeSpan.FromMilliseconds(retryTimeoutMilliseconds / tries)); } return false; }
public async Task IncrementAsync(string counterName, string id, long value) { var key = string.Format("____COUNTER____{0}-{1}", counterName, id); var token = new LockToken(key); var result = await _lockStore.TryLockAsync(token); if(!result) throw new TimeoutException("Could not lock the resource"); var blob = await GetBlobAsync(key); var text = await blob.DownloadTextAsync(); var current = long.Parse(string.IsNullOrEmpty(text) ? "0" : text); var newValue = current + value; if(newValue < 0) throw new InvalidOperationException("Value cannot get below zero: " + newValue); await blob.UploadTextAsync(newValue.ToString()); await _lockStore.ReleaseLockAsync(token); }
public void TwoCannotLockAtTheSameTime() { var locker = new AzureLockStore( new BlobSource() { ContainerName = "band25", ConnectionString = ConnectionString, Path = "this/is/great/" }); var resource = Guid.NewGuid().ToString(); var token = new LockToken(resource); var canLock = locker.TryLockAsync(token).Result; Assert.True(canLock); var newtoken = new LockToken(resource); var canDoubleLock = locker.TryLockAsync(newtoken, 1, 100).Result; Assert.False(canDoubleLock); }
public async Task<Tuple<IEnumerable<Event>, bool>> TryScheduleAsync(DiagnosticsSource source) { // if Stop offset has been reached if (source.StopOffsetPoint != null && source.LastOffsetPoint != null && source.LastOffsetPoint.CompareTo(source.StopOffsetPoint) >= 0) return new Tuple<IEnumerable<Event>, bool>(Enumerable.Empty<Event>(), false); var lockToken = new LockToken(source.ToTypeKey()); int seconds = Convert.ToInt32(_configurationValueProvider.GetValue(ConfigurationKeys.ClusterLockDurationSeconds)); if (!(await _lockStore.TryLockAsync(lockToken, 2, 1000, seconds * 1000))) { TheTrace.TraceInformation("I could NOT be master for {0}", source.ToTypeKey()); return new Tuple<IEnumerable<Event>, bool>(Enumerable.Empty<Event>(), false); } try { var events = await DoSchedule(source); return new Tuple<IEnumerable<Event>, bool>(events, true); } finally { Task.Run( () => _lockStore.ReleaseLockAsync(lockToken)).Wait(); } }
public async Task ReleaseLockAsync(LockToken token) { var blob = await GetBlobAsync(token.ResourceId); await blob.ReleaseLeaseAsync(AccessCondition.GenerateLeaseCondition(token.TokenId.ToString("N"))); }