/// <summary> /// <para> /// <b>INTERNAL USE ONLY:</b> Returns a <see cref="HiveBus"/> connected to the hive /// <b>neon</b> virtual host. This property is intended for use only by neonHIVE /// tools, services and containers. /// </para> /// <note> /// <b>WARNING:</b> The <see cref="HiveBus"/> instance returned should <b>NEVER BE DISPOSED</b>. /// </note> /// </summary> /// <param name="useBootstrap"> /// Optionally specifies that the settings returned should directly /// reference to the HiveMQ cluster nodes rather than routing traffic /// through the <b>private</b> traffic manager. This is used internally /// to resolve chicken-and-the-egg dilemmas for the traffic manager and /// proxy implementations that rely on HiveMQ messaging. /// </param> public HiveBus NeonHiveBus(bool useBootstrap = false) { var bus = neonHiveBus; if (bus != null) { return(bus); } lock (syncLock) { if (neonHiveBus != null) { return(neonHiveBus); } if (!useBootstrap) { return(neonHiveBus = parent.GetNeonSettings(useBootstrap: false).ConnectHiveBus()); } // Remember the bootstrap settings and then start a task that // periodically polls Consul for settings changes to raise the // [HiveMQBootstrapChanged] event when changes happen. bootstrapSettings = parent.GetNeonSettings(useBootstrap); neonHiveBus = bootstrapSettings.ConnectHiveBus(); bootstrapChangeDetector = Task.Run(() => BootstrapChangeDetector()); return(neonHiveBus); } }
/// <summary> /// Polls Consul for changes to the <b>neon</b> virtual host HiveMQ /// bootstrap settings and raises the <see cref="HiveMQBootstrapChanged"/> /// when this happens. /// </summary> /// <returns>The tracking <see cref="Task"/>.</returns> private async Task BootstrapChangeDetector() { var pollInterval = TimeSpan.FromSeconds(120); // Delay for a random period of time between [0..pollInterval]. This // will help prevent Consul traffic spikes when services are started // at the same time. await Task.Delay(NeonHelper.RandTimespan(pollInterval)); // This will spin forever once started when a NeonHiveBus using bootstrap // settings is created above. This polls Consul for changes to the [neon] // HiveMQ virtual host settings stored in Consul. We'll be performing two // Consul lookups for each poll (one to get the [neon] vhost settings and // the other to obtain the bootstrap settings. // // When a settings change is detected, we'll first ensure that we've // establisted a new [neonHiveBus] connection using the new settings and // then we'll raise the change event. while (true) { try { var latestBootstrapSettngs = parent.GetNeonSettings(useBootstrap: true); if (!NeonHelper.JsonEquals(bootstrapSettings, latestBootstrapSettngs)) { // The latest bootstrap settings don't match what we used to // connect the current [bus]. lock (syncLock) { bootstrapSettings = latestBootstrapSettngs; neonHiveBus = bootstrapSettings.ConnectHiveBus(); } var handler = bootstrapChangedEvent; handler?.Invoke(this, latestBootstrapSettngs); } } catch (Exception e) { log.LogError(e); } await Task.Delay(pollInterval); } }