public DIIgniteServers() { // Create a set of mocked configurations for caches the servers was want var mockedConfigs = new List <CacheConfiguration> { new CacheConfiguration(TRexCaches.MutableNonSpatialCacheName()), new CacheConfiguration(TRexCaches.SpatialSubGridDirectoryCacheName(StorageMutability.Mutable)), new CacheConfiguration(TRexCaches.SpatialSubGridDirectoryCacheName(StorageMutability.Immutable)), new CacheConfiguration(TRexCaches.SpatialSubGridSegmentCacheName(StorageMutability.Mutable)), new CacheConfiguration(TRexCaches.SpatialSubGridSegmentCacheName(StorageMutability.Immutable)), new CacheConfiguration(TRexCaches.ImmutableNonSpatialCacheName()), new CacheConfiguration(TRexCaches.SiteModelMetadataCacheName()), new CacheConfiguration(TRexCaches.DesignTopologyExistenceMapsCacheName()), new CacheConfiguration(TRexCaches.TAGFileBufferQueueCacheName()), new CacheConfiguration(TRexCaches.SegmentRetirementQueueCacheName()), new CacheConfiguration(TRexCaches.SiteModelChangeBufferQueueCacheName()), new CacheConfiguration(TRexCaches.ProductionDataExistenceMapCacheName(StorageMutability.Mutable)), new CacheConfiguration(TRexCaches.ProductionDataExistenceMapCacheName(StorageMutability.Mutable)) }; var igniteConfiguration = new IgniteConfiguration { CacheConfiguration = mockedConfigs }; // Get the mocked Ignite instance and add the configuration to it IgniteMock.Immutable.mockIgnite.Setup(x => x.GetConfiguration()).Returns(igniteConfiguration); IgniteMock.Mutable.mockIgnite.Setup(x => x.GetConfiguration()).Returns(igniteConfiguration); }
/// <summary> /// Creates or obtains a reference to an already created change map file buffer queue /// </summary> private void InstantiateCache() { var ignite = DIContext.Obtain <ITRexGridFactory>()?.Grid(StorageMutability.Immutable) ?? Ignition.GetIgnite(TRexGrids.ImmutableGridName()); _queueCache = ignite?.GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>( TRexCaches.SiteModelChangeBufferQueueCacheName()); if (_queueCache == null) { Log.LogInformation($"Failed to get Ignite cache {TRexCaches.SiteModelChangeBufferQueueCacheName()}"); throw new TRexException("Ignite cache not available"); } }
/// <summary> /// Create the cache that holds the per project, per machine, change maps driven by TAG file ingest /// Note: This machine based information is distinguished from that in the non-spatial cache in that /// it is partitioned, rather than replicated. /// </summary> private void InstantiateSiteModelChangeBufferQueueCacheReference() { immutableTRexGrid.GetOrCreateCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(new CacheConfiguration { Name = TRexCaches.SiteModelChangeBufferQueueCacheName(), KeepBinaryInStore = true, CacheMode = CacheMode.Partitioned, // TODO: No backups for now Backups = 0, DataRegionName = DataRegions.IMMUTABLE_NONSPATIAL_DATA_REGION, // Configure the function that maps the change maps to nodes in the grid // Note: This cache uses an affinity function that assigns data for a site model onto a single node. // For the purposes of the immutable grid, it is helpful for a node to contain all change maps for a single // site model as this simplifies the process of updating those change maps in response to messages from production data ingest AffinityFunction = new ProjectBasedSpatialAffinityFunction(), }); }
/// <summary> /// Add the factories for the storage proxy caches, both standard and transacted, for spatial and non spatial caches in TRex /// </summary> private static void AddDIEntries() { DIBuilder.Continue() //*********************************************** // Injected factories for non-transacted proxies // ********************************************** // Add the singleton reference to the non-transacted site model change map cache .Add(x => x.AddSingleton <Func <IStorageProxyCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > >( () => new StorageProxyCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(DIContext.Obtain <ITRexGridFactory>() .Grid(StorageMutability.Immutable)? .GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(TRexCaches.SiteModelChangeBufferQueueCacheName()))) ) //****************************************** // Injected factories for transacted proxies // ***************************************** // Add the singleton reference to the transacted site model change map cache .Add(x => x.AddSingleton <Func <IStorageProxyCacheTransacted <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > >( () => new StorageProxyCacheTransacted <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(DIContext.Obtain <ITRexGridFactory>() .Grid(StorageMutability.Immutable)? .GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(TRexCaches.SiteModelChangeBufferQueueCacheName()), new SiteModelChangeBufferQueueKeyEqualityComparer()) )); }
private void AddChangeMapQueueCacheToDI() { var transactedProxy = new StorageProxyCacheTransacted_TestHarness <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> (DIContext.Obtain <ITRexGridFactory>().Grid(StorageMutability.Immutable)?.GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(TRexCaches.SiteModelChangeBufferQueueCacheName()), new SiteModelChangeBufferQueueKeyEqualityComparer()); var nonTransactedProxy = new StorageProxyCacheTransacted_TestHarness <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> (DIContext.Obtain <ITRexGridFactory>().Grid(StorageMutability.Immutable)?.GetCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem>(TRexCaches.SiteModelChangeBufferQueueCacheName()), new SiteModelChangeBufferQueueKeyEqualityComparer()); DIBuilder .Continue() // Add the factories for the storage proxy caches, both standard and transacted, for spatial and non spatial caches in TRex //////////////////////////////////////////////////// // Injected standard storage proxy cache //////////////////////////////////////////////////// // Add the singleton reference to the non-transacted site model change map cache .Add(x => x.AddSingleton <Func <IStorageProxyCache <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > >(() => nonTransactedProxy)) ///////////////////////////////////////////////////// // Injected transacted storage proxy cache factories ///////////////////////////////////////////////////// // Add the singleton reference to the transacted site model change map cache .Add(x => x.AddSingleton <Func <IStorageProxyCacheTransacted <ISiteModelChangeBufferQueueKey, ISiteModelChangeBufferQueueItem> > >(() => transactedProxy)) .Build() .Add(x => x.AddSingleton <ISiteModelChangeMapDeltaNotifier>(new SiteModelChangeMapDeltaNotifier())) .Build(); }
/// <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"); } }