/// <summary> /// Adds or updates the handler with the given job script /// </summary> public AddJobScriptResult Add(JobScriptInfo jobScriptInfo) { // Prepare the info object var addResult = new AddJobScriptResult(); // Parse the content var jobScriptFile = JobScriptFileParser.Parse(jobScriptInfo.JobScript); if (jobScriptFile.ParsingFailed) { Logger.Error("Failed to parse job script: {0}", jobScriptFile.ErrorMessage); addResult.SetError(AddJobScriptError.ParsingFailed, jobScriptFile.ErrorMessage); return(addResult); } // Compile the job file var compileResult = JobScriptCompiler.Compile(jobScriptFile, _packageManager.GetPackagePath(jobScriptFile.PackageName)); // Check for compilation error if (compileResult.ResultType == CompileResultType.Failed) { Logger.Error("Failed to compile job script: {0}", compileResult.ErrorString); addResult.SetError(AddJobScriptError.CompilationFailed, compileResult.ErrorString); return(addResult); } // Check if it already was compiled if (compileResult.ResultType == CompileResultType.AlreadyCompiled) { Logger.Info("Job script already exists"); } // Get the settings from the job file HandlerSettings handlerSettings; var readScuccess = JobFileHandlerSettingsReader.ReadSettingsInOwnDomain(compileResult.OutputAssembly, out handlerSettings); if (!readScuccess) { Logger.Error("Initializer type not found"); addResult.SetError(AddJobScriptError.HandlerInitializerMissing, "Handler initializer type not found"); return(addResult); } // Search for an already existing handler var currentFullName = Helpers.BuildFullName(jobScriptFile.PackageName, handlerSettings.HandlerName, handlerSettings.JobName); HandlerInstance handlerInstance = null; lock (_loadedHandlers.GetSyncRoot()) { bool foundExisting = false; foreach (var handler in _loadedHandlers) { if (handler.Value.FullName == currentFullName) { // Found an existing same handler handlerInstance = handler.Value; foundExisting = true; break; } } if (!foundExisting) { // No handler instance found, create a new one handlerInstance = new HandlerInstance(Logger, _packageManager); _loadedHandlers.Add(handlerInstance.Id, handlerInstance); } // Initialize/update the values var replaced = handlerInstance.InitializeFromJobScript(jobScriptFile, compileResult.OutputAssembly, handlerSettings); if (foundExisting) { if (replaced) { addResult.SetOk(handlerInstance.Id, AddJobScriptStatus.JobScriptReplaced); Logger.Info(entry => entry.SetHandlerId(handlerInstance.Id), "Updated jobscript"); } else { addResult.SetOk(handlerInstance.Id, AddJobScriptStatus.NoUpdateNeeded); Logger.Info(entry => entry.SetHandlerId(handlerInstance.Id), "No jobscript update needed"); } return(addResult); } } // Autostart if wanted if (handlerInstance.HandlerSettings.AutoStart) { Start(handlerInstance.Id); } // Fill the info object from the result addResult.SetOk(handlerInstance.Id, AddJobScriptStatus.Ok); Logger.Info(entry => entry.SetHandlerId(handlerInstance.Id), "Added", handlerInstance.Id); return(addResult); }
/// <summary> /// Initializes the handler and everything it needs to run /// </summary> public JobScriptInitializeResult InitializeAndStart(RunningHandlerInitializeParams runningHandlerInitializeParams) { // Initialization _jobScriptHash = runningHandlerInitializeParams.JobHash; var packageName = runningHandlerInitializeParams.PackageName; var currentPackageFolder = _packageManager.GetPackagePath(packageName); // Preparations var result = new JobScriptInitializeResult(); // Assign the path to the output assembly var jobAssemblyPath = runningHandlerInitializeParams.JobAssemblyPath; // Read the settings IHandlerCustomSettings customSettings; JobFileHandlerSettingsReader.LoadAssemblyAndReadSettings(jobAssemblyPath, out _handlerSettings, out customSettings); // Read the package information object var packageInfo = _packageManager.GetInfo(packageName); // Search for the correct handler type in the given assemblies Type handlerType = null; foreach (var handlerAssemblyName in packageInfo.HandlerAssemblies) { // Load the assembly var handlerAssemblyPath = Path.Combine(currentPackageFolder, handlerAssemblyName); var handlerAssembly = AppDomain.CurrentDomain.Load(AssemblyName.GetAssemblyName(handlerAssemblyPath)); // Try loading the from the assembly Type[] types; try { types = handlerAssembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { result.SetError(AddJobScriptError.TypeException, ex.LoaderExceptions.First().Message); return(result); } // Search for the correct handler type foreach (var type in types) { if (typeof(IHandler).IsAssignableFrom(type)) { var att = type.GetCustomAttribute <HandlerNameAttribute>(true); if (att != null) { if (att.HandlerName == _handlerSettings.HandlerName) { handlerType = type; break; } } } } if (handlerType != null) { break; } } if (handlerType == null) { result.SetError(AddJobScriptError.JobScriptMissing, String.Format("Handler type for handler '{0}' not found", _handlerSettings.HandlerName)); return(result); } // Initialize the handler var handlerInstance = (IHandler)Activator.CreateInstance(handlerType); // Initialize the handler with the custom settings handlerInstance.InitializeCustomSettings(customSettings); // Attach to the logger handlerInstance.Logger.LogEvent += (sender, args) => Logger.Log(args.LogEntry.SetHandlerId(Id)); // Call the virtual initialize method handlerInstance.Initialize(); // Event when a job was added handlerInstance.EnqueueJobEvent += EnqueueJob; // Assign the handler _handler = handlerInstance; // Start the control thread _controlTaskCancelToken = new CancellationTokenSource(); _controlTask = new Task(ControlThread, _controlTaskCancelToken.Token); _controlTask.ContinueWith(t => { Logger.Fatal(t.Exception, "Handler: '{0}' has exception", Id); TearDown(true); OnStateChangedEvent(new RunningHandlerStateChangedEventArgs(RunningHandlerState.Failed)); }, TaskContinuationOptions.OnlyOnFaulted); _controlTask.Start(); // Notify the start event _handler.OnStart(); // Fill and return the info object result.HandlerId = Id; return(result); }