Example #1
0
        private async Task UpdateSagaAsync <TMessage>(TMessage message, ISaga saga, ISagaState state)
            where TMessage : class
        {
            var sagaType = saga.GetType();

            var updatedSagaData = sagaType.GetProperty(nameof(ISaga <object> .Data))?.GetValue(saga);

            state.Update(saga.State, updatedSagaData);
            var logData = SagaLogData.Create(saga.Id, sagaType, message);

            if (_configuration.AllowConcurrentWrites)
            {
                var persistenceTasks = new[]
                {
                    _repository.WriteAsync(state),
                    _log.WriteAsync(logData)
                };

                await Task.WhenAll(persistenceTasks).ConfigureAwait(false);
            }
            else
            {
                await _repository.WriteAsync(state);

                await _log.WriteAsync(logData);
            }
        }
Example #2
0
 void LogIfSagaIsFinished(ISaga saga)
 {
     if (saga.Completed)
     {
         logger.Debug(string.Format("{0} {1} has completed.", saga.GetType().FullName, saga.Entity.Id));
     }
 }
Example #3
0
 public static Type GetSagaDataType(this ISaga saga)
 => saga
 .GetType()
 .GetInterfaces()
 .FirstOrDefault(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(ISaga <>))
 ?.GetGenericArguments()
 .FirstOrDefault();
 static void OnSagaSaved(EventHandlerBase sender, ISaga saga, IEvent by)
 {
     if (by != null && saga != null)
     {
         Console.WriteLine("[SAGA] {0} -> {1} -> {2}",
                           by.GetType().FullName,
                           saga.GetType().FullName,
                           string.Join(", ", saga.GetUndispatchedMessages().OfType <object>().Select(e => e.GetType().FullName)));
     }
 }
Example #5
0
        public ActiveSagaInstance(ISaga saga, LoadedMessageHandlers.LoadedHandler messageHandler, LogicalMessage message)
        {
            Instance = saga;
            SagaType = saga.GetType();
            MessageToProcess = message;
            Handler = messageHandler;

            //default the invocation to disabled until we have a entity attached
            Handler.InvocationDisabled = true;
        }
Example #6
0
        public ActiveSagaInstance(ISaga saga, LoadedMessageHandlers.LoadedHandler messageHandler, LogicalMessage message)
        {
            Instance         = saga;
            SagaType         = saga.GetType();
            MessageToProcess = message;
            Handler          = messageHandler;

            //default the invocation to disabled until we have a entity attached
            Handler.InvocationDisabled = true;
        }
Example #7
0
        public void Populate(SagaHolder sagaHolder, ISaga saga)
        {
            sagaHolder.Id                = saga.Id;
            sagaHolder.Name              = saga.GetType().Name;
            sagaHolder.Type              = saga.GetType().AssemblyQualifiedName;
            sagaHolder.Key               = saga.Key;
            sagaHolder.Partition         = saga.Partition;
            sagaHolder.State             = saga.CurrentState.ToString();
            sagaHolder.SerializedSaga    = _serializer.ToJson(saga, SerializationOptions);
            sagaHolder.UncommittedEvents = _serializer.ToJson(saga.GetUncommittedEvents());

            var chapterHolders = (from c in saga.Chapters
                                  select GetChapterHolderFromChapter(c)).ToArray();

            sagaHolder.SerializedChapters = _serializer.ToJson(chapterHolders);

            if (saga.CurrentChapter != null)
            {
                sagaHolder.CurrentChapterType = saga.CurrentChapter.GetType().AssemblyQualifiedName;
            }
        }
        private string generateInsertScriptForObject(ISaga @state)
        {
            Type          type   = @state.GetType();
            StringBuilder script = new StringBuilder();

            script.Append($"insert into {_sqlServerOptions.TableName} ({idColumn},{stateNameColumn},{jsonColumn},{createdColumn},{modifiedColumn},{stateColumn},{stepColumn},{compensatingColumn}");

            script.Append($") select @{idColumn},@{stateNameColumn},@{jsonColumn},@{createdColumn},@{modifiedColumn},@{stateColumn},@{stepColumn},@{compensatingColumn}");

            script.Append($"; ");

            return(script.ToString());
        }
        private static Dictionary <string, object> PrepareHeaders(ISaga saga, Action <IDictionary <string, object> > updateHeaders)
        {
            var headers = new Dictionary <string, object>();

            headers[SagaTypeHeader] = saga.GetType().FullName;
            if (updateHeaders != null)
            {
                updateHeaders(headers);
            }

            var i = 0;

            foreach (var command in saga.GetUndispatchedMessages())
            {
                headers[UndispatchedMessageHeader + i++] = command;
            }

            return(headers);
        }
Example #10
0
        public async Task ProcessAsync <TMessage>(ISaga saga, TMessage message, ISagaContext context,
                                                  Func <TMessage, ISagaContext, Task> onCompleted, Func <TMessage, ISagaContext, Task> onRejected)
        {
            var sagaType = saga.GetType();

            switch (saga.State)
            {
            case SagaStates.Rejected:
                await onRejected(message, context);
                await CompensateAsync(saga, sagaType, context);

                break;

            case SagaStates.Completed:
                await onCompleted(message, context);

                break;
            }
        }
Example #11
0
        private string generateUpdateScriptForObject(ISaga @state)
        {
            Type          type   = @state.GetType();
            StringBuilder script = new StringBuilder();

            script.Append($" update {_sqlServerOptions.TableName} set ");

            script.Append($" {stateNameColumn} = @{stateNameColumn}, ");
            script.Append($" {jsonColumn} = @{jsonColumn}, ");
            script.Append($" {createdColumn} = @{createdColumn}, ");
            script.Append($" {modifiedColumn} = @{modifiedColumn}, ");
            script.Append($" {stateColumn} = @{stateColumn}, ");
            script.Append($" {stepColumn} = @{stepColumn}, ");
            script.Append($" {compensatingColumn} = @{compensatingColumn} ");

            script.Append($" where {idColumn} = @{idColumn}; ");

            return(script.ToString());
        }
        IContainSagaData TryLoadSagaEntity(ISaga saga, LogicalMessage message)
        {
            var sagaType = saga.GetType();

            var sagaEntityType = Features.Sagas.GetSagaEntityTypeForSagaType(sagaType);

            var finders = GetFindersFor(message.MessageType, sagaEntityType);

            foreach (var finder in finders)
            {
                var sagaEntity = UseFinderToFindSaga(finder, message.Instance);

                if (sagaEntity != null)
                {
                    return(sagaEntity);
                }
            }

            return(null);
        }
Example #13
0
        public void Add(ISaga saga)
        {
            if (sagas.TryGetValue(saga.Id, out ISaga existing))
            {
                if (saga != existing)
                {
                    throw new ArgumentException($"Saga {saga} with specified ID already exists");
                }

                return;
            }

            repository.Add(saga);

            Guid sagaClassId = entityTypeManager.GetClassInfoByClrType(saga.GetType()).Id;

            MetadataRepository.AddSaga(saga.Id, sagaClassId);

            sagas[saga.Id] = saga;
        }
        IContainSagaData TryLoadSagaEntity(ISaga saga, LogicalMessage message)
        {
            var sagaType = saga.GetType();

            var sagaEntityType = Features.Sagas.GetSagaEntityTypeForSagaType(sagaType);

            var finders = GetFindersFor(message.MessageType, sagaEntityType);

            foreach (var finder in finders)
            {
                var sagaEntity = UseFinderToFindSaga(finder, message.Instance);

                if (sagaEntity != null)
                    return sagaEntity;
            }

            return null;
        }
Example #15
0
 public ActiveSagaInstance(ISaga saga)
 {
     Instance = saga;
     SagaType = saga.GetType();
 }
 public ActiveSagaInstance(ISaga saga)
 {
     Instance = saga;
     SagaType = saga.GetType();
 }
 void LogIfSagaIsFinished(ISaga saga)
 {
     if (saga.Completed)
         logger.Debug(string.Format("{0} {1} has completed.", saga.GetType().FullName, saga.Entity.Id));
 }
Example #18
0
		public void Populate(SagaHolder sagaHolder, ISaga saga)
		{
			sagaHolder.Id = saga.Id;
			sagaHolder.Name = saga.GetType().Name;
			sagaHolder.Type = saga.GetType().AssemblyQualifiedName;
			sagaHolder.Key = saga.Key;
			sagaHolder.Partition = saga.Partition;
		    sagaHolder.State = saga.CurrentState.ToString();
			sagaHolder.SerializedSaga = _serializer.ToJson(saga, SerializationOptions);
			sagaHolder.UncommittedEvents = _serializer.ToJson(_eventConverter.ToEventHolders(saga.GetUncommittedEvents()));

			var chapterHolders = (from c in saga.Chapters
			                      select GetChapterHolderFromChapter(c)).ToArray();

			sagaHolder.SerializedChapters = _serializer.ToJson(chapterHolders);

			if (saga.CurrentChapter != null)
				sagaHolder.CurrentChapterType = saga.CurrentChapter.GetType().AssemblyQualifiedName;
		}
Example #19
0
 public static object InvokeGeneric(this ISaga saga, string method, params object[] args)
 => saga
 .GetType()
 .GetMethod(method, args.Select(arg => arg.GetType()).ToArray())
 ?.Invoke(saga, args);