/// <summary> /// Creates the aggregate root. /// </summary> /// <param name="id">The id.</param> /// <param name="entityEventSource">The entity event source.</param> /// <param name="domainEventErroneoAction">The domainEventErroneoAction.</param> /// <returns></returns> private AggregateRoot <TEntity, TId> CreateAggregateRoot(TId id, EntityEventSource <TEntity, TId> entityEventSource, Action <AggregateRoot <TEntity, TId>, IDomainEvent <TEntity> > domainEventErroneoAction = null) { Logger.Debug(string.Format("Creando la entidad {1} {0}", id, typeof(TEntity).Name)); var root = entityEventSource.SnapShot ?? new TEntity { Id = id, Version = 0 }; var fsmDecorator = FiniteStateMachineFactory.Create <TEntity, TId>(_fsmConfigurator, root, entityEventSource.State); var aggregate = new AggregateRoot <TEntity, TId>(_repository, fsmDecorator, _applierEvents) { Logger = Logger }; aggregate.DomainEventErroneo += (sender, args) => { if (domainEventErroneoAction != null) { domainEventErroneoAction.Invoke((AggregateRoot <TEntity, TId>)sender, args.Event); } }; Logger.Debug(string.Format("Reconstruyendo la entidad {0}", id)); aggregate.ApplyEvents(entityEventSource.Events); Logger.Debug(string.Format("Estado de la entidad {0}: {1}", id, aggregate.State)); return(aggregate); }
/// <summary> /// Finds the and modify. /// </summary> /// <param name="id"> </param> /// <param name="event">The @event.</param> /// <returns></returns> public EntityEventSource <TEntity, TId> AddEvent(TId id, IDomainEvent <TEntity> @event) { _repository.Create(new EntityEventSource <TEntity, TId> { Id = id, Status = "Ready" }); EntityEventSource <TEntity, TId> entity = null; SpinWait.SpinUntil(() => { var query = Query.And(Query.EQ("_id", BsonDocumentWrapper.Create(id)), Query.Or(Query.EQ("Status", "Ready"), Query.LTE("ProcessingAt", new BsonDateTime( DateTime.UtcNow.Subtract(TimeSpan.FromSeconds(_timeOut)))), Query.EQ("ProcessingBy", Thread.CurrentThread.ManagedThreadId.ToString( CultureInfo.InvariantCulture)))); entity = _repository.FindAndModify ( query, x => ((UpdateBuilder)x.GetUpdateBuilder()) .Push("Events", BsonDocumentWrapper.Create(@event)) .Set("Status", new BsonString("Processing")) .Set("ProcessingAt", new BsonDateTime(DateTime.UtcNow)) .Set("ProcessingBy", new BsonString(Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture))), false, true ); return(entity != null); }); return(entity); }
/// <summary> /// Gets the and apply event. /// </summary> /// <param name="id">The id.</param> /// <param name="events">The @event.</param> /// <param name="domainEventErroneoAction">The domain event erroneo action.</param> /// <returns></returns> public AggregateRoot <TEntity, TId> GetAndApplyEvents(TId id, IEnumerable <IDomainEvent <TEntity> > events, Action <AggregateRoot <TEntity, TId>, IDomainEvent <TEntity> > domainEventErroneoAction) { EntityEventSource <TEntity, TId> entityEventSource = null; foreach (var domainEvent in events) { entityEventSource = _repository.AddEvent(id, domainEvent); } return(CreateAggregateRoot(id, entityEventSource, domainEventErroneoAction)); }
/// <summary> /// Finds the and modify. /// </summary> /// <param name="id">The id.</param> /// <param name="events">The events.</param> /// <returns></returns> public EntityEventSource <TEntity, long> AddEvent(long id, IEnumerable <IDomainEvent <TEntity> > events) { if (NHibernateHelper.CurrentSession.Get <EntityEventSourceWrapper>(id) == null) { NHibernateHelper.CurrentSession.Save(new EntityEventSourceWrapper { Id = id, Status = "Ready" }); NHibernateHelper.CurrentSession.Flush(); } EntityEventSource <TEntity, long> entity = null; SpinWait.SpinUntil(() => { var criterion = Restrictions.Or(Restrictions.Or(Restrictions.Eq("Status", "Ready"), Restrictions.Le("ProcessingAt", DateTime.UtcNow.Subtract(TimeSpan.FromSeconds(_timeOut)))), Restrictions.Eq("ProcessingBy", Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture))); var query = Restrictions.And(Restrictions.Eq("Id", id), criterion); var entitySourceWrapper = (EntityEventSourceWrapper)NHibernateHelper.CurrentSession .CreateCriteria <EntityEventSourceWrapper>() .Add(query).UniqueResult(); if (entitySourceWrapper != null) { entitySourceWrapper.Status = "Processing"; entitySourceWrapper.ProcessingAt = DateTime.UtcNow; entitySourceWrapper.ProcessingBy = Thread.CurrentThread.ManagedThreadId.ToString(CultureInfo.InvariantCulture); foreach (var domainEvent in events) { BsonClassMap.IsClassMapRegistered(domainEvent.GetType()); var eventWrapper = new EventWrapper { Type = domainEvent.GetType().Name, Data = domainEvent.ToBson(), Version = domainEvent.Version }; entitySourceWrapper.AddEvent(eventWrapper); } NHibernateHelper.CurrentSession.Update(entitySourceWrapper); NHibernateHelper.CurrentSession.Flush(); entity = new EntityEventSource <TEntity, long>(); Translator.Instance.TranslateToDomain(entity, entitySourceWrapper); } return(entity != null); }); return(entity); }
public void TranslateToDomain <TEntity>(EntityEventSource <TEntity, long> domain, EntityEventSourceWrapper entity) where TEntity : IVersionableEntity <long>, new() { domain.Id = entity.Id; domain.State = entity.State; domain.Status = entity.Status; domain.ProcessingAt = entity.ProcessingAt; domain.ProcessingBy = entity.ProcessingBy; if (entity.SnapShot != null) { domain.SnapShot = (TEntity)BsonSerializer.Deserialize(entity.SnapShot, typeof(TEntity)); } foreach (var eventWrapper in entity.Events) { var registeredClassMaps = BsonClassMap.GetRegisteredClassMaps(); var bsonClassMap = registeredClassMaps.First(map => map.Discriminator == eventWrapper.Type); var @event = BsonSerializer.Deserialize(eventWrapper.Data, bsonClassMap.ClassType); domain.Events.Add((IDomainEvent <TEntity>)@event); } }