internal void RegisterCompletionOf(Job job) { Log.DispatcherActivity(Settings.DispatcherId, DispatcherActivity.JobWasCompleted, job, job.ExecutionStatus, job.ExecutionStatus); }
internal void RepublishAsPending(Job job) { Republish(job, JobStatus.Pending); }
internal void RepublishAsFailed(Job job) { Republish(job, JobStatus.Failed); }
public bool HasExecutingWorkerFor(Job job) { lock (ExecutingWorkers) { IWorker worker; if (ExecutingWorkers.TryGetValue(job.WorkerId, out worker)) { return worker.IsExecuting(job); } } return false; }
public bool IsWaitingForCompletionOf(Job job) { if (job.WorkerId == null) return false; lock (ExecutingWorkers) { IWorker worker; if (ExecutingWorkers.TryGetValue(job.WorkerId, out worker)) { return worker.HasCompletionCallback(); } } return false; }
public void Execute(Job job, Action<Job> completionCallback, CancellationTokenSource cancellationTokenSource) { ExecutingJob = job; CompletionCallback = completionCallback; CancellationTokenSource = cancellationTokenSource; bool executionSucceeded; var hasTimedOut = false; var succeeded = false; try { ExecutingJob.ExecutionStatus = JobStatus.Processing; PublishingBus.Publish(JobStatus.Processing.TopicId(), ExecutingJob, StorageType.NonPersistent); // Tenta executar o trabalho executionSucceeded = TryExecuteWithTimeout(); // Após executar, checa se não demorou mais tempo que o permitido para concluir a execução hasTimedOut = ExecutingJob.HasTimedOut(); // Se a execução foi bem sucedida e se não demorou tempo demais, // marca para consolidar as alterações de estado e publicar os eventos decorrentes da conclusão da execução com sucesso if (executionSucceeded && !hasTimedOut) succeeded = true; } catch (ThreadAbortException threadAbortException) { // ThreadAbortException ocorrerá caso o Dispatcher em que o Worker está rodando seja finalizado, // portanto deve ser ignorado e considerado como uma execução não completada ExecutingJob.ExecutionException = threadAbortException; executionSucceeded = false; succeeded = false; } catch (Exception executionException) { // Se houve exceção, armazena na solicitação de trabalho para posterior análise ExecutingJob.ExecutionException = executionException; executionSucceeded = false; succeeded = false; Log.Error(executionException, String.Format("Error when trying to execute {0}!", GetType().Name)); } // Se demorou demais para concluir a execução if (hasTimedOut) { // Um trabalho que não concluiu em tempo é considerado um trabalho que falhou ExecutingJob.ExecutionStatus = JobStatus.Failed; Timeout(); } // Se a execução concluiu dentro do tempo esperado else { // Armazena o resultado da execução para posterior análise ExecutingJob.ExecutionStatus = executionSucceeded ? JobStatus.Succeeded : JobStatus.Failed; } // Consolida ou cancela as alterações de estado decorrentes da execução do trabalho if (succeeded) { PublishingBus.Publish(JobStatus.Succeeded.TopicId(), ExecutingJob, StorageType.NonPersistent); Complete(); } else if (!hasTimedOut) { PublishingBus.Publish(JobStatus.Failed.TopicId(), ExecutingJob, StorageType.NonPersistent); Fail(); } // Executa callback de confirmação da execução if (HasCompletionCallback()) CompletionCallback(ExecutingJob); }
private void FailJobExecution(Job job) { if (job.ExecutionException != null) { Log.DispatcherActivity( Repository.Settings.DispatcherId, DispatcherActivity.BackgroundThreadException, job, JobStatus.Failed, JobStatus.Failed ); } Repository.RepublishAsFailed(job); }
private static IWorker NewWorkerFor(Job job) { var worker = DependencyResolver.Get<Worker>(job.WorkerType); return worker; }
private void ProcessAsCompleted(Job job) { Repository.RegisterCompletionOf(job); switch (job.ExecutionStatus) { case JobStatus.Succeeded: break; case JobStatus.Failed: CheckIfShallRepeatOrLogTheExecutionOf(job); break; default: Debug.Fail(String.Format("Invalid execution status for work request {0}", job.MessageId)); break; } }
private IWorker InitializeWorkerAndJob(Job job) { var worker = NewWorkerFor(job); Debug.Assert(worker != null, "worker != null"); job.WorkerId = worker.WorkerId; lock (ExecutingWorkers) { ExecutingWorkers[job.WorkerId] = worker; } //Repository.SubscribeToWorkerLifeSignal(job.WorkerId); return worker; }
private void ExecuteJob(Job job, IWorker worker) { try { Log.Debug("Dispatching {0} to {1}", job.GetType().FullName, worker.GetType().FullName); worker.Execute(job, ProcessAsCompleted, CancellationTokenForExecutionOfJob); } finally { FinalizeWorker(worker); } }
private static void ApplyConfigurationToJob(Job job, JobConfiguration configuration) { job.RequestMaxAttempts = configuration.RequestMaxAttempts; job.RequestTimeout = configuration.RequestTimeout; job.ProcessingAttempts += 1; job.RequestMaxTime = configuration.RequestTimeout == Timeout.InfiniteTimeSpan ? Timeout.InfiniteTimeSpan : TimeSpan.FromSeconds(configuration.RequestTimeout.TotalSeconds * configuration.RequestMaxAttempts); job.WorkerType = configuration.JobAndWorkerType.WorkerType.Type; }
private void DispatchJob(Job job) { var configuration = Repository.Settings.JobConfigurations.Single(c => c.JobAndWorkerType.JobType.Type == job.GetType()); ApplyConfigurationToJob(job, configuration); var worker = InitializeWorkerAndJob(job); Log.DispatcherActivity(Repository.Settings.DispatcherId, DispatcherActivity.JobWasDispatched, job, job.ExecutionStatus, job.ExecutionStatus); ExecuteJob(job, worker); }
private void ReceiveJob(Job job) { // Since ReceiveJob is called asyncronously, this lock avoid reentrance while processing a received work request lock (ReceivingJobLock) { Log.DispatcherActivity(Repository.Settings.DispatcherId, DispatcherActivity.JobWasReceived, job, job.ExecutionStatus, job.ExecutionStatus); DispatchJob(job); } }
private void Republish(Job job, JobStatus newRequestStatus) { var oldRequestStatus = job.ExecutionStatus; job.ExecutionStatus = newRequestStatus; Log.DispatcherActivity(Settings.DispatcherId, DispatcherActivity.JobWasRepublished, job, oldRequestStatus, newRequestStatus); PublishingBus.Publish(newRequestStatus.TopicId(), job); }
private void CheckIfShallRepeatOrLogTheExecutionOf(Job job) { switch (job.FailureAction) { case JobFailureAction.Repeat: if (job.HasExceededMaxAttempts()) FailJobExecution(job); else { Repository.RepublishAsPending(job); } break; case JobFailureAction.Log: FailJobExecution(job); break; } }
internal static void DispatcherActivity(this Logger log, DispatcherId dispatcherId, DispatcherActivity activity, Job job, JobStatus oldStatus, JobStatus? newStatus = null) { var logEntry = new DispatcherActivityLogEntry { DispatcherId = dispatcherId, Activity = activity, Job = job, OldStatus = oldStatus, NewStatus = newStatus ?? oldStatus }; log.Info(logEntry); }
public bool IsExecuting(Job job) { return ExecutingJob == job; }