private async Task <bool> LookForEventsProcessedBySagas <T>(T message, AFBusMessageContext messageContext, ILogger log) where T : class { var instantiated = false; foreach (var sagaInfo in messageToSagaDictionary[message.GetType()]) { var saga = CreateInstance(sagaInfo.SagaType); dynamic sagaDynamic = saga; var sagaMessageToMethod = sagaInfo?.EventsThatCorrelatesSagas?.FirstOrDefault(m => m.Message == message.GetType()); //try to load saga from repository if (sagaMessageToMethod != null) { var locker = new SagaAzureStorageLocker(); object[] lookForInstanceParametersArray = new object[] { message }; sagaDynamic.SagaPersistence = new SagaAzureStoragePersistence(locker, this.lockSaga); var sagasData = await((Task <List <SagaData> >)sagaMessageToMethod.CorrelatingMethod.Invoke(saga, lookForInstanceParametersArray)).ConfigureAwait(false); if (sagasData != null) { //process each saga data independently foreach (var sagaData in sagasData) { try { dynamic finalSagaData = sagaData; SagaData lockedSagaData = await sagaDynamic.SagaPersistence.GetSagaDataAsync <SagaData>(sagaData.PartitionKey, sagaData.RowKey).ConfigureAwait(false); finalSagaData.Timestamp = lockedSagaData.Timestamp; finalSagaData.ETag = lockedSagaData.ETag; finalSagaData.LockID = lockedSagaData.LockID; sagaDynamic.Data = finalSagaData; var bus = new Bus(serializer, SolveDependency <ISendMessages>(), SolveDependency <IPublishEvents>()) { Context = messageContext }; object[] parametersArray = new object[] { bus, message, log }; SagaData typedSagaData = (SagaData)sagaData; log?.LogInformation("Invoke event saga handler " + sagaMessageToMethod.HandlingMethod.ToString() + " for transaction " + messageContext.TransactionID); await((Task)sagaMessageToMethod.HandlingMethod.Invoke(saga, parametersArray)).ConfigureAwait(false); await sagaPersistence.UpdateAsync(sagaDynamic.Data).ConfigureAwait(false); instantiated = true; } catch (Exception ex) { //if there is an error release the lock. log?.LogError(ex.Message, ex); var sagaID = sagaData.PartitionKey + sagaData.RowKey; await locker.ReleaseLock(sagaID, sagaData.LockID); throw; } } } } } return(instantiated); }
private async Task <bool> LookForCommandsProcessedByASaga <T>(T message, AFBusMessageContext messageContext, ILogger log) where T : class { var instantiated = false; foreach (var sagaInfo in messageToSagaDictionary[message.GetType()]) { var saga = CreateInstance(sagaInfo.SagaType);//Activator.CreateInstance(sagaInfo.SagaType); dynamic sagaDynamic = saga; var sagaMessageToMethod = sagaInfo.CommandsThatAreCorrelatedByTheSaga.FirstOrDefault(m => m.Message == message.GetType()); //try to load saga from repository if (sagaMessageToMethod != null) { var locker = new SagaAzureStorageLocker(); object[] lookForInstanceParametersArray = new object[] { message }; sagaDynamic.SagaPersistence = new SagaAzureStoragePersistence(locker, this.lockSaga); dynamic sagaData = await((Task <SagaData>)sagaMessageToMethod.CorrelatingMethod.Invoke(saga, lookForInstanceParametersArray)).ConfigureAwait(false); if (sagaData != null) { try { sagaDynamic.Data = sagaData; var bus = new Bus(serializer, SolveDependency <ISendMessages>(), SolveDependency <IPublishEvents>()) { Context = messageContext }; object[] parametersArray = new object[] { bus, message, log }; SagaData typedSagaData = (SagaData)sagaData; log?.LogInformation("Invoke saga handler " + sagaMessageToMethod.HandlingMethod.ToString() + " for transaction " + messageContext.TransactionID + " with key (" + typedSagaData.PartitionKey.ToString() + "," + typedSagaData.RowKey + ")"); await((Task)sagaMessageToMethod.HandlingMethod.Invoke(saga, parametersArray)).ConfigureAwait(false); await sagaPersistence.UpdateAsync(sagaDynamic.Data).ConfigureAwait(false); instantiated = true; } catch (Exception ex) { //if there is an error release the lock. log?.LogError(ex.Message, ex); var sagaID = sagaData.PartitionKey + sagaData.RowKey; await locker.ReleaseLock(sagaID, sagaData.LockID); throw; } } } sagaMessageToMethod = sagaInfo.CommandsThatActivateTheSaga.FirstOrDefault(m => m.Message == message.GetType()); //if not => create the saga if (!instantiated && sagaMessageToMethod != null) { var bus = new Bus(serializer, SolveDependency <ISendMessages>(), SolveDependency <IPublishEvents>()) { Context = messageContext }; object[] parametersArray = new object[] { bus, message, log }; log?.LogInformation("Invoke saga handler " + sagaMessageToMethod.HandlingMethod.ToString() + " for transaction " + messageContext.TransactionID + " creating new saga"); await((Task)sagaMessageToMethod.HandlingMethod.Invoke(saga, parametersArray)).ConfigureAwait(false); await sagaPersistence.InsertAsync(sagaDynamic.Data).ConfigureAwait(false); SagaData typedSagaData = (SagaData)sagaDynamic.Data; log?.LogInformation("Saga data inserted " + sagaMessageToMethod.HandlingMethod.ToString() + " for transaction " + messageContext.TransactionID + " with key (" + typedSagaData.PartitionKey.ToString() + "," + typedSagaData.RowKey.ToString() + ")"); instantiated = true; } } return(instantiated); }