public async Task TestDisposeAsync_Mutex_Is_Not_Acquired() { var mutexName = Guid.NewGuid().ToString(); const string expectedMutexChallenge = "123"; var distributedMutexClientMock = new Mock <IDistributedMutexClient>(); distributedMutexClientMock.Setup(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>())).ReturnsAsync(expectedMutexChallenge); distributedMutexClientMock.Setup(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>())).Returns(Task.CompletedTask); await using var distributedMutex = new DistributedMutex(distributedMutexClientMock.Object, new LogProvider.NoOpLogger(), mutexName, CancellationToken.None); await distributedMutex.DisposeAsync(); Assert.True(distributedMutex.Disposed); Assert.False(distributedMutex.Acquired); distributedMutexClientMock.Verify(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>()), Times.Never); distributedMutexClientMock.Verify(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>()), Times.Never); }
public Bus(IEntityFactory entityFactory, IVolumeHandler volumeHandler, IPubSubFactory pubSubFactory, IStateManager stateManager, IProcessDataStorage storage, IDistributedMutexFactory distributedMutexFactory, IResolver resolver, IBatchLoggerFactory batchLoggerFactory) { EntityFactory = entityFactory; VolumeHandler = volumeHandler; PubSubFactory = pubSubFactory; _stateManager = stateManager; _storage = storage; DistributedMutexFactory = distributedMutexFactory; _resolver = resolver; _batchLoggerFactory = batchLoggerFactory; _cts = new CancellationTokenSource(); _cancellationToken = _cts.Token; HookExceptionEvents(); _logger = batchLoggerFactory.GetSystemLogger(); EventAggregator = new TinyEventAggregator(); var wrapper = new BusStateManager(_stateManager, _logger, resolver); _stateManager = wrapper; var originalStorage = _storage; _storage = new CacheBusWrapper(_logger, originalStorage, resolver); _cacheCommandPipeline = new CacheStoragePipeline(_logger, _cancellationToken, originalStorage); _cacheAside = new CacheAside(_stateManager, _storage, EventAggregator, _logger, batchLoggerFactory); _processRepository = _resolver.Resolve <IProcessRepository>(); //var taskListener = resolver.Resolve<ITaskListener>(); //if (!ReferenceEquals(taskListener, _processRepository)) //{ // Console.WriteLine("ALERT"); //} _taskExecutorsRepo = new TaskExecutorsPool(_logger, _cacheAside, _cancellationToken, _stateManager, _processRepository, EventAggregator, resolver, _logger); //BuildCommandHandlerPipeline(); _statePersistencePipeline = new StatePersistencePipeline(_logger, _cancellationToken); this._databasePipeline = new DatabasePipeline(_logger, _cancellationToken, 0);//todo 500 _taskProcessorPipeline = GetTaskProcessorPipeLine(); //_grouPipeline=new GroupHandlerPipeline(_stateManager, _logger, _branchEngineSubscriber); //_volumePipeline = new ProcessVolumePipeline(_cancellationToken, _logger, _stateManager, _cacheAside, _processRepository, VolumeHandler, resolver, EventAggregator, _branchEngineSubscriber); _branchEngineSubscriber = new BatchEngineSubscribers(); //_watchDog = new ProcessWatchDog(_logger, StateManager, _branchEngineSubscriber, _cacheAside, SerializersFactory.Instance, EntityFactory, EventAggregator, Storage); //watchDog.Start(_cancellationToken);//todo // _grouPipeline = new Pipeline<GroupMessage>(_watchDog); //_watchDogPipeline = new Pipeline<IWatchDogMessage>(_watchDog); _taskProducer = new TaskProducerWorker(_logger, _cacheAside, VolumeHandler, resolver, batchLoggerFactory); _leaderManager = DistributedMutexFactory.CreateDistributedMutex(NodeSettings.Instance.LockKey, RunLocalWatchDog, () => SwitchToPubSubWatchDog(null), batchLoggerFactory.GetSystemLogger()); }
static IDistributedMutex WithDistributedMutex([NotNull] IDistributedMutexClient distributedMutexClient, [NotNull] ILog logger, [NotNull] string name, CancellationToken cancellationToken, bool releaseOnDispose = true) { var mutex = new DistributedMutex(distributedMutexClient, logger, name, cancellationToken, releaseOnDispose); DistributedMutexes.Add(mutex); return(mutex); }
static async Task <int> CommandLock([NotNull] LockOptions lockOptions, [NotNull] IDistributedMutexClient distributedMutexClient, [NotNull] ISnapFilesystem filesystem, [NotNull] ISnapAppReader appReader, [NotNull] ILog logger, [NotNull] string workingDirectory, CancellationToken cancellationToken) { if (lockOptions == null) { throw new ArgumentNullException(nameof(lockOptions)); } if (distributedMutexClient == null) { throw new ArgumentNullException(nameof(distributedMutexClient)); } if (logger == null) { throw new ArgumentNullException(nameof(logger)); } if (workingDirectory == null) { throw new ArgumentNullException(nameof(workingDirectory)); } var snapApps = BuildSnapAppsFromDirectory(filesystem, appReader, workingDirectory); var snapApp = snapApps.Apps.FirstOrDefault(x => string.Equals(x.Id, lockOptions.Id, StringComparison.OrdinalIgnoreCase)); if (snapApp == null) { logger.Error($"Unable to find application with id: {lockOptions.Id}."); return(1); } MaybeOverrideLockToken(snapApps, logger, lockOptions.Id, lockOptions.Token, "--token"); if (string.IsNullOrWhiteSpace(snapApps.Generic.Token)) { logger.Error("Please specify a token in your snapx.yml file. A random UUID is sufficient."); return(1); } await using var distributedMutex = WithDistributedMutex(distributedMutexClient, logger, snapApps.BuildLockKey(snapApp), cancellationToken, false); bool success; if (!lockOptions.Release) { success = await distributedMutex.TryAquireAsync(); return(success ? 0 : 1); } success = await DistributedMutex.TryForceReleaseAsync(distributedMutex.Name, distributedMutexClient, logger); return(success ? 0 : 1); }
public async Task TestTryForceReleaseAsync_Static() { var mutexName = Guid.NewGuid().ToString(); var distributedMutexClientMock = new Mock <IDistributedMutexClient>(); distributedMutexClientMock.Setup(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>())).ThrowsAsync(new WebServiceException()); Assert.False(await DistributedMutex.TryForceReleaseAsync(mutexName, distributedMutexClientMock.Object, new LogProvider.NoOpLogger())); distributedMutexClientMock.Verify(x => x .ReleaseLockAsync( It.Is <string>(v => string.Equals(mutexName, v, StringComparison.Ordinal)), It.Is <string>(v => v == null), It.Is <TimeSpan>(v => v == TimeSpan.Zero)), Times.Once); }
public async Task TestTryForceReleaseAsync_Disposed() { var mutexName = Guid.NewGuid().ToString(); var distributedMutexClientMock = new Mock <IDistributedMutexClient>(); distributedMutexClientMock.Setup(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>())).ThrowsAsync(new WebServiceException()); await using var distributedMutex = new DistributedMutex(distributedMutexClientMock.Object, new LogProvider.NoOpLogger(), mutexName, CancellationToken.None); await distributedMutex.DisposeAsync(); Assert.False(await distributedMutex.TryReleaseAsync()); distributedMutexClientMock.Verify(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>()), Times.Never); }
public async Task TestAcquireAsync_Retry() { var mutexName = Guid.NewGuid().ToString(); const string expectedMutexChallenge = "123"; const int retries = 3; var remainingRetries = retries; var distributedMutexClientMock = new Mock <IDistributedMutexClient>(); distributedMutexClientMock.Setup(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>())).ReturnsAsync(() => { if (--remainingRetries > 0) { throw new WebServiceException(); } return(expectedMutexChallenge); }); distributedMutexClientMock.Setup(x => x .ReleaseLockAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <TimeSpan?>())).Returns(Task.CompletedTask); await using var distributedMutex = new DistributedMutex(distributedMutexClientMock.Object, new LogProvider.NoOpLogger(), mutexName, CancellationToken.None); Assert.True(await distributedMutex.TryAquireAsync(TimeSpan.Zero, retries)); Assert.True(distributedMutex.Acquired); distributedMutexClientMock.Verify(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>()), Times.Exactly(retries)); await distributedMutex.DisposeAsync(); Assert.True(distributedMutex.Disposed); Assert.False(distributedMutex.Acquired); distributedMutexClientMock.Verify(x => x .ReleaseLockAsync( It.Is <string>(v => string.Equals(mutexName, v, StringComparison.Ordinal)), It.Is <string>(v => string.Equals(v, expectedMutexChallenge, StringComparison.Ordinal)), It.IsAny <TimeSpan?>()), Times.Once); }
public async Task TestAcquireAsync_ReturnsInvalidChallengeValue() { var mutexName = Guid.NewGuid().ToString(); var expectedChallenge = string.Empty; var distributedMutexClientMock = new Mock <IDistributedMutexClient>(); distributedMutexClientMock.Setup(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>())).ReturnsAsync(() => expectedChallenge); await using var distributedMutex = new DistributedMutex(distributedMutexClientMock.Object, new LogProvider.NoOpLogger(), mutexName, CancellationToken.None); var ex = await Assert.ThrowsAsync <DistributedMutexUnknownException>(async() => await distributedMutex.TryAquireAsync()); Assert.Equal($"Challenge should not be null or empty. Mutex: {mutexName}. Challenge: {expectedChallenge}", ex.Message); Assert.False(distributedMutex.Acquired); distributedMutexClientMock.Verify(x => x .AcquireAsync(It.IsAny <string>(), It.IsAny <TimeSpan>()), Times.Once); }