예제 #1
0
        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);
        }
예제 #2
0
        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);
        }