public async Task Handle(StartLiquidationInternalCommand command, IEventPublisher publisher) { #region Private Methods void PublishFailedEvent(string reason) { publisher.PublishEvent(new LiquidationFailedEvent { OperationId = command.OperationId, CreationTime = _dateService.Now(), Reason = reason, LiquidationType = command.LiquidationType.ToType <LiquidationTypeContract>(), AccountId = command.AccountId, AssetPairId = command.AssetPairId, Direction = command.Direction?.ToType <PositionDirectionContract>(), }); _liquidationEndEventChannel.SendEvent(this, new LiquidationEndEventArgs { OperationId = command.OperationId, CreationTime = _dateService.Now(), AccountId = command.AccountId, LiquidatedPositionIds = new List <string>(), FailReason = reason, }); } #endregion #region Validations if (string.IsNullOrEmpty(command.AccountId)) { PublishFailedEvent("AccountId must be specified"); return; } if (_accountsCache.TryGet(command.AccountId) == null) { PublishFailedEvent("Account does not exist"); return; } #endregion var(executionInfo, _) = await _operationExecutionInfoRepository.GetOrAddAsync( operationName : LiquidationSaga.OperationName, operationId : command.OperationId, factory : () => new OperationExecutionInfo <LiquidationOperationData>( operationName: LiquidationSaga.OperationName, id: command.OperationId, lastModified: _dateService.Now(), data: new LiquidationOperationData { State = LiquidationOperationState.Initiated, AccountId = command.AccountId, AssetPairId = command.AssetPairId, QuoteInfo = command.QuoteInfo, Direction = command.Direction, LiquidatedPositionIds = new List <string>(), ProcessedPositionIds = new List <string>(), LiquidationType = command.LiquidationType, OriginatorType = command.OriginatorType, AdditionalInfo = command.AdditionalInfo, StartedAt = command.CreationTime } )); if (executionInfo.Data.State == LiquidationOperationState.Initiated) { if (!_accountsCache.TryStartLiquidation(command.AccountId, command.OperationId, out var currentOperationId)) { if (currentOperationId != command.OperationId) { PublishFailedEvent( $"Liquidation is already in progress. Initiated by operation : {currentOperationId}"); return; } } _chaosKitty.Meow( $"{nameof(StartLiquidationInternalCommand)}:" + $"Publish_LiquidationStartedInternalEvent:" + $"{command.OperationId}"); publisher.PublishEvent(new LiquidationStartedEvent { OperationId = command.OperationId, CreationTime = _dateService.Now(), AssetPairId = executionInfo.Data.AssetPairId, AccountId = executionInfo.Data.AccountId, LiquidationType = executionInfo.Data.LiquidationType.ToType <LiquidationTypeContract>() }); } }