Beispiel #1
0
        public void Register(Type atomicAggregateType)
        {
            var attribute = AtomicReadmodelInfoAttribute.GetFrom(atomicAggregateType);

            if (attribute == null)
            {
                throw new JarvisFrameworkEngineException($"Type {atomicAggregateType} cannot be used as atomic readmodel, it misses the AtomicReadmodelInfo attribute");
            }

            if (_registeredTypeNames.ContainsKey(attribute.Name))
            {
                if (_registeredTypeNames[attribute.Name] == atomicAggregateType)
                {
                    return; //already added.
                }
                throw new JarvisFrameworkEngineException($"Type {atomicAggregateType} cannot be used as atomic readmodel, it uses name {attribute.Name} already in use by type {_registeredTypeNames[attribute.Name]}");
            }

            //Simply store all information in memory, we simply need to initialize latest checkpoint if not reloaded
            if (!_inMemoryCheckpoint.ContainsKey(attribute.Name))
            {
                AtomicProjectionCheckpoint atomicProjectionCheckpoint = new AtomicProjectionCheckpoint()
                {
                    Id       = attribute.Name,
                    Position = 0
                };
                _inMemoryCheckpoint.AddOrUpdate(attribute.Name, atomicProjectionCheckpoint, (k, e) => atomicProjectionCheckpoint);
            }
            _registeredTypeNames.Add(attribute.Name, atomicAggregateType);
        }
Beispiel #2
0
 public AtomicReadmodelProjectorHelper(
     IAtomicCollectionWrapper <TModel> atomicCollectionWrapper,
     IAtomicReadModelFactory atomicReadModelFactory,
     ILiveAtomicReadModelProcessor liveAtomicReadModelProcessor,
     ILogger logger)
 {
     _atomicCollectionWrapper      = atomicCollectionWrapper;
     _atomicReadmodelInfoAttribute = AtomicReadmodelInfoAttribute.GetFrom(typeof(TModel));
     _logger = logger;
     _atomicReadModelFactory       = atomicReadModelFactory;
     _liveAtomicReadModelProcessor = liveAtomicReadModelProcessor;
 }
Beispiel #3
0
        /// <summary>
        /// Register an atomic readmodel and return false if the readmodel is too old to
        /// be projected, it should be projected by another catchup projection engine.
        /// </summary>
        /// <param name="atomicReadmodelType"></param>
        /// <returns></returns>
        public AtomicProjectionEngine RegisterAtomicReadModel(Type atomicReadmodelType)
        {
            var attribute          = AtomicReadmodelInfoAttribute.GetFrom(atomicReadmodelType);
            var projectionPosition = _atomicProjectionCheckpointManager.GetCheckpoint(attribute.Name);

            Logger.InfoFormat("Registered atomic readmodel {0} starting from position  {1}", attribute.Name, projectionPosition);

            if (_lastPositionDispatched - projectionPosition > MaximumDifferenceForCatchupPoller)
            {
                Logger.InfoFormat("Readmodel {0} was registered in Atomic Projection Engine with catchup poller because it is too old. Last dispatched is {1} but we already dispatched {2}",
                                  attribute.Name,
                                  projectionPosition,
                                  _lastPositionDispatched);

                AddConsumer(projectionPosition, CatchupPollerId, atomicReadmodelType, attribute);
                return(this);
            }

            //default poller
            Logger.InfoFormat("Readmodel {0} registered in default poller in Atomic Projection Engine", attribute.Name);
            AddConsumer(projectionPosition, DefaultPollerId, atomicReadmodelType, attribute);
            return(this);
        }
Beispiel #4
0
        private void AddConsumer(Int64 projectedPosition, Int32 pollerId, Type atomicReadmodelType, AtomicReadmodelInfoAttribute atomicReadmodelInfoAttribute)
        {
            //The real starting point is the minimum between actual position and what is already in the dictionary, each poller id should start from
            //minimum dispatched to avoid missing data. If the poller still was not added, its default value is MaxValue because it is passed to the min
            //value, so projectedPosition will always win.
            _pollerStartingPoint[pollerId] = Math.Min(TryGetStartingPoint(pollerId, Int32.MaxValue), projectedPosition);

            if (!_consumerBlocks.TryGetValue(atomicReadmodelInfoAttribute.AggregateIdType, out List <AtomicDispatchChunkConsumer> atomicReadmodelEventConsumers))
            {
                atomicReadmodelEventConsumers = new List <AtomicDispatchChunkConsumer>();
                _consumerBlocks.Add(atomicReadmodelInfoAttribute.AggregateIdType, atomicReadmodelEventConsumers);
            }
            //add the consumer
            if (!atomicReadmodelEventConsumers.Any(_ => _.Consumer.AtomicReadmodelInfoAttribute.Name == atomicReadmodelInfoAttribute.Name))
            {
                var consumer       = _atomicReadmodelProjectorHelperFactory.CreateFor(atomicReadmodelType);
                var atomicConsumer = new AtomicDispatchChunkConsumer(consumer, pollerId);
                atomicReadmodelEventConsumers.Add(atomicConsumer);
            }

            _atomicProjectionCheckpointManager.Register(atomicReadmodelType);
        }