예제 #1
0
        private void PerformProcessEvent(SiteModelChangeBufferQueueKey key, SiteModelChangeBufferQueueItem value)
        {
            var mockEvent = new Mock <ICacheEntryEvent <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> >();

            mockEvent.Setup(x => x.EventType).Returns(CacheEntryEventType.Created);
            mockEvent.Setup(x => x.Key).Returns(key);
            mockEvent.Setup(x => x.Value).Returns(value);

            using (var handler = new SiteModelChangeProcessorItemHandler())
            {
                handler.Add(mockEvent.Object);
                handler.QueueCount.Should().Be(1);

                // The handler has an item. Activate it to cause it to exercise ProcessChangeMapUpdateItems()

                handler.Activate();

                int count = 0;
                while (count++ == 0 || handler.QueueCount > 0)
                {
                    var wait = new EventWaitHandle(false, EventResetMode.ManualReset);
                    wait.WaitOne(1000);
                }

                // Check the item was removed from the queue
                handler.QueueCount.Should().Be(0);
            }
        }
예제 #2
0
 public void Abort()
 {
     using (var handler = new SiteModelChangeProcessorItemHandler())
     {
         handler.Abort();
         handler.Aborted.Should().BeTrue();
     }
 }
예제 #3
0
 public void Activation()
 {
     using (var handler = new SiteModelChangeProcessorItemHandler())
     {
         handler.Activate();
         handler.Active.Should().BeTrue();
         handler.Aborted.Should().BeFalse();
     }
 }
예제 #4
0
 public void Creation()
 {
     using (var handler = new SiteModelChangeProcessorItemHandler())
     {
         handler.Should().NotBeNull();
         handler.Active.Should().BeFalse();
         handler.Aborted.Should().BeFalse();
     }
 }
예제 #5
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);
            }
        }
예제 #6
0
        public void Creation_NoIgnite()
        {
            DIBuilder.Eject(); // Be doubly sure

            Action act = () =>
            {
                var _ = new SiteModelChangeProcessorItemHandler();
            };

            if (DIContext.DefaultIsRequired)
            {
                act.Should().Throw <Exception>().WithMessage("DIContext service provider not available");
            }
            else
            {
                act.Should().Throw <TRexException>().WithMessage("Failed to obtain immutable Ignite reference");
            }
        }
예제 #7
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");
            }
        }
예제 #8
0
 public LocalSiteModelChangeListener(SiteModelChangeProcessorItemHandler handler)
 {
     Handler = handler ?? throw new ArgumentException("Listener must be supplied with a handler");
 }