Inheritance: IMonitoredSubscription
示例#1
0
        private bool TryFill(SubscriptionBuffer buffer)
        {
            if (!buffer.IsPolling && !buffer.IsPoisoned && buffer.NewEventsQueue.Count < queueMaxCount)
            {
                buffer.IsPolling = true;
                try
                {
                    if (!ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(_ =>
                                poller.PollSubscription(buffer.StreamType, buffer.Url, buffer.Token, buffer.CurrentBufferVersion)), null))
                    {
                        this.bus.Publish(new FatalErrorOcurred(new FatalErrorException("A work item could not be queued in Poller.TryFill()")));
                    }
                }
                catch (Exception ex)
                {
                    this.bus.Publish(new FatalErrorOcurred(new FatalErrorException("A work item could not be queued in Poller.TryFill()", ex)));
                    throw;
                }
                return true;
            }

            return false;
        }
示例#2
0
        public void Handle(AddNewSubscriptionOnTheFly message)
        {
            lock (this.lockObjectForOnTheFlySub)
            {
                if (this.repository.TryAddNewSubscriptionOnTheFly(message.StreamType, message.Url, message.Token))
                {

                    if (this.onTheFlyBufferPool == null)
                        this.onTheFlyBufferPool = new ConcurrentBag<SubscriptionBuffer>();
                    else
                        if (this.onTheFlyBufferPool.Any(x => x.StreamType == message.StreamType))
                        return;

                    var sub = new SubscriptionBuffer(message.StreamType, message.Url, message.Token, 0, false);
                    this.mainPublisherRegistry.Register(new OcassionallyConnectedSource(sub.StreamType, this.microserviceName));
                    this.onTheFlyBufferPool.Add(sub);

                    if (this.onTheFlySubscriptionsDetected)
                        return;

                    this.onTheFlySubscriptionsDetected = true;
                    if (this.onTheFlyThread != null)
                        throw new InvalidOperationException($"Already a thread of on the fly subscription running in poller of {this.microserviceName}.");

                    this.onTheFlyThread = new Thread(() =>
                    {
                        // This algorithm performs very well!
                        bool working;
                        while (!this.stopping)
                        {
                            working = false;
                            foreach (var buffer in this.onTheFlyBufferPool)
                            {
                                if (working)
                                {
                                    this.TryFill(buffer);
                                    this.TryFlush(buffer);
                                }
                                else
                                {
                                    if (this.TryFlush(buffer) | this.TryFill(buffer))
                                    {
                                        working = true;
                                    }
                                }
                            }
                            if (!working)
                                Thread.Sleep(1);
                        }
                    })
                    {
                        IsBackground = true,
                        Name = this.microserviceName + "_POLLER_ON-THE-FLY-SUBSCRIPTION"
                    };
                    this.onTheFlyThread.Start();
                }

                else
                    return;
            }
        }
示例#3
0
        private bool TryFlush(SubscriptionBuffer buffer)
        {

            //var eventsInQueueCount = buffer.NewEventsQueue.Count();
            //if (eventsInQueueCount < 1 || buffer.EventsInProcessorByEcv.Any(e => !e.Value.WasProcessed))
            //The buffer is empty or there are still events in the processor
            //return false;

            if (buffer.NewEventsQueue.IsEmpty)
                return false;

            long processorBufferVersion;
            var eventsToProcess = new List<IEvent>();
            if (buffer.EventsInProcessorByEcv.Any(e => !e.Value.WasProcessed))
            {
                while (!buffer.EventsInProcessorByEcv.IsEmpty)
                {
                    EventInProcessorBucket toBeRemovedIfApplicable;
                    var min = buffer.EventsInProcessorByEcv.Min(x => x.Key);
                    if (buffer.EventsInProcessorByEcv[min].WasProcessed)
                        buffer.EventsInProcessorByEcv.TryRemove(min, out toBeRemovedIfApplicable);
                    else
                        break;
                }

                if (buffer.EventsInProcessorByEcv.IsEmpty)
                    return false;

                processorBufferVersion = buffer.EventsInProcessorByEcv.Min(x => x.Key);

                // there are still some events in the 'bag', try to add a few more
                int freeSlots;
                var eventsInProcessor = buffer.EventsInProcessorByEcv.Where(x => !x.Value.WasProcessed).Count();
                if (eventsToFlushMaxCount > eventsInProcessor)
                    freeSlots = eventsToFlushMaxCount - eventsInProcessor;
                else
                    // there could be events to process, but there are not empty slots...
                    return false;

                for (int i = 0; i < freeSlots; i++)
                {
                    IEvent @event;
                    if (buffer.NewEventsQueue.TryPeek(out @event))
                    {
                        if (!buffer.EventsInProcessorByEcv.Any(x => x.Value.Event.StreamId == @event.StreamId && !x.Value.WasProcessed))
                        {
                            // there is not an event of the same stream that is still in the processor
                            buffer.NewEventsQueue.TryDequeue(out @event);
                            eventsToProcess.Add(@event);
                        }
                    }
                    else
                        break;
                }

                if (eventsToProcess.Count < 1)
                    // no events could be try to process. No op
                    return false;
#if DEBUG
                this.log.Trace($"Optimizing event processing for {eventsToProcess.Count} event/s from {buffer.ProducerName}");
#endif
            }
            else
            {
                // if all events where processed, go here
                for (int i = 0; i < eventsToFlushMaxCount; i++)
                {
                    IEvent @event;
                    if (!buffer.NewEventsQueue.TryDequeue(out @event))
                        break;

                    eventsToProcess.Add(@event);
                }

                // the minimun of the queue
                processorBufferVersion = eventsToProcess.Min(e => e.EventCollectionVersion);
                // Reset the bag;
                buffer.EventsInProcessorByEcv.Clear();
            }

            var streams = eventsToProcess.Select(incomingEvent =>
            {
                var message = (Message)incomingEvent;
                message.ProcessorBufferVersion = processorBufferVersion;
                message.StreamType = buffer.StreamType;

                buffer.EventsInProcessorByEcv.TryAdd(incomingEvent.EventCollectionVersion, new EventInProcessorBucket(incomingEvent));

                return incomingEvent;
                //this.bus.Publish(new NewIncomingEvents(incomingEvent));
            });

            this.bus.Publish(new NewIncomingEvents(streams));

            // Here we persist the current subscription version state
            this.repository.PersistSubscriptionVersion(buffer.StreamType, processorBufferVersion, buffer.ProducerVersion);
            return true;
        }
示例#4
0
 private void RegisterOcassionallyConnectedSourceIfApplicable(SubscriptionBuffer subscription)
 {
     if (subscription.Token == Constants.OcassionallyConnectedSourceToken)
         this.mainPublisherRegistry.Register(new OcassionallyConnectedSource(subscription.StreamType, this.microserviceName));
 }
示例#5
0
        private bool TryFlush(SubscriptionBuffer buffer)
        {
            long processorBufferVersion;
            var eventsInQueueCount = buffer.NewEventsQueue.Count();
            //if (eventsInQueueCount < 1 || buffer.EventsInProcessorByEcv.Any(e => !e.Value.WasProcessed))
            //The buffer is empty or there are still events in the processor
            //return false;

            if (eventsInQueueCount < 1)
                return false;

            var eventsToProcess = new List<IEvent>();
            if (buffer.EventsInProcessorByEcv.Any(e => !e.Value.WasProcessed))
            {
                while (!buffer.EventsInProcessorByEcv.IsEmpty)
                {
                    EventInProcessorBucket toBeRemovedIfApplicable;
                    var min = buffer.EventsInProcessorByEcv.Min(x => x.Key);
                    if (buffer.EventsInProcessorByEcv[min].WasProcessed)
                        buffer.EventsInProcessorByEcv.TryRemove(min, out toBeRemovedIfApplicable);
                    else
                        break;
                }

                if (buffer.EventsInProcessorByEcv.IsEmpty)
                    return false;

                processorBufferVersion = buffer.EventsInProcessorByEcv.Min(x => x.Key);

                // there are still some events in the 'bag', try to add a few more
                int freeSlots;
                var eventsInProcessor = buffer.EventsInProcessorByEcv.Where(x => !x.Value.WasProcessed).Count();
                if (eventsToFlushMaxCount > eventsInProcessor)
                    freeSlots = eventsToFlushMaxCount - eventsInProcessor;
                else
                    // there could be events to process, but there are not empty slots...
                    return false;

                for (int i = 0; i < freeSlots; i++)
                {
                    IEvent @event;
                    if (buffer.NewEventsQueue.TryPeek(out @event))
                    {
                        if (!buffer.EventsInProcessorByEcv.Any(x => x.Value.Event.StreamId == @event.StreamId && !x.Value.WasProcessed))
                        {
                            // there is not an event of the same stream that is still in the processor
                            buffer.NewEventsQueue.TryDequeue(out @event);
                            eventsToProcess.Add(@event);
                        }
                    }
                    else
                        break;
                }

                if (eventsToProcess.Count < 1)
                    // no events could be try to process. No op
                    return false;
#if DEBUG
                this.log.Trace($"Optimizing event processing for {eventsToProcess.Count} event/s from {buffer.ProducerName}");
#endif
            }
            else
            {
                // if all events where processed, go here
                for (int i = 0; i < eventsToFlushMaxCount; i++)
                {
                    IEvent @event;
                    if (!buffer.NewEventsQueue.TryDequeue(out @event))
                        break;

                    eventsToProcess.Add(@event);
                }

                // the minimun of the queue
                processorBufferVersion = eventsToProcess.Min(e => e.EventCollectionVersion);
                // Reset the bag;
                buffer.EventsInProcessorByEcv.Clear();
            }

            var streams = eventsToProcess.Select(incomingEvent =>
            {
                ((Message)incomingEvent).ProcessorBufferVersion = processorBufferVersion;

                buffer.EventsInProcessorByEcv.TryAdd(incomingEvent.EventCollectionVersion, new EventInProcessorBucket(incomingEvent));

                return incomingEvent;
                //this.bus.Publish(new NewIncomingEvents(incomingEvent));
            })
            .GroupBy(x => x.StreamId, x => x,
                    (key, group) => new
                    {
                        StreamId = key,
                        Events = group
                    });

            foreach (var stream in streams)
                // no need to order by again
                //this.bus.Publish(new NewIncomingEvents(stream.Events.OrderBy(x => x.Version))); 
                this.bus.Publish(new NewIncomingEvents(stream.Events));

            this.log.Trace($"{this.microserviceName} is handling {eventsToProcess.Count} event/s of {buffer.StreamType} queue with {eventsInQueueCount} event/s pulled from {buffer.Url}");

            return true;
        }