public async Task TestLockOnDifferentBlobClientTypes( [Values] BlobClientType type, [Values] bool isAsync) { if (isAsync) { await TestAsync(); } else { SyncViaAsync.Run(_ => TestAsync(), default(object)); } async ValueTask TestAsync() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); var name = provider.GetUniqueSafeName(); var client = CreateClient(type, name); if (client is AppendBlobClient appendClient) { Assert.That( Assert.Throws <RequestFailedException>(() => appendClient.CreateIfNotExists()).ToString(), Does.Contain("This feature is not currently supported by the Storage Emulator") ); return; } if (client.GetType() == typeof(BlobBaseClient)) { // work around inability to do CreateIfNotExists for the base client new BlobClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName, name).Upload(Stream.Null); } var @lock = new AzureBlobLeaseDistributedLock(client); await using var handle = await @lock.TryAcquireAsync(); Assert.IsNotNull(handle); await using var nestedHandle = await @lock.TryAcquireAsync(); Assert.IsNull(nestedHandle); } }
public void TestSafeNaming() { var names = new[] { string.Empty, new string('a', 2000), "a/", "a\\", string.Join("/", Enumerable.Repeat("a", 254)), string.Join(@"\", Enumerable.Repeat("b", 254)), new string('/', 254), new string('\\', 254) }; var containerClient = new BlobContainerClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName); foreach (var name in names) { var @lock = new AzureBlobLeaseDistributedLock(containerClient, name); Assert.DoesNotThrow(() => @lock.Acquire()); } }
public void TestCanUseLeaseIdForBlobOperations() { using var provider = new TestingAzureBlobLeaseDistributedLockProvider(); var name = provider.GetUniqueSafeName(); var client = new PageBlobClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName, name); const int BlobSize = 512; client.Create(size: BlobSize); var @lock = new AzureBlobLeaseDistributedLock(client); using var handle = @lock.Acquire(); Assert.Throws <RequestFailedException>(() => client.UploadPages(new MemoryStream(new byte[BlobSize]), offset: 0)) .ErrorCode.ShouldEqual(AzureErrors.LeaseIdMissing); Assert.DoesNotThrow( () => client.UploadPages(new MemoryStream(new byte[BlobSize]), offset: 0, conditions: new PageBlobRequestConditions { LeaseId = handle.LeaseId }) ); handle.Dispose(); Assert.Throws <ObjectDisposedException>(() => handle.LeaseId.ToString()); }
public static int Main(string[] args) { var type = args[0]; var name = args[1]; IDisposable?handle; switch (type) { case nameof(SqlDistributedLock): handle = new SqlDistributedLock(name, SqlServerCredentials.ConnectionString).Acquire(); break; case "Write" + nameof(SqlDistributedReaderWriterLock): handle = new SqlDistributedReaderWriterLock(name, SqlServerCredentials.ConnectionString).AcquireWriteLock(); break; case nameof(SqlDistributedSemaphore) + "1AsMutex": handle = new SqlDistributedSemaphore(name, maxCount: 1, connectionString: SqlServerCredentials.ConnectionString).Acquire(); break; case nameof(SqlDistributedSemaphore) + "5AsMutex": handle = new SqlDistributedSemaphore(name, maxCount: 5, connectionString: SqlServerCredentials.ConnectionString).Acquire(); break; case nameof(PostgresDistributedLock): handle = new PostgresDistributedLock(new PostgresAdvisoryLockKey(name), PostgresCredentials.GetConnectionString(Environment.CurrentDirectory)).Acquire(); break; case "Write" + nameof(PostgresDistributedReaderWriterLock): handle = new PostgresDistributedReaderWriterLock(new PostgresAdvisoryLockKey(name), PostgresCredentials.GetConnectionString(Environment.CurrentDirectory)).AcquireWriteLock(); break; case nameof(EventWaitHandleDistributedLock): handle = new EventWaitHandleDistributedLock(name).Acquire(); break; case nameof(WaitHandleDistributedSemaphore) + "1AsMutex": handle = new WaitHandleDistributedSemaphore(name, maxCount: 1).Acquire(); break; case nameof(WaitHandleDistributedSemaphore) + "5AsMutex": handle = new WaitHandleDistributedSemaphore(name, maxCount: 5).Acquire(); break; case nameof(AzureBlobLeaseDistributedLock): handle = new AzureBlobLeaseDistributedLock( new BlobClient(AzureCredentials.ConnectionString, AzureCredentials.DefaultBlobContainerName, name), o => o.Duration(TimeSpan.FromSeconds(15)) ) .Acquire(); break; case nameof(FileDistributedLock): handle = new FileDistributedLock(new FileInfo(name)).Acquire(); break; case nameof(RedisDistributedLock) + "1": handle = AcquireRedisLock(name, serverCount: 1); break; case nameof(RedisDistributedLock) + "3": handle = AcquireRedisLock(name, serverCount: 3); break; case nameof(RedisDistributedLock) + "2x1": handle = AcquireRedisLock(name, serverCount: 2); // we know the last will fail; don't bother (we also don't know its port) break; case nameof(RedisDistributedLock) + "1WithPrefix": handle = AcquireRedisLock("distributed_locks:" + name, serverCount: 1); break; case "Write" + nameof(RedisDistributedReaderWriterLock) + "1": handle = AcquireRedisWriteLock(name, serverCount: 1); break; case "Write" + nameof(RedisDistributedReaderWriterLock) + "3": handle = AcquireRedisWriteLock(name, serverCount: 3); break; case "Write" + nameof(RedisDistributedReaderWriterLock) + "2x1": handle = AcquireRedisWriteLock(name, serverCount: 2); // we know the last will fail; don't bother (we also don't know its port) break; case "Write" + nameof(RedisDistributedReaderWriterLock) + "1WithPrefix": handle = AcquireRedisWriteLock("distributed_locks:" + name, serverCount: 1); break; case string _ when type.StartsWith(nameof(RedisDistributedSemaphore)): { var maxCount = type.EndsWith("1AsMutex") ? 1 : type.EndsWith("5AsMutex") ? 5 : throw new ArgumentException(type); handle = new RedisDistributedSemaphore( name, maxCount, GetRedisDatabases(serverCount: 1).Single(), // in order to see abandonment work in a reasonable timeframe, use very short expiry options => options.Expiry(TimeSpan.FromSeconds(1)) .BusyWaitSleepTime(TimeSpan.FromSeconds(.1), TimeSpan.FromSeconds(.3)) ).Acquire(); break; } default: Console.Error.WriteLine($"type: {type}"); return(123); } Console.WriteLine("Acquired"); Console.Out.Flush(); if (Console.ReadLine() != "abandon") { handle.Dispose(); } return(0); }
public override string GetSafeName(string name) => AzureBlobLeaseDistributedLock.GetSafeName(name, new BlobContainerClient(AzureCredentials.ConnectionString, this.Strategy.ContainerName));