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); } }
public void Abort() { using (var handler = new SiteModelChangeProcessorItemHandler()) { handler.Abort(); handler.Aborted.Should().BeTrue(); } }
public void Activation() { using (var handler = new SiteModelChangeProcessorItemHandler()) { handler.Activate(); handler.Active.Should().BeTrue(); handler.Aborted.Should().BeFalse(); } }
public void Creation() { using (var handler = new SiteModelChangeProcessorItemHandler()) { handler.Should().NotBeNull(); handler.Active.Should().BeFalse(); handler.Aborted.Should().BeFalse(); } }
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); } }
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"); } }
/// <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"); } }
public LocalSiteModelChangeListener(SiteModelChangeProcessorItemHandler handler) { Handler = handler ?? throw new ArgumentException("Listener must be supplied with a handler"); }