/// <summary> /// Reschedules the job instance if it's a recurring job. /// </summary> /// <returns>The new job instance that is in the queue now.</returns> /// <remarks> /// The completed job is marked as completed and is stored for reference, so a new /// job instance is created with updated properties. /// </remarks> public JobInstance RescheduleIfRecurring() { if ((jobExecutionStatus == Registry.JobExecutionState.Completed || jobExecutionStatus == Registry.JobExecutionState.Failed || jobExecutionStatus == Registry.JobExecutionState.Cancelled) && scheduleType == ScheduleType.Recurring) { // Create a copy first JobInstance newjob = new JobInstance(this); // Reset properties newjob.Guid = Guid.Empty; newjob.Name = GenerateRecurringJobID(); newjob.dateStarted = DateTime.MinValue; newjob.dateFinished = DateTime.MinValue; newjob.JobExecutionStatus = JobExecutionState.Scheduled; newjob.ScheduleTime = GetNextScheduleTime(); newjob.workflowInstanceId = Guid.Empty; newjob.adminRequestTime = DateTime.MinValue; newjob.adminRequestData = null; newjob.adminRequestResult = -1; newjob.exceptionMessage = null; // Save new job newjob.Save(); return(newjob); } else { return(null); } }
/// <summary> /// Starts a single job /// </summary> /// <param name="job"></param> private void StartOrResumeJob(Job job) { AppDomainHost adh = null; using (Context context = ContextManager.Instance.CreateContext(ConnectionMode.AutoOpen, TransactionMode.AutoCommit)) { context.JobGuid = job.Guid; context.ContextGuid = contextGuid; JobInstance ji = new JobInstance(context); ji.Guid = job.Guid; ji.Load(); // Lock the job, so noone else can pick it up ji.DateStarted = DateTime.Now; ji.ObtainLock(); ji.Save(); } // Schedule job in the appropriate app domain adh = GetOrCreateAppDomainHost(job); // Check if job is a new instance or previously persisted and // has to be resumed switch (job.Status) { case JobStatus.Starting: if (interactive) { Console.WriteLine("Starting job: {0}", job.Guid); } job.WorkflowInstanceId = adh.PrepareStartJob(job); break; case JobStatus.Resuming: if (interactive) { Console.WriteLine("Resuming job: {0}", job.Guid); } job.WorkflowInstanceId = adh.PrepareResumeJob(job); break; default: throw new NotImplementedException(); } // Update job status job.TimeStarted = DateTime.Now; job.Status = JobStatus.Executing; job.AppDomainID = adh.ID; // TODO: this has to happen before starting the job lock (runningJobs) { runningJobs.Add(job.WorkflowInstanceId, job); } adh.RunJob(job); }
private void PersistJob(Job job) { using (Context context = ContextManager.Instance.CreateContext(ConnectionMode.AutoOpen, TransactionMode.AutoCommit)) { context.JobGuid = job.Guid; context.ContextGuid = contextGuid; var ji = new JobInstance(context); ji.Guid = job.Guid; ji.Load(); // Update registry ji.JobExecutionStatus = JobExecutionState.Persisting; ji.Save(); } // Update job status job.Status = JobStatus.Persisted; appDomains[job.AppDomainID].PersistJob(job); }
/// <summary> /// Finished the execution of a job and records the results in the registry. /// </summary> /// <param name="workflowInstanceId"></param> /// <param name="eventType"></param> private void FinishJob(Job job, HostEventArgs e) { using (Context context = ContextManager.Instance.CreateContext(ConnectionMode.AutoOpen, TransactionMode.AutoCommit)) { context.JobGuid = job.Guid; context.ContextGuid = contextGuid; JobInstance ji = new JobInstance(context); ji.Guid = job.Guid; ji.Load(); // Update execution status, error message and finish time switch (e.EventType) { case WorkflowEventType.Completed: ji.JobExecutionStatus = JobExecutionState.Completed; break; case WorkflowEventType.Cancelled: ji.JobExecutionStatus = JobExecutionState.Cancelled; break; case WorkflowEventType.TimedOut: ji.JobExecutionStatus = JobExecutionState.TimedOut; break; case WorkflowEventType.Persisted: ji.JobExecutionStatus = JobExecutionState.Persisted; break; case WorkflowEventType.Failed: ji.JobExecutionStatus = JobExecutionState.Failed; ji.ExceptionMessage = e.ExceptionMessage; break; } // Update registry ji.DateFinished = DateTime.Now; ji.Save(); ji.ReleaseLock(false); ji.RescheduleIfRecurring(); // Do local bookkeeping lock (runningJobs) { lock (Cluster.Queues[job.QueueGuid].Jobs) { Cluster.Queues[job.QueueGuid].Jobs.Remove(job.Guid); } runningJobs.Remove(job.WorkflowInstanceId); } if (interactive) { Console.WriteLine("Finishing job: {0}", ji.Guid); } } }
private void CancelOrTimeOutJob(Job job, bool timeout) { using (Context context = ContextManager.Instance.CreateContext(ConnectionMode.AutoOpen, TransactionMode.AutoCommit)) { context.JobGuid = job.Guid; context.ContextGuid = contextGuid; var ji = new JobInstance(context); ji.Guid = job.Guid; ji.Load(); // Update registry ji.JobExecutionStatus = JobExecutionState.Cancelling; ji.Save(); } // Update job status if (timeout) { job.Status = JobStatus.TimedOut; appDomains[job.AppDomainID].TimeOutJob(job); } else { job.Status = JobStatus.Cancelled; appDomains[job.AppDomainID].CancelJob(job); } }
/// <summary> /// Reschedules the job instance if it's a recurring job. /// </summary> /// <returns>The new job instance that is in the queue now.</returns> /// <remarks> /// The completed job is marked as completed and is stored for reference, so a new /// job instance is created with updated properties. /// </remarks> public JobInstance RescheduleIfRecurring() { if ((jobExecutionStatus == Registry.JobExecutionState.Completed || jobExecutionStatus == Registry.JobExecutionState.Failed || jobExecutionStatus == Registry.JobExecutionState.Cancelled) && scheduleType == ScheduleType.Recurring) { // Create a copy first JobInstance newjob = new JobInstance(this); // Reset properties newjob.Guid = Guid.Empty; newjob.Name = GenerateRecurringJobID(); newjob.dateStarted = DateTime.MinValue; newjob.dateFinished = DateTime.MinValue; newjob.JobExecutionStatus = JobExecutionState.Scheduled; newjob.ScheduleTime = GetNextScheduleTime(); newjob.workflowInstanceId = Guid.Empty; newjob.adminRequestTime = DateTime.MinValue; newjob.adminRequestData = null; newjob.adminRequestResult = -1; newjob.exceptionMessage = null; // Save new job newjob.Save(); return newjob; } else { return null; } }