/// <summary> /// Schedules the service app process. /// </summary> /// <param name="process">The process to schedule.</param> /// <returns> /// Any errors that occured when trying to create the schedule. /// </returns> /// <exception cref="System.InvalidOperationException">Cannot schedule an uninitialized ServiceApp.</exception> public string ScheduleServiceApp(ServiceAppProcess process) { if (!process.IsProcessRunning) { throw new InvalidOperationException("Cannot schedule a service app that has not been started."); } string errorMessage = string.Empty; string appName = process.ServiceApp.Name; if (process.ServiceApp.StartupTypeEnum == StartupType.Automatic) { if (string.IsNullOrEmpty(process.ServiceApp.Schedule)) { process.AddMessage(ServiceAppMessages.InvalidSchedule, ServiceAppState.Error); errorMessage = string.Format("Schedule for service app '{0}' was not defined", appName); } else if (!HasJob(appName)) { AddJob(appName, process.ServiceApp.Schedule, () => { process.ExecuteServiceApp(); }); } } else if (process.ServiceApp.StartupTypeEnum != StartupType.Manual) { errorMessage = string.Format("Cannot start '{0}'. The service app is disabled. Please enable the service app first before scheduling.", appName); } return(errorMessage); }
/// <summary> /// Removes the specified service app from the container. /// </summary> /// <param name="appName">Name of the application.</param> /// <param name="dao">The DAO.</param> /// <param name="appListDao">The application list DAO.</param> /// <exception cref="System.IndexOutOfRangeException">The app name could not be found.</exception> /// <exception cref="System.InvalidOperationException">The ServiceApp was not stopped first.</exception> public void RemoveServiceApp(string appName, IServiceAppDao dao, IAppListDao appListDao) { ServiceAppProcess process = ServiceAppProcesses[appName]; if (process != null) { if (process.IsProcessRunning) { throw new InvalidOperationException(string.Format("ServiceApp '{0}' must be stopped before it can be updated or removed.", appName)); } ServiceAppProcesses.Remove(process); // This will prevent leaks process.Started -= ServiceAppProcess_Started; process.Error -= ServiceAppProcess_Error; process.Executed -= ServiceAppProcess_Executed; process.Performance -= ServiceAppProcess_Performance; process.Stopped -= ServiceAppProcess_Stopped; } if (appListDao != null) { appListDao.DeleteServiceApp(appName); } if (dao != null) { dao.DeleteServiceApp(appName); } }
public void Start_ServiceAppProcessCanStartSucessfully() { ILog log = Substitute.For <ILog>(); bool monitorMethodCalled = false; IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>(); procFactory.CreateProcess().Returns(new FakeStandardProcess()); var serviceApp = new ServiceApp { Name = "Test", AppVersion = new Version() }; ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory); appProcToTest.MonitorProcessCallback = () => { monitorMethodCalled = true; }; Task t = appProcToTest.Start(); bool success = t.Wait(500); if (!success) { Assert.Fail("Start() took too long to finish"); } log.DidNotReceive().Error(Arg.Any <object>(), Arg.Any <Exception>()); log.DidNotReceive().Warn(Arg.Any <object>(), Arg.Any <Exception>()); Assert.IsTrue(monitorMethodCalled, "MonitorProcessCallback() not called."); }
/// <summary> /// Loads the service app which should be added to the pool of service apps. /// </summary> /// <param name="appName">Name of the application.</param> /// <param name="dao">The DAO.</param> /// <returns>A string containing an error message if a recoverable error occured.</returns> /// <exception cref="System.IndexOutOfRangeException">The ServiceApp could not be found in the container.</exception> /// <exception cref="System.InvalidOperationException">The ServiceApp is not in a stopped state.</exception> public string InitializeServiceApp(string appName, IServiceAppDao dao) { ServiceAppProcess process = this.ServiceAppProcesses[appName]; if (process == null) { var e = new IndexOutOfRangeException(string.Format("ServiceApp '{0}' could not be found to initialize.", appName)); this._log.Error("Error in InitializeServiceApp", e); throw e; } else if (process.IsProcessRunning) { var e = new InvalidOperationException(string.Format("ServiceApp '{0}' must be stopped before it can be reinitialized.", appName)); this._log.Error("Error in InitializeServiceApp", e); throw e; } if (process.ServiceApp.StartupTypeEnum != StartupType.Disabled) { process.Start(); return(string.Empty); } else { return(string.Format("ServiceApp '{0}' is disabled", appName)); } }
public void ProcessError_LoggingWorksWithUnrecognizedExceptionObject() { ILog log = Substitute.For <ILog>(); IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>(); procFactory.CreateProcess().Returns(new FakeStandardProcess()); var serviceApp = new ServiceApp { Name = "Test", AppVersion = new Version() }; ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory); Exception testException = new InvalidOperationException("test"); string exceptionMessage = string.Format(@"{{ error: {{ details: {{ type: ""{0}"", message: ""{1}"", source: ""{2}"", stackTrace: ""{3}"" }}, exception: ""xxxxx"" }} }}", testException.GetType().ToString(), testException.Message, testException.Source, testException.StackTrace); bool shouldExit = appProcToTest.ProcessMessage(exceptionMessage); log.Received().Warn(Arg.Any <string>()); Assert.IsFalse(shouldExit, "Process message was not meant to return true"); }
public void Remove_CannotRemoveDomainFromEmptyCollection() { ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer()); ServiceAppProcess saProc = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); bool success = collection.Remove(saProc); Assert.IsFalse(success); }
public void Add_CanInsertUniqueDomainToCollection() { ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer()); ServiceAppProcess saProc = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); collection.Add(saProc); Assert.AreEqual(1, collection.Count); }
public void GetIndex_CanReturnServiceAppProcessFromCollectionUsingString() { ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer()); ServiceAppProcess saProc = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); collection.Add(saProc); Assert.AreEqual(saProc, collection["__Test"]); }
public void Remove_CanRemoveInstalledDomainFromCollection() { ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer()); ServiceAppProcess saProc = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); collection.Add(saProc); bool success = collection.Remove(saProc); Assert.IsTrue(success); }
public void Constructor_ServiceAppProcessConstructorHasNoSurprises() { IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>(); procFactory.CreateProcess().Returns(new FakeStandardProcess()); ServiceAppProcess appProcToTest = new ServiceAppProcess( new ServiceApp { Name = "Test" }, Substitute.For <ILog>(), procFactory); }
/// <summary> /// Stops the specified service app. /// </summary> /// <param name="appName">Name of the application.</param> /// <param name="dao">The DAO.</param> /// <param name="isExiting">Set to <c>true</c> if the service is in the middle of exiting.</param> /// <exception cref="System.IndexOutOfRangeException">The app name could not be found.</exception> public void StopServiceApp(string appName, IServiceAppDao dao, bool isExiting) { ServiceAppProcess process = this.ServiceAppProcesses[appName]; if (process == null) { var e = new IndexOutOfRangeException(string.Format("appName '{0}' could not be found to stop.", appName)); this._log.Error("Error in StopServiceApp", e); } else { process.Stop(isExiting); _schedulingService.RemoveJob(appName); dao.RecordServiceAppStop(appName); } }
public void ProcessMessage_DebugIsLogged() { ILog log = Substitute.For <ILog>(); IProcessWrapperFactory procFactory = Substitute.For <IProcessWrapperFactory>(); procFactory.CreateProcess().Returns(new FakeStandardProcess()); var serviceApp = new ServiceApp { Name = "Test", AppVersion = new Version() }; ServiceAppProcess appProcToTest = new ServiceAppProcess(serviceApp, log, procFactory); bool shouldExit = appProcToTest.ProcessMessage("{debug:\"test\"}"); log.Received().Debug("From Test: test"); Assert.IsFalse(shouldExit, "Process message was not meant to return true"); }
/// <summary> /// Runs the service application immediately. /// </summary> /// <param name="appName">Name of the application.</param> public void RunServiceApp(string appName) { string errorMessage = string.Empty; ServiceAppProcess process = this.ServiceAppProcesses[appName]; if (process == null) { throw new IndexOutOfRangeException(string.Format("ServiceApp '{0}' could not be found to execute.", appName)); } else if (!process.IsProcessRunning) { throw new InvalidOperationException(string.Format("ServiceApp '{0}' must be started before it can be run.", appName)); } // run the service app as if the timer elapsed process.ExecuteServiceApp(); }
/// <summary> /// Adds the service app to the container or updates it if it already exists and saves it to the AppList configuration. /// </summary> /// <param name="app">The application.</param> /// <param name="dao">The DAO.</param> /// <param name="appListDao">The application list DAO.</param> /// <exception cref="System.InvalidOperationException">The service app is added and is still running.</exception> public string SyncServiceApp(ServiceApp app, IServiceAppDao dao, IAppListDao appListDao) { string errorMessage = string.Empty; this.RemoveServiceApp(app.Name, dao); ServiceAppProcess process = _serviceAppFactory.CreateServiceAppProcess(app, this._log); try { this.ServiceAppProcesses.Add(process); process.EntropyValue = dao.SaveServiceApp(app); if (appListDao != null) { try { appListDao.PersistServiceApp(app); } catch (Exception e) { this._log.Error(string.Format("{0} could not be saved to AppList", app.Name), e); errorMessage = string.Format("ServiceApp '{0}' could not be saved to the configuration.", app.Name); } } process.Started += ServiceAppProcess_Started; process.Error += ServiceAppProcess_Error; process.Executed += ServiceAppProcess_Executed; process.Performance += ServiceAppProcess_Performance; process.Stopped += ServiceAppProcess_Stopped; } catch (ArgumentException) { errorMessage = string.Format("ServiceApp '{0}' is already added.", app.Name); } return(errorMessage); }
public void Add_CannotAddDuplicateDomainToCollection() { ServiceAppProcessCollection collection = new ServiceAppProcessCollection(new ServiceAppProcessComparer()); ServiceAppProcess saProc1 = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); ServiceAppProcess saProc2 = _serviceAppProcessFactory.CreateServiceAppProcess(null, null); collection.Add(saProc1); try { collection.Add(saProc2); Assert.Fail("Able to add duplicate domain."); } catch (AssertionException) { throw; } catch { Assert.AreEqual(1, collection.Count); } }
/// <summary> /// Handles the Started event of the ServiceAppProcess object. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void ServiceAppProcess_Started(object sender, EventArgs e) { // TODO: this is so bad! but there's a bug here that disappeared as soon as I added this :( try { string errorMessage = string.Empty; ServiceAppProcess process = sender as ServiceAppProcess; if (process != null) { if (process.IsProcessRunning) { using (var dao = _daoFactory.Create <IServiceAppDao>()) { dao.RecordServiceAppStart(process.ServiceApp.Name); } if (process.ServiceApp.StartupTypeEnum == StartupType.Automatic) { errorMessage = _schedulingService.ScheduleServiceApp(process); } } else { errorMessage = string.Format("Failed to initialize ServiceApp '{0}'", process.ServiceApp.Name); } } if (!string.IsNullOrWhiteSpace(errorMessage)) { this._log.Warn(errorMessage); } } catch (Exception ex) { _log.Error("ServiceAppProcess_Started event failed", ex); } }