public async Task InsertAsync(SagaData entity)
        {
            var sagaID = entity.PartitionKey + entity.RowKey;
            var lockID = string.Empty;

            if (this.lockSagas)
            {
                lockID = await sagaLock.CreateLock(sagaID).ConfigureAwait(false);
            }

            entity.CreationTimeStamp = DateTime.UtcNow;

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            CloudTable table = tableClient.GetTableReference(TABLE_NAME);


            // Create the TableOperation object that inserts the customer entity.
            TableOperation insertOperation = TableOperation.Insert(entity as ITableEntity);

            // Execute the insert operation.
            await table.ExecuteAsync(insertOperation).ConfigureAwait(false);

            if (this.lockSagas)
            {
                await sagaLock.ReleaseLock(sagaID, lockID).ConfigureAwait(false);
            }
        }
        public async Task UpdateAsync(SagaData entity)
        {
            if (entity.IsDeleted)
            {
                return;
            }

            CloudStorageAccount storageAccount = CloudStorageAccount.Parse(SettingsUtil.GetSettings <string>(SETTINGS.AZURE_STORAGE));

            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            CloudTable table = tableClient.GetTableReference(TABLE_NAME);


            // Create the TableOperation object that inserts the customer entity.
            TableOperation replaceOperation = TableOperation.Replace(entity as ITableEntity);

            // Execute the insert operation.
            await table.ExecuteAsync(replaceOperation).ConfigureAwait(false);

            var sagaID = entity.PartitionKey + entity.RowKey;

            if (this.lockSagas && !entity.IsDeleted)
            {
                await sagaLock.ReleaseLock(sagaID, entity.LockID).ConfigureAwait(false);
            }
        }
        public async Task DeleteAsync(SagaData entity)
        {
            entity.IsDeleted          = true;
            entity.FinishingTimeStamp = DateTime.UtcNow;

            var sagaID = entity.PartitionKey + entity.RowKey;

            if (this.lockSagas)
            {
                await sagaLock.DeleteLock(sagaID, entity.LockID).ConfigureAwait(false);
            }


            // Create the table client.
            CloudTableClient tableClient = storageAccount.CreateCloudTableClient();

            CloudTable table = tableClient.GetTableReference(TABLE_NAME);

            // Create the TableOperation object that inserts the customer entity.
            TableOperation replaceOperation = TableOperation.Delete(entity);

            // Execute the insert operation.
            await table.ExecuteAsync(replaceOperation);

            /*
             * entity.IsDeleted = true;
             * entity.FinishingTimeStamp = DateTime.UtcNow;
             *
             * var sagaID = entity.PartitionKey + entity.RowKey;
             *
             * if (this.lockSagas)
             * {
             *  await sagaLock.DeleteLock(sagaID, entity.LockID);
             * }*/
        }
Пример #4
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);
        }
Пример #5
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);
        }