Ejemplo n.º 1
0
        public void Creation()
        {
            var listener = new LocalSiteModelChangeListener(new SiteModelChangeProcessorItemHandler());

            listener.Should().NotBeNull();
            listener.Handler.Should().NotBeNull();
        }
Ejemplo n.º 2
0
        public void Creation_NoHandler()
        {
            Action act = () =>
            {
                var _ = new LocalSiteModelChangeListener(null);
            };

            act.Should().Throw <ArgumentException>().WithMessage("Listener must be supplied with a handler");
        }
Ejemplo n.º 3
0
        public void OnEvent_AcceptedEvent(CacheEntryEventType evtType, bool expectedToBeAccepted)
        {
            var mockEvent = new Mock <ICacheEntryEvent <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> >();

            mockEvent.Setup(x => x.EventType).Returns(evtType);

            using (var handler = new SiteModelChangeProcessorItemHandler())
            {
                var listener = new LocalSiteModelChangeListener(handler);
                listener.OnEvent(new List <ICacheEntryEvent <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > {
                    mockEvent.Object
                });

                // the listener should have placed the event in to the handler
                handler.QueueCount.Should().Be(expectedToBeAccepted ? 1 : 0);
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Executes the life cycle of the service until it is aborted
        /// </summary>
        public void Execute(IServiceContext context)
        {
            try
            {
                if (_log == null)
                {
                    Console.WriteLine($"Error: Null logger present in {nameof(SiteModelChangeProcessorService)}.{nameof(Execute)}");
                }

                _log.LogInformation($"{context.Name} starting executing");
                Aborted     = false;
                _waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);

                // Get the ignite grid and cache references

                var ignite = DIContext.Obtain <ITRexGridFactory>()?.Grid(StorageMutability.Immutable) ??
                             Ignition.GetIgnite(TRexGrids.ImmutableGridName());

                if (ignite == null)
                {
                    _log.LogError("Ignite reference in service is null - aborting service execution");
                    return;
                }

                // Don't start operations until the local (immutable) grid is confirmed as active
                DIContext.ObtainRequired <IActivatePersistentGridServer>().WaitUntilGridActive(TRexGrids.ImmutableGridName());

                // Once active, delay start of operations for a time to ensure everything is up and running
                var delay = DIContext.ObtainRequired <IConfigurationStore>().GetValueInt("TREX_SITE_MODEL_CHANGE_MAP_SERVICE_OPERATION_START_DELAY_SECONDS", 120);
                _log.LogInformation($"Delaying start of operations for {delay} seconds");
                Thread.Sleep(delay * 1000);

                _log.LogInformation("Obtaining queue cache reference");

                var queueCache = ignite.GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(TRexCaches.SiteModelChangeBufferQueueCacheName());

                _log.LogInformation($"Obtained queue cache for SiteModelChangeBufferQueueKey: {queueCache}");

                var handler  = new SiteModelChangeProcessorItemHandler();
                var listener = new LocalSiteModelChangeListener(handler);

                // Obtain the query handle for the continuous query from the DI context, or if not available create it directly
                // Construct the continuous query machinery
                // Set the initial query to return all elements in the cache
                // Instantiate the queryHandle and start the continuous query on the remote nodes
                // Note: Only cache items held on this local node will be handled here
                var queryHandleFactory = DIContext.Obtain <Func <LocalSiteModelChangeListener, IContinuousQueryHandle <ICacheEntry <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > > >();

                if (queryHandleFactory != null)
                {
                    _log.LogInformation("Obtaining query handle from DI factory");
                    _queryHandle = queryHandleFactory(listener);
                }

                while (_queryHandle == null && !Aborted)
                {
                    _log.LogInformation("Obtaining query handle from QueryContinuous() API");

                    try
                    {
                        _queryHandle = queueCache.QueryContinuous
                                           (qry: new ContinuousQuery <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(listener)
                        {
                            Local = true
                        },
                                           initialQry: new ScanQuery <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> {
                            Local = true
                        });
                    }
                    catch (Exception e)
                    {
                        _log.LogError(e, "Exception while constructing continuous query, will sleep and retry");
                        Thread.Sleep(5000);
                    }
                }

                if (_queryHandle == null || Aborted)
                {
                    _log.LogInformation("No query handle available, or aborting");
                    return;
                }

                using (_queryHandle)
                {
                    _log.LogInformation("Performing initial continuous query cursor scan of items to process");

                    // Perform the initial query to grab all existing elements and process them. Make sure to sort them in time order first
                    _queryHandle.GetInitialQueryCursor().OrderBy(x => x.Key.InsertUTCTicks).ForEach(handler.Add);

                    while (!Aborted)
                    {
                        try
                        {
                            {
                                // Cycle looking for new work to do as items arrive until aborted...
                                _log.LogInformation("Entering steady state continuous query scan of items to process");

                                // Activate the handler with the inject initial continuous query and move into steady state processing

                                InSteadyState = true;
                                handler.Activate();
                                do
                                {
                                    _waitHandle.WaitOne(_serviceCheckIntervalMs);
                                } while (!Aborted);
                            }
                        }
                        catch (Exception e)
                        {
                            _log.LogError(e, "Site model change processor service unhandled exception, waiting and trying again");

                            // Sleep for 5 seconds to see if things come right and then try again
                            Thread.Sleep(5000);
                        }
                    }
                }

                handler.Cancel();
            }
            catch (Exception e)
            {
                _log.LogError(e, "Exception occurred performing initial set up of continuous query and scan of existing items");
            }
            finally
            {
                _log.LogInformation($"{context.Name} completed executing");
            }
        }