protected override UntypedChannel Visitor(BroadcastChannel channel) { var results = new List<UntypedChannel>(); bool changed = false; foreach (UntypedChannel subscriber in channel.Listeners) { UntypedChannel newSubscriber = Visit(subscriber); if (newSubscriber == null || newSubscriber != subscriber) { changed = true; if (newSubscriber == null) continue; } results.Add(newSubscriber); } if (!_added) { _added = true; results.Add(_newChannel); changed = true; } if (changed) return new BroadcastChannel(results); return channel; }
private async Task OpenChannels() { InputChannel = new InputChannel( await StartChannelAsync(ServiceType.SystemInput)); /* * InputTvRemoteChannel fails when connecting non-authenticated * (Either a bug or feature from Microsoft!) * Simply disabling it for now - it serves no use anyways atm * InputTvRemoteChannel = new InputTVRemoteChannel( * await StartChannelAsync(ServiceType.SystemInputTVRemote)); */ MediaChannel = new MediaChannel( await StartChannelAsync(ServiceType.SystemMedia)); TextChannel = new TextChannel( await StartChannelAsync(ServiceType.SystemText)); BroadcastChannel = new BroadcastChannel( await StartChannelAsync(ServiceType.SystemBroadcast)); if (this.connectedAuthenticated) { InputTvRemoteChannel = new InputTVRemoteChannel( await StartChannelAsync(ServiceType.SystemInputTVRemote) ); } }
protected override UntypedChannel Visitor(BroadcastChannel channel) { var results = new List <UntypedChannel>(); bool changed = false; foreach (UntypedChannel subscriber in channel.Listeners) { UntypedChannel newSubscriber = Visit(subscriber); if (newSubscriber == null || newSubscriber != subscriber) { changed = true; if (newSubscriber == null) { continue; } } results.Add(newSubscriber); } if (!_added) { _added = true; results.Add(_newChannel); changed = true; } if (changed) { return(new BroadcastChannel(results)); } return(channel); }
/// <summary> /// Starts or restarts the handler listening for the [ProxyUpdateMessage] messages. /// </summary> private static void StartNotifyHandler() { lock (syncLock) { // Use the latest settings to reconnect to the [proxy-notify] channel. if (proxyNotifyChannel != null) { proxyNotifyChannel.Dispose(); } proxyNotifyChannel = hive.HiveMQ.Internal.GetProxyNotifyChannel(useBootstrap: true).Open(); // Register a handler for [ProxyUpdateMessage] messages that determines // whether the message is meant for this service instance and handle it. proxyNotifyChannel.ConsumeAsync <ProxyUpdateMessage>( async message => { // We cannot process updates in parallel so we'll use an // AsyncMutex to prevent this. using (await asyncLock.AcquireAsync()) { var forThisInstance = false; if (isPublic) { forThisInstance = message.PublicProxy && !isBridge || message.PublicBridge && isBridge; } else { forThisInstance = message.PrivateProxy && !isBridge || message.PrivateBridge && isBridge; } if (!forThisInstance) { log.LogInfo(() => $"HAPROXY-SHIM: Received but ignorning: {message}"); return; } log.LogInfo(() => $"HAPROXY-SHIM: Received: {message}"); var jitter = NeonHelper.RandTimespan(HiveConst.MaxJitter); log.LogDebug(() => $"HAPROXY-SHIM: Jitter delay [{jitter}]."); await Task.Delay(jitter); await ConfigureHAProxy(); } }); } }
protected override UntypedChannel Visitor(BroadcastChannel channel) { _current = GetVertex(channel.GetHashCode(), () => "Router", typeof(BroadcastChannel), typeof(object)); if (_stack.Count > 0) { _edges.Add(new Edge(_stack.Peek(), _current, _current.TargetType.Name)); } return(WithVertex(() => base.Visitor(channel))); }
public void Should_return_false_if_there_are_no_subscribers() { Fiber fiber = new SynchronousFiber(); Channel<UserUpdate> channel = new BroadcastChannel<UserUpdate>(new Channel<UserUpdate>[] {}); var update = new UserUpdate(); channel.Send(update); // exception here? or just ignore }
public void Should_return_false_if_there_are_no_subscribers() { Fiber fiber = new SynchronousFiber(); Channel <UserUpdate> channel = new BroadcastChannel <UserUpdate>(new Channel <UserUpdate>[] {}); var update = new UserUpdate(); channel.Send(update); // exception here? or just ignore }
private async Task OpenChannels() { InputChannel = new InputChannel( await StartChannelAsync(ServiceType.SystemInput)); MediaChannel = new MediaChannel( await StartChannelAsync(ServiceType.SystemMedia)); TextChannel = new TextChannel( await StartChannelAsync(ServiceType.SystemText)); BroadcastChannel = new BroadcastChannel( await StartChannelAsync(ServiceType.SystemBroadcast)); InputTvRemoteChannel = new InputTVRemoteChannel( await StartChannelAsync(ServiceType.SystemInputTVRemote)); }
public void Dispose() { // TODO: Close opened channels? // Assuming so for the time being, but don't know how to send stop messages yet InputChannel.Dispose(); // InputTvRemoteChannel.Dispose(); TextChannel.Dispose(); MediaChannel.Dispose(); BroadcastChannel.Dispose(); _sessionMessageTransport.Dispose(); _messageTransport.Dispose(); }
protected override object ExecuteCommand(object message) { var gs = (TimeGetSet)message; if (gs.IsGet) { BroadcastChannel.TimeGet(gs.IsExecute, gs.DateTime, Client.UniqueKey); } else { BroadcastChannel.TimeSet(gs.IsExecute, gs.DateTime, Client.UniqueKey); } return(null); }
private SmartGlassClient( Device device, ConnectResponseMessage connectResponse, CryptoContext cryptoContext) { _messageTransport = new MessageTransport(device.Address.ToString(), cryptoContext); _sessionMessageTransport = new SessionMessageTransport( _messageTransport, new SessionInfo() { ParticipantId = connectResponse.ParticipantId }); _sessionMessageTransport.MessageReceived += (s, e) => { var consoleStatusMessage = e.Message as ConsoleStatusMessage; if (consoleStatusMessage != null) { CurrentConsoleStatus = new ConsoleStatus() { Configuration = consoleStatusMessage.Configuration, ActiveTitles = consoleStatusMessage.ActiveTitles }; ConsoleStatusChanged?.Invoke(this, new ConsoleStatusChangedEventArgs( CurrentConsoleStatus )); } }; _sessionMessageTransport.SendAsync(new LocalJoinMessage()); _inputChannel = new DisposableAsyncLazy <InputChannel>(async() => { return(new InputChannel(await StartChannelAsync(ServiceType.SystemInput))); }); _mediaChannel = new DisposableAsyncLazy <MediaChannel>(async() => { return(new MediaChannel(await StartChannelAsync(ServiceType.SystemMedia))); }); _broadcastChannel = new DisposableAsyncLazy <BroadcastChannel>(async() => { var broadcastChannel = new BroadcastChannel(await StartChannelAsync(ServiceType.SystemBroadcast)); await broadcastChannel.WaitForEnabledAsync(); return(broadcastChannel); }); }
public void Should_filter_out_unwanted_messages() { var update = new UserUpdate {LastActivity = DateTime.Now - 5.Minutes()}; Fiber fiber = new SynchronousFiber(); var future = new FutureChannel<UserUpdate>(); var filter = new FilterChannel<UserUpdate>(fiber, future, x => x.LastActivity > DateTime.Now); Channel<UserUpdate> channel = new BroadcastChannel<UserUpdate>(new[] {filter}); channel.Send(update); Assert.IsFalse(future.WaitUntilCompleted(1.Seconds())); }
protected override Channel <T> Visitor <T>(BroadcastChannel <T> channel) { bool changed; Channel <T>[] subscribers = VisitSubscribers(channel.Listeners, out changed).ToArray(); if (subscribers.Length == 1) { return(subscribers[0]); } if (changed) { return(new BroadcastChannel <T>(subscribers)); } return(channel); }
public void Should_filter_out_unwanted_messages() { var update = new UserUpdate { LastActivity = DateTime.Now - 5.Minutes() }; Fiber fiber = new SynchronousFiber(); var future = new FutureChannel <UserUpdate>(); var filter = new FilterChannel <UserUpdate>(fiber, future, x => x.LastActivity > DateTime.Now); Channel <UserUpdate> channel = new BroadcastChannel <UserUpdate>(new[] { filter }); channel.Send(update); Assert.IsFalse(future.WaitUntilCompleted(1.Seconds())); }
/// <summary> /// Manages the Varnish initial configuration from Consul and Vault settings and /// then listens for <see cref="ProxyUpdateMessage"/> messages on the <see cref="HiveMQChannels.ProxyNotify"/> /// broadcast by <b>neon-proxy-manager</b> signalling that the configuration has been /// updated. /// </summary> /// <remarks> /// <para> /// This method will terminate the service with an error if the configuration could /// not be retrieved or applied for the first attempt since this very likely indicates /// a larger problem with the hive (e.g. Consul is down). /// </para> /// <para> /// If Varnish was configured successfully on the first attempt, subsequent failures /// will be logged as warnings but the service will continue running with the out-of-date /// configuration to provide some resilience for running hive services. /// </para> /// </remarks> /// <returns>The tracking <see cref="Task"/>.</returns> private async static Task VarnishShim() { // This call ensures that Varnish is started immediately. await ConfigureVarnish(); // Register a handler for [ProxyUpdateMessage] messages that determines // whether the message is meant for this service instance and handle it. StartNotifyHandler(); // Register an event handler that will be fired when the HiveMQ bootstrap // settings change. This will restart the [ProxyUpdateMessage] listener // using the new settings. hive.HiveMQ.Internal.HiveMQBootstrapChanged += (s, a) => { StartNotifyHandler(); }; // Spin quietly while waiting for a cancellation indicating that // the service is stopping. var task = new AsyncPeriodicTask( TimeSpan.FromMinutes(5), onTaskAsync: async() => await Task.FromResult(false), onTerminateAsync: async() => { log.LogInfo(() => "VARNISH-SHIM: Terminating"); if (proxyNotifyChannel != null) { proxyNotifyChannel.Dispose(); proxyNotifyChannel = null; } await Task.CompletedTask; }, cancellationTokenSource: terminator.CancellationTokenSource); await task.Run(); }
public void Should_schedule_events() { var update = new UserUpdate {LastActivity = DateTime.Now - 5.Minutes()}; Fiber fiber = new SynchronousFiber(); var future = new FutureChannel<UserUpdate>(); Channel<UserUpdate> channel = new BroadcastChannel<UserUpdate>(new Channel<UserUpdate>[] {future}); var scheduler = new TimerScheduler(fiber); scheduler.Schedule(1000, fiber, () => channel.Send(update)); Thread.Sleep(500); Assert.IsFalse(future.WaitUntilCompleted(0.Seconds())); Assert.IsTrue(future.WaitUntilCompleted(1.Seconds())); }
public void Should_add_a_consumer_that_is_assignable_to_the_type() { var firstFuture = new Future<TestMessage>(); var secondFuture = new Future<ITestMessage>(); var first = new ConsumerChannel<TestMessage>(_fiber, firstFuture.Complete); var subs = new BroadcastChannel<TestMessage>(new[] {first}); var adapter = new ChannelAdapter<TestMessage>(subs); var second = new ConsumerChannel<ITestMessage>(_fiber, secondFuture.Complete); using (var scope = adapter.Connect(x => x.AddChannel(second))) { new TraceChannelVisitor().Visit(adapter); adapter.Send(new TestMessage()); } firstFuture.IsCompleted.ShouldBeTrue(); secondFuture.IsCompleted.ShouldBeTrue(); }
protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // TODO: Close opened channels? // Assuming so for the time being, but don't know how to send stop messages yet InputChannel.Dispose(); // InputTvRemoteChannel.Dispose(); TextChannel.Dispose(); MediaChannel.Dispose(); BroadcastChannel.Dispose(); _sessionMessageTransport.Dispose(); _messageTransport.Dispose(); } _disposed = true; } }
public void Should_add_a_consumer_to_an_existing_adapter_chain() { var firstFuture = new Future <TestMessage>(); var secondFuture = new Future <TestMessage>(); var first = new ConsumerChannel <TestMessage>(_fiber, firstFuture.Complete); var subs = new BroadcastChannel <TestMessage>(new[] { first }); var adapter = new ChannelAdapter <TestMessage>(subs); var second = new ConsumerChannel <TestMessage>(_fiber, secondFuture.Complete); using (var scope = adapter.Connect(x => x.AddChannel(second))) { new TraceChannelVisitor().Visit(adapter); adapter.Send(new TestMessage()); } firstFuture.IsCompleted.ShouldBeTrue(); secondFuture.IsCompleted.ShouldBeTrue(); }
private void CheckScheduleForBroadcastSwitchover(BroadcastChannel channel) { Broadcast cuedShow = null; Broadcast currentShow = null; bool foundScheduledShow = false; bool foundCurrentShow = false; foreach (Broadcast show in channel.schedule) { if (Time.time > show.startTime && !show.isPlaying && !show.finishedPlaying) { cuedShow = show; foundScheduledShow = true; } if (show.isPlaying) { currentShow = show; foundCurrentShow = true; } } if (foundScheduledShow) { if (foundCurrentShow) { channel.PlayBroadcast(cuedShow); cuedShow.isPlaying = true; channel.ResetBroadcast(currentShow); currentShow.isPlaying = false; currentShow.finishedPlaying = true; } else { if (Time.time > currentShow.startTime + currentShow.duration) { channel.ShowOffAirScreens(); } } } }
public void Should_schedule_events() { var update = new UserUpdate { LastActivity = DateTime.Now - 5.Minutes() }; Fiber fiber = new SynchronousFiber(); var future = new FutureChannel <UserUpdate>(); Channel <UserUpdate> channel = new BroadcastChannel <UserUpdate>(new Channel <UserUpdate>[] { future }); var scheduler = new TimerScheduler(fiber); scheduler.Schedule(1000, fiber, () => channel.Send(update)); Thread.Sleep(500); Assert.IsFalse(future.WaitUntilCompleted(0.Seconds())); Assert.IsTrue(future.WaitUntilCompleted(1.Seconds())); }
protected override UntypedChannel Visitor(ChannelAdapter channel) { UntypedChannel original = channel.Output; UntypedChannel replacement = Visit(original); if (!_added) { if (replacement.GetType() == typeof(ShuntChannel)) { replacement = new BroadcastChannel(new[] { _newChannel }); _added = true; } } if (original != replacement) { channel.ChangeOutputChannel(original, replacement); } return(channel); }
protected override UntypedChannel Visitor(BroadcastChannel channel) { var results = new List <UntypedChannel>(); bool changed = false; foreach (UntypedChannel subscriber in channel.Listeners) { UntypedChannel newSubscriber = Visit(subscriber); if (_channels.Contains(newSubscriber)) { _channels.Remove(newSubscriber); newSubscriber = null; } if (newSubscriber == null || newSubscriber != subscriber) { changed = true; if (newSubscriber == null) { continue; } } results.Add(newSubscriber); } if (results.Count == 0) { return(null); } if (changed) { return(new BroadcastChannel(results)); } return(channel); }
protected override UntypedChannel Visitor(ChannelAdapter channel) { bool wasAdded = _added; channel.ChangeOutputChannel(original => { _added = wasAdded; UntypedChannel replacement = Visit(original); if (!_added) { if (replacement.GetType() == typeof(ShuntChannel)) { replacement = new BroadcastChannel(new[] { _newChannel }); _added = true; } } return(replacement); }); return(channel); }
protected override UntypedChannel Visitor(BroadcastChannel channel) { channel.Listeners.OrderBy(x => x.GetType().FullName).Each(subscriber => { Visit(subscriber); }); return(channel); }
/// <summary> /// Parameterized constructor /// </summary> /// <param name="channel">The specified channel to use</param> public broadcast_channel_indicator(BroadcastChannel channel) : base(TlvTag) { Value = (byte)channel; }
protected override object ExecuteCommand(object message) { BroadcastChannel.BroadcastMessage(message == null ? null : message.ToString(), Client.UniqueKey); return(null); }
protected virtual UntypedChannel Visitor(BroadcastChannel channel) { channel.Listeners.Each(subscriber => { Visit(subscriber); }); return(channel); }
protected virtual Channel <T> Visitor <T>(BroadcastChannel <T> channel) { channel.Listeners.Each(subscriber => { Visit(subscriber); }); return(channel); }
/// <summary> /// Application entry point. /// </summary> /// <param name="args">Command line arguments.</param> public static async Task Main(string[] args) { LogManager.Default.SetLogLevel(Environment.GetEnvironmentVariable("LOG_LEVEL")); log = LogManager.Default.GetLogger(typeof(Program)); log.LogInfo(() => $"Starting [{serviceName}]"); log.LogInfo(() => $"LOG_LEVEL={LogManager.Default.LogLevel.ToString().ToUpper()}"); // Create process terminator to handle process termination signals. terminator = new ProcessTerminator(log); terminator.AddHandler( () => { // Cancel any operations in progress. exit = true; terminator.CancellationTokenSource.Cancel(); // This gracefully closes the [proxyNotifyChannel] so HiveMQ will // promptly remove the associated queue. if (proxyNotifyChannel != null) { proxyNotifyChannel.Dispose(); proxyNotifyChannel = null; } try { NeonHelper.WaitFor(() => !processingConfigs, terminator.Timeout); log.LogInfo(() => "Tasks stopped gracefully."); } catch (TimeoutException) { log.LogWarn(() => $"Tasks did not stop within [{terminator.Timeout}]."); } }); // Establish the hive connections. if (NeonHelper.IsDevWorkstation) { var vaultCredentialsSecret = "neon-proxy-manager-credentials"; Environment.SetEnvironmentVariable("VAULT_CREDENTIALS", vaultCredentialsSecret); hive = HiveHelper.OpenHiveRemote(new DebugSecrets().VaultAppRole(vaultCredentialsSecret, "neon-proxy-manager")); } else { hive = HiveHelper.OpenHive(); } // [neon-proxy-manager] requires access to the [IHostingManager] implementation for the // current environment, so we'll need to initialize the hosting loader. HostingLoader.Initialize(); try { // Log into Vault using a Docker secret. var vaultCredentialsSecret = Environment.GetEnvironmentVariable("VAULT_CREDENTIALS"); if (string.IsNullOrEmpty(vaultCredentialsSecret)) { log.LogCritical("[VAULT_CREDENTIALS] environment variable does not exist."); Program.Exit(1, immediate: true); } var vaultSecret = HiveHelper.GetSecret(vaultCredentialsSecret); if (string.IsNullOrEmpty(vaultSecret)) { log.LogCritical($"Cannot read Docker secret [{vaultCredentialsSecret}]."); Program.Exit(1, immediate: true); } var vaultCredentials = HiveCredentials.ParseJson(vaultSecret); if (vaultCredentials == null) { log.LogCritical($"Cannot parse Docker secret [{vaultCredentialsSecret}]."); Program.Exit(1, immediate: true); } // Open the hive data services and then start the main service task. log.LogInfo(() => $"Connecting: Vault"); using (vault = HiveHelper.OpenVault(vaultCredentials)) { log.LogInfo(() => $"Connecting: Consul"); using (consul = HiveHelper.OpenConsul()) { log.LogInfo(() => $"Connecting: Docker"); using (docker = HiveHelper.OpenDocker()) { log.LogInfo(() => $"Connecting: {HiveMQChannels.ProxyNotify} channel"); // NOTE: // // We're passing [useBootstrap=true] here so that the HiveMQ client will // connect directly to the HiveMQ cluster nodes as opposed to routing // traffic through the private traffic manager. This is necessary because // the load balancers rely on HiveMQ to broadcast update notifications. // // One consequence of this is that this service will need to be restarted // whenever HiveMQ instances are relocated to different hive hosts. // We're going to monitor for changes to the HiveMQ bootstrap settings // and gracefully terminate the process when this happens. We're then // depending on Docker to restart the process so we'll be able to pick // up the change. hive.HiveMQ.Internal.HiveMQBootstrapChanged += (s, a) => { log.LogInfo("HiveMQ bootstrap settings change detected. Terminating service with [exitcode=-1] expecting that Docker will restart it."); // Use ExitCode=-1 so that we'll restart even if the service/container // was not configured with [restart=always]. terminator.Exit(-1); }; using (proxyNotifyChannel = hive.HiveMQ.Internal.GetProxyNotifyChannel(useBootstrap: true).Open()) { // Read the service settings, initializing their default values // if they don't already exist. if (!await consul.KV.Exists(certWarnDaysKey)) { log.LogInfo($"Persisting setting [{certWarnDaysKey}=30.0]"); await consul.KV.PutDouble(certWarnDaysKey, 30.0); } if (!await consul.KV.Exists(cacheRemoveSecondsKey)) { log.LogInfo($"Persisting setting [{cacheRemoveSecondsKey}=300.0]"); await consul.KV.PutDouble(cacheRemoveSecondsKey, 300.0); } if (!await consul.KV.Exists(failsafeSecondsKey)) { log.LogInfo($"Persisting setting [{failsafeSecondsKey}=120.0]"); await consul.KV.PutDouble(failsafeSecondsKey, 120); } certWarnTime = TimeSpan.FromDays(await consul.KV.GetDouble(certWarnDaysKey)); cacheRemoveDelay = TimeSpan.FromDays(await consul.KV.GetDouble(cacheRemoveSecondsKey)); failsafeInterval = TimeSpan.FromSeconds(await consul.KV.GetDouble(failsafeSecondsKey)); log.LogInfo(() => $"Using setting [{certWarnDaysKey}={certWarnTime.TotalSeconds}]"); log.LogInfo(() => $"Using setting [{cacheRemoveSecondsKey}={cacheRemoveDelay.TotalSeconds}]"); log.LogInfo(() => $"Using setting [{failsafeSecondsKey}={failsafeInterval.TotalSeconds}]"); // Run the service tasks. var tasks = new List <Task>(); tasks.Add(ConfigGeneratorAsync()); tasks.Add(FailsafeBroadcasterAsync()); await NeonHelper.WaitAllAsync(tasks); } } } } } catch (Exception e) { log.LogCritical(e); Program.Exit(1); return; } finally { HiveHelper.CloseHive(); terminator.ReadyToExit(); } Program.Exit(0); return; }
protected override UntypedChannel Visitor(ChannelAdapter channel) { bool wasAdded = _added; channel.ChangeOutputChannel(original => { _added = wasAdded; UntypedChannel replacement = Visit(original); if (!_added) { if (replacement.GetType() == typeof(ShuntChannel)) { replacement = new BroadcastChannel(new[] { _newChannel }); _added = true; } } return replacement; }); return channel; }
protected override UntypedChannel Visitor(ChannelAdapter channel) { UntypedChannel original = channel.Output; UntypedChannel replacement = Visit(original); if (!_added) { if (replacement.GetType() == typeof(ShuntChannel)) { replacement = new BroadcastChannel(new[] {_newChannel}); _added = true; } } if (original != replacement) channel.ChangeOutputChannel(original, replacement); return channel; }
/// <summary> /// Application entry point. /// </summary> /// <param name="args">Command line arguments.</param> public static async Task Main(string[] args) { LogManager.Default.SetLogLevel(Environment.GetEnvironmentVariable("LOG_LEVEL")); log = LogManager.Default.GetLogger(typeof(Program)); log.LogInfo(() => $"Starting [{serviceName}]"); log.LogInfo(() => $"LOG_LEVEL={LogManager.Default.LogLevel.ToString().ToUpper()}"); // Create process terminator to handle process termination signals. terminator = new ProcessTerminator(log); try { // Establish the hive connections. if (NeonHelper.IsDevWorkstation) { var secrets = new DebugSecrets(); // NOTE: // // Add your target hive's Vault credentials here for // manual debugging. Take care not to commit sensitive // credentials for production hives. // // You'll find this information in the ROOT hive login // for the target hive. secrets.Add("neon-hive-manager-vaultkeys", new VaultCredentials() { RootToken = "cd5831fa-86ec-cc22-b1f3-051f88147382", KeyThreshold = 1, UnsealKeys = new List <string>() { "8SgwdO/GwqJ7nyxT2tK2n1CCR3084kQVh7gEy8jNQh8=" } }); hive = HiveHelper.OpenHiveRemote(secrets); } else { hive = HiveHelper.OpenHive(sshCredentialsSecret: "neon-ssh-credentials"); } // Ensure that we're running on a manager node. We won't be able // to query swarm status otherwise. var nodeRole = Environment.GetEnvironmentVariable("NEON_NODE_ROLE"); if (string.IsNullOrEmpty(nodeRole)) { log.LogCritical(() => "Service does not appear to be running on a neonHIVE."); Program.Exit(1, immediate: true); } if (!string.Equals(nodeRole, NodeRole.Manager, StringComparison.OrdinalIgnoreCase)) { log.LogCritical(() => $"[neon-hive-manager] service is running on a [{nodeRole}] hive node. Running on only [{NodeRole.Manager}] nodes are supported."); Program.Exit(1, immediate: true); } // Open the hive data services and then start the main service task. log.LogDebug(() => $"Connecting: Consul"); using (consul = HiveHelper.OpenConsul()) { log.LogDebug(() => $"Connecting: Docker"); using (docker = HiveHelper.OpenDocker()) { log.LogInfo(() => $"Connecting: {HiveMQChannels.ProxyNotify} channel"); // We're passing [useBootstrap=true] here so that the HiveMQ client will // connect directly to the HiveMQ cluster nodes as opposed to routing // traffic through the private traffic manager. This is necessary because // the load balancers rely on HiveMQ to broadcast update notifications. // // One consequence of this is that this service will need to be restarted // whenever HiveMQ instances are relocated to different hive hosts. // We're going to monitor for changes to the HiveMQ bootstrap settings // and gracefully terminate the process when this happens. We're then // depending on Docker to restart the process so we'll be able to pick // up the change. hive.HiveMQ.Internal.HiveMQBootstrapChanged += (s, a) => { log.LogInfo("HiveMQ bootstrap settings change detected. Terminating service with [exitcode=-1] expecting that Docker will restart it."); // Use ExitCode=-1 so that we'll restart even if the service/container // was not configured with [restart=always]. terminator.Exit(-1); }; using (proxyNotifyChannel = hive.HiveMQ.Internal.GetProxyNotifyChannel(useBootstrap: true).Open()) { await RunAsync(); } } } } catch (Exception e) { log.LogCritical(e); Program.Exit(1); return; } finally { HiveHelper.CloseHive(); terminator.ReadyToExit(); } Program.Exit(0); return; }
private void OnBroadcast() { var source = StreamSource; var contentReaderFactory = ContentType; if (!CanBroadcast(source, contentReaderFactory, channelName)) { return; } IYellowPageClient yellowPage = this.yellowPage; var channelInfo = CreateChannelInfo(this); var channelTrack = CreateChannelTrack(this); var channel_id = BroadcastChannel.CreateChannelID( peerCast.BroadcastID, networkType, channelName, genre, source.ToString()); var source_stream = selectedSourceStream ?? peerCast.SourceStreamFactories .Where(sstream => (sstream.Type & SourceStreamType.Broadcast) != 0) .FirstOrDefault(sstream => sstream.Scheme == source.Scheme); var channel = peerCast.BroadcastChannel( networkType, yellowPage, channel_id, channelInfo, source, source_stream, contentReaderFactory); if (channel != null) { channel.ChannelTrack = channelTrack; } var info = new BroadcastInfoViewModel { NetworkType = this.NetworkType, StreamUrl = this.StreamUrl, StreamType = this.SelectedSourceStream != null ? this.SelectedSourceStream.Name : null, Bitrate = this.bitrate.HasValue ? this.bitrate.Value : 0, ContentType = this.ContentType.Name, YellowPage = this.YellowPage != null ? this.YellowPage.Name : null, ChannelName = this.ChannelName, Genre = this.Genre, Description = this.Description, Comment = this.Comment, ContactUrl = this.ContactUrl, TrackTitle = this.TrackTitle, TrackAlbum = this.TrackAlbum, TrackArtist = this.TrackArtist, TrackGenre = this.TrackGenre, TrackUrl = this.TrackUrl, Favorite = false, }; uiSettings.AddBroadcastHistory(info); uiSettings.Save(); }
protected override Channel <T> Visitor <T>(BroadcastChannel <T> channel) { Trace.WriteLine("ChannelRouter<{0}>, {1} subscribers".FormatWith(typeof(T).Name, channel.Listeners.Count())); return(base.Visitor(channel)); }
protected override UntypedChannel Visitor(BroadcastChannel channel) { Trace.WriteLine("UntypedChannelRouter: {0} subscribers".FormatWith(channel.Listeners.Count())); return(base.Visitor(channel)); }