public static void HostStarted(ScriptHost scriptHost) { if (scriptHost == null || scriptHost.Functions == null) { return; } foreach (var function in scriptHost.Functions) { if (function == null || function.Metadata == null) { continue; } MetricEventSource.Log.RaiseFunctionsInfoEvent( siteName, GetNormalizedString(function.Name), function.Metadata != null ? SerializeBindings(function.Metadata.InputBindings) : GetNormalizedString(null), function.Metadata != null ? SerializeBindings(function.Metadata.OutputBindings) : GetNormalizedString(null), function.Metadata.ScriptType.ToString(), function.Metadata != null ? function.Metadata.IsDisabled : false); } }
public static ScriptHost Create(ScriptHostConfiguration scriptConfig = null) { if (scriptConfig == null) { scriptConfig = new ScriptHostConfiguration() { RootPath = Environment.CurrentDirectory }; } if (!Path.IsPathRooted(scriptConfig.RootPath)) { scriptConfig.RootPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootPath); } JobHostConfiguration config = new JobHostConfiguration(); ScriptHost scriptHost = new ScriptHost(config, scriptConfig); scriptHost.Initialize(); return scriptHost; }
public void RunAndBlock(CancellationToken cancellationToken = default(CancellationToken)) { // Start the host and restart it if requested. Host Restarts will happen when // host level configuration files change do { IsRunning = false; _config.HostConfig = new JobHostConfiguration(); ScriptHost newInstance = ScriptHost.Create(_config); newInstance.Start(); lock (_liveInstances) { _liveInstances.Add(newInstance); } _currentInstance = newInstance; OnHostStarted(); // only after ALL initialization is complete do we set this flag IsRunning = true; // Wait for a restart signal. This event will automatically reset. // While we're restarting, it is possible for another restart to be // signaled. That is fine - the restart will be processed immediately // once we get to this line again. The important thing is that these // restarts are only happening on a single thread. WaitHandle.WaitAny(new WaitHandle[] { newInstance.RestartEvent, _stopEvent }); // Orphan the current host instance. We're stopping it, so it won't listen for any new functions // it will finish any currently executing functions and then clean itself up. // Spin around and create a new host instance. Task tIgnore = Orphan(newInstance); } while (!_stopped); }
public static ScriptHost Create(ScriptHostConfiguration scriptConfig = null) { if (scriptConfig == null) { scriptConfig = new ScriptHostConfiguration(); } if (!Path.IsPathRooted(scriptConfig.RootScriptPath)) { scriptConfig.RootScriptPath = Path.Combine(Environment.CurrentDirectory, scriptConfig.RootScriptPath); } ScriptHost scriptHost = new ScriptHost(scriptConfig); try { scriptHost.Initialize(); } catch (Exception ex) { if (scriptHost.TraceWriter != null) { scriptHost.TraceWriter.Error("ScriptHost initialization failed", ex); } throw; } return scriptHost; }
public void RunAndBlock(CancellationToken cancellationToken = default(CancellationToken)) { // Start the host and restart it if requested. Host Restarts will happen when // host level configuration files change do { ScriptHost newInstance = null; try { // if we were in an error state retain that, // otherwise move to default if (State != ScriptHostState.Error) { State = ScriptHostState.Default; } // Create a new host config, but keep the host id from existing one _config.HostConfig = new JobHostConfiguration { HostId = _config.HostConfig.HostId }; OnInitializeConfig(_config); newInstance = _scriptHostFactory.Create(_settingsManager, _config); _traceWriter = newInstance.TraceWriter; _currentInstance = newInstance; lock (_liveInstances) { _liveInstances.Add(newInstance); } OnHostCreated(); if (_traceWriter != null) { string message = string.Format("Starting Host (HostId={0}, Version={1}, ProcessId={2}, Debug={3})", newInstance.ScriptConfig.HostConfig.HostId, ScriptHost.Version, Process.GetCurrentProcess().Id, newInstance.InDebugMode.ToString()); _traceWriter.Info(message); } newInstance.StartAsync(cancellationToken).GetAwaiter().GetResult(); // log any function initialization errors LogErrors(newInstance); OnHostStarted(); // only after ALL initialization is complete do we set the // state to Running State = ScriptHostState.Running; LastError = null; // Wait for a restart signal. This event will automatically reset. // While we're restarting, it is possible for another restart to be // signaled. That is fine - the restart will be processed immediately // once we get to this line again. The important thing is that these // restarts are only happening on a single thread. WaitHandle.WaitAny(new WaitHandle[] { cancellationToken.WaitHandle, newInstance.RestartEvent, _stopEvent }); // Orphan the current host instance. We're stopping it, so it won't listen for any new functions // it will finish any currently executing functions and then clean itself up. // Spin around and create a new host instance. Task taskIgnore = Orphan(newInstance); } catch (Exception ex) { State = ScriptHostState.Error; LastError = ex; // We need to keep the host running, so we catch and log any errors // then restart the host if (_traceWriter != null) { _traceWriter.Error("A ScriptHost error has occurred", ex); } // If a ScriptHost instance was created before the exception was thrown // Orphan and cleanup that instance. if (newInstance != null) { Orphan(newInstance, forceStop: true) .ContinueWith(t => { if (t.IsFaulted) { t.Exception.Handle(e => true); } }, TaskContinuationOptions.ExecuteSynchronously); } // Wait for a short period of time before restarting to // avoid cases where a host level config error might cause // a rapid restart cycle Task.Delay(_config.RestartInterval).GetAwaiter().GetResult(); } } while (!_stopped && !cancellationToken.IsCancellationRequested); }
private static async Task StopAndDisposeAsync(ScriptHost instance) { try { await instance.StopAsync(); } catch { // best effort } finally { instance.Dispose(); } }
/// <summary> /// Remove the <see cref="ScriptHost"/> instance from the live instances collection, /// allowing it to finish currently executing functions before stopping and disposing of it. /// </summary> /// <param name="instance">The <see cref="ScriptHost"/> instance to remove</param> /// <param name="forceStop">Forces the call to stop and dispose of the instance, even if it isn't present in the live instances collection.</param> /// <returns></returns> private async Task Orphan(ScriptHost instance, bool forceStop = false) { lock (_liveInstances) { bool removed = _liveInstances.Remove(instance); if (!forceStop && !removed) { return; // somebody else is handling it } } try { // this thread now owns the instance if (instance.TraceWriter != null) { instance.TraceWriter.Info("Stopping Host"); } await instance.StopAsync(); } finally { instance.Dispose(); } }
private static void LogErrors(ScriptHost host) { if (host.FunctionErrors.Count > 0) { StringBuilder builder = new StringBuilder(); builder.AppendLine(string.Format(CultureInfo.InvariantCulture, "The following {0} functions are in error:", host.FunctionErrors.Count)); foreach (var error in host.FunctionErrors) { string functionErrors = string.Join(Environment.NewLine, error.Value); builder.AppendLine(string.Format(CultureInfo.InvariantCulture, "{0}: {1}", error.Key, functionErrors)); } host.TraceWriter.Error(builder.ToString()); } }
// Let the existing host instance finish currently executing functions. private async Task Orphan(ScriptHost instance) { lock (_liveInstances) { bool removed = _liveInstances.Remove(instance); if (!removed) { return; // somebody else is handling it } } // this thread now owns the instance await instance.StopAsync(); instance.Dispose(); }
public void RunAndBlock(CancellationToken cancellationToken = default(CancellationToken)) { // Start the host and restart it if requested. Host Restarts will happen when // host level configuration files change do { ScriptHost newInstance = null; try { IsRunning = false; // Create a new host config, but keep the host id from existing one _config.HostConfig = new JobHostConfiguration { HostId = _config.HostConfig.HostId }; OnInitializeConfig(_config.HostConfig); newInstance = _scriptHostFactory.Create(_config); _traceWriter = newInstance.TraceWriter; newInstance.StartAsync(cancellationToken).Wait(); // write any function initialization errors to the log file LogErrors(newInstance); lock (_liveInstances) { _liveInstances.Add(newInstance); } _currentInstance = newInstance; OnHostStarted(); // only after ALL initialization is complete do we set this flag IsRunning = true; LastError = null; // Wait for a restart signal. This event will automatically reset. // While we're restarting, it is possible for another restart to be // signaled. That is fine - the restart will be processed immediately // once we get to this line again. The important thing is that these // restarts are only happening on a single thread. WaitHandle.WaitAny(new WaitHandle[] { cancellationToken.WaitHandle, newInstance.RestartEvent, _stopEvent }); // Orphan the current host instance. We're stopping it, so it won't listen for any new functions // it will finish any currently executing functions and then clean itself up. // Spin around and create a new host instance. Task taskIgnore = Orphan(newInstance); } catch (Exception ex) { IsRunning = false; LastError = ex; // We need to keep the host running, so we catch and log any errors // then restart the host if (_traceWriter != null) { _traceWriter.Error("A ScriptHost error occurred", ex); } // If a ScriptHost instance was created before the exception was thrown // Orphan and cleanup that instance. if (newInstance != null) { Orphan(newInstance, forceStop: true) .ContinueWith(t => { if (t.IsFaulted) { t.Exception.Handle(e => true); } }); } // Wait for a short period of time before restarting to // avoid cases where a host level config error might cause // a rapid restart cycle Task.Delay(5000).Wait(); } } while (!_stopped && !cancellationToken.IsCancellationRequested); }
public void RunAndBlock(CancellationToken cancellationToken = default(CancellationToken)) { // Start the host and restart it if requested. Host Restarts will happen when // host level configuration files change do { ScriptHost newInstance = null; try { IsRunning = false; // Create a new host config, but keep the host id from existing one _config.HostConfig = new JobHostConfiguration { HostId = _config.HostConfig.HostId }; OnInitializeConfig(_config.HostConfig); newInstance = _scriptHostFactory.Create(_config); _traceWriter = newInstance.TraceWriter; newInstance.StartAsync(cancellationToken).Wait(); // write any function initialization errors to the log file LogErrors(newInstance); lock (_liveInstances) { _liveInstances.Add(newInstance); } _currentInstance = newInstance; OnHostStarted(); // only after ALL initialization is complete do we set this flag IsRunning = true; LastError = null; // Wait for a restart signal. This event will automatically reset. // While we're restarting, it is possible for another restart to be // signaled. That is fine - the restart will be processed immediately // once we get to this line again. The important thing is that these // restarts are only happening on a single thread. WaitHandle.WaitAny(new WaitHandle[] { cancellationToken.WaitHandle, newInstance.RestartEvent, _stopEvent }); // Orphan the current host instance. We're stopping it, so it won't listen for any new functions // it will finish any currently executing functions and then clean itself up. // Spin around and create a new host instance. Task taskIgnore = Orphan(newInstance); } catch (Exception ex) { IsRunning = false; LastError = ex; // We need to keep the host running, so we catch and log any errors // then restart the host if (_traceWriter != null) { _traceWriter.Error("A ScriptHost error occurred", ex); } // If a ScriptHost instance was created before the exception was thrown // Orphan and cleanup that instance. if (newInstance != null) { Orphan(newInstance, forceStop: true) .ContinueWith(t => { if (t.IsFaulted) { t.Exception.Handle(e => true); } }); } // Wait for a short period of time before restarting to // avoid cases where a host level config error might cause // a rapid restart cycle Task.Delay(5000).Wait(); } }while (!_stopped && !cancellationToken.IsCancellationRequested); }
public ScriptHost Create(IScriptHostEnvironment environment, IScriptEventManager eventManager, ScriptSettingsManager settingsManager, ScriptHostConfiguration config) { return(ScriptHost.Create(environment, eventManager, config, settingsManager)); }