public SagaDispatchResult DispatchToSaga(string correlationId, object message, bool createNew, bool wait, SagaBase sagaHandler, Action<SagaBase> callback)
        {
            string sagaId = null;
            if (!sagaHandler.TryGetSagaIdFromMessage(message, out sagaId))
            {
                sagaId = correlationId;
            }
            else
            {
                if (SagaBase.IGNORE_MESSAGE == sagaId)
                {
                    return SagaDispatchResult.MessageHandled;
                }
            }

            if (!createNew && string.IsNullOrEmpty(sagaId))
            {
                if (IgnoreMessagesWithoutSagaId)
                {
                    return SagaDispatchResult.MessageHandled;
                }
                else throw new Exception("Saga Id could not be determined");
            }

            bool b = ExclusiveLock(sagaId, wait, delegate()
            {
                DispatchToSagaInternal(sagaId, createNew, sagaHandler, callback);
            });
            if (!b)
            {
                log.Info("Concurrent update of saga {0}, will process the message later", sagaId);
            }
            return b ? SagaDispatchResult.MessageHandled : SagaDispatchResult.ConcurrentUpdateHandleLater;
        }
Beispiel #2
0
        protected void DispatchToSagaInternal(string sagaId, bool createNew, SagaBase sagaHandler, Action <SagaBase> callback)
        {
            string version       = null;
            bool   found         = false;
            object sagaState     = null;
            var    st            = Stopwatch.StartNew();
            var    sagaStateType = sagaHandler.GetType().BaseType.GetGenericArguments()[0]; //todo: what if inheritance is deeper???

            if (!string.IsNullOrEmpty(sagaId))
            {
                found = SagaStateRepo.Get(sagaId, sagaStateType, true, out sagaState, out version);
            }
            else //create new id
            {
                sagaId = Guid.NewGuid().ToString("N");
            }

            if (!found)
            {
                if (!createNew)
                {
                    throw new Exception("Saga instance not found: " + sagaId);
                }
                sagaState = Activator.CreateInstance(sagaStateType);

                version = "1";
            }
            sagaHandler.IsNew = !found;
            sagaHandler.InitializeSagaState(sagaId, version, sagaState);
            callback(sagaHandler);
            if (sagaHandler.Completed)
            {
                if (!createNew)
                {
                    SagaStateRepo.Delete(sagaId);
                    log.Info("Deleted saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
            }
            else
            {
                sagaHandler.BeforeSave();
                if (!found)
                {
                    SagaStateRepo.InsertNew(sagaHandler.Id, sagaState);
                    log.Info("Saved new saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
                else
                {
                    SagaStateRepo.Update(sagaHandler.Id, sagaState, version);
                    log.Debug("Updated saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
            }
            st.Stop();
            statLog.Info("Dispatch:{0}", st.ElapsedMilliseconds);
        }
Beispiel #3
0
 public EfSagaRecord(SagaBase saga, List<SagaCorrelationProperty> sagaCorrelationIds) : base(saga.SagaId)
 {
     Guard.ArgumentNotNull(saga, nameof(saga));
     Guard.ArgumentNotNull(sagaCorrelationIds, nameof(sagaCorrelationIds));
     var sagaState = saga.SagaState;
     var sagaStateType = sagaState.State.GetType();
     StateType = sagaStateType.AssemblyQualifiedName;
     SagaState = ContractlessMessagePackSerializer.Instance.BinarySerialize(sagaState.State, sagaStateType);
     SagaVersion = sagaState.SagaVersion;
     foreach (var message in sagaState.Messages)
     {
         this.RaiseEvent(message);
     }
     sagaState.Messages.Clear();
     CorrelationIds = sagaCorrelationIds.Select(id => new EfSagaCorrelationId(Id, saga.GetType().Name, id.PropertyName, id.PropertyValue)).ToList();
 }
Beispiel #4
0
 // here we need to attach Saga
 public void SaveSaga(SagaBase saga, List <SagaCorrelationProperty> correlationIds)
 {
     using (var db = _contextFactory())
     {
         var record = new EfSagaRecord(saga, correlationIds);
         if (record.SagaVersion == 1)
         {
             db.Sagas.Add(record);
         }
         else
         {
             db.Sagas.Update(record);
             db.Entry(record).Property("SagaVersion").OriginalValue = (saga.SagaState.SagaVersion - 1);
         }
         db.SaveChanges();
     }
 }
Beispiel #5
0
        public List <SagaCorrelationProperty> GetCorrelationIdsFromSaga(SagaBase saga)
        {
            if (saga.GetType() != SagaType)
            {
                throw new InvalidOperationException("Wrong Saga Type");
            }
            List <SagaCorrelationProperty> result = new List <SagaCorrelationProperty>();

            foreach (var config in EventMappings.Values.DistinctBy(v => v.SagaPropertyName))
            {
                var value = config.SagaPropertyFunc(saga.SagaState.State);
                if (value == null || object.Equals(GetDefault(value.GetType()), value))
                {
                    continue;
                }
                result.Add(new SagaCorrelationProperty(config.SagaPropertyName, value.ToString()));
            }
            return(result);
        }
Beispiel #6
0
        public SagaDispatchResult DispatchToSaga(string correlationId, object message, bool createNew, bool wait, SagaBase sagaHandler, Action <SagaBase> callback)
        {
            string sagaId = null;

            if (!sagaHandler.TryGetSagaIdFromMessage(message, out sagaId))
            {
                sagaId = correlationId;
            }
            else
            {
                if (SagaBase.IGNORE_MESSAGE == sagaId)
                {
                    return(SagaDispatchResult.MessageHandled);
                }
            }

            if (!createNew && string.IsNullOrEmpty(sagaId))
            {
                if (IgnoreMessagesWithoutSagaId)
                {
                    return(SagaDispatchResult.MessageHandled);
                }
                else
                {
                    throw new Exception("Saga Id could not be determined");
                }
            }

            bool b = ExclusiveLock(sagaId, wait, delegate()
            {
                DispatchToSagaInternal(sagaId, createNew, sagaHandler, callback);
            });

            if (!b)
            {
                log.Info("Concurrent update of saga {0}, will process the message later", sagaId);
            }
            return(b ? SagaDispatchResult.MessageHandled : SagaDispatchResult.ConcurrentUpdateHandleLater);
        }
 public SendNotificationToAdministrator(SagaBase saga) : base(saga)
 {
 }
 public SendGreetingEmail(SagaBase saga) : base(saga)
 {
 }
        protected void DispatchToSagaInternal(string sagaId, bool createNew, SagaBase sagaHandler, Action<SagaBase> callback)
        {
            string version = null;
            bool found = false;
            object sagaState = null;
            var st = Stopwatch.StartNew();
            var sagaStateType = sagaHandler.GetType().BaseType.GetGenericArguments()[0]; //todo: what if inheritance is deeper???

            if (!string.IsNullOrEmpty(sagaId))
            {
                found = SagaStateRepo.Get(sagaId, sagaStateType, true, out sagaState, out version);
            }
            else //create new id
            {
                sagaId = Guid.NewGuid().ToString("N");
            }

            if (!found)
            {
                if (!createNew) throw new Exception("Saga instance not found: " + sagaId);
                sagaState = Activator.CreateInstance(sagaStateType);

                version = "1";
            }
            sagaHandler.IsNew = !found;
            sagaHandler.InitializeSagaState(sagaId, version, sagaState);
            callback(sagaHandler);
            if (sagaHandler.Completed)
            {
                if (!createNew)
                {
                    SagaStateRepo.Delete(sagaId);
                    log.Info("Deleted saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
            }
            else
            {
                sagaHandler.BeforeSave();
                if (!found)
                {
                    SagaStateRepo.InsertNew(sagaHandler.Id, sagaState);
                    log.Info("Saved new saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
                else
                {
                    SagaStateRepo.Update(sagaHandler.Id, sagaState, version);
                    log.Debug("Updated saga {0}/{1}", sagaHandler.GetType().Name, sagaId);
                }
            }
            st.Stop();
            statLog.Info("Dispatch:{0}", st.ElapsedMilliseconds);
        }