private IState PerformJob(BackgroundProcessContext context, IStorageConnection connection, string jobId) { try { var jobData = connection.GetJobData(jobId); if (jobData == null) { // Job expired just after moving to a processing state. This is an // unreal scenario, but shit happens. Returning null instead of throwing // an exception and rescuing from en-queueing a poisoned jobId back // to a queue. return(null); } jobData.EnsureLoaded(); var backgroundJob = new BackgroundJob(jobId, jobData.Job, jobData.CreatedAt); using (var jobToken = new ServerJobCancellationToken(connection, jobId, context.ServerId, context.ExecutionId.ToString(), context.StoppedToken)) { var performContext = new PerformContext(context.Storage, connection, backgroundJob, jobToken, _profiler); var latency = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds; var duration = Stopwatch.StartNew(); var result = _performer.Perform(performContext); duration.Stop(); return(new SucceededState(result, (long)latency, duration.ElapsedMilliseconds)); } } catch (JobAbortedException) { // Background job performance was aborted due to a // state change, so its identifier should be removed // from a queue. return(null); } catch (JobPerformanceException ex) { return(new FailedState(ex.InnerException) { Reason = ex.Message }); } catch (Exception ex) { if (ex is OperationCanceledException && context.IsStopped) { throw; } return(new FailedState(ex) { Reason = "An exception occurred during processing of a background job." }); } }
public object Perform(PerformContext context) { var requestTelemetry = new RequestTelemetry() { Name = $"JOB {context.BackgroundJob.Job.Type.Name}.{context.BackgroundJob.Job.Method.Name}", }; // Track Hangfire Job as a Request (operation) in AI var operation = _telemetryClient.StartOperation( requestTelemetry ); try { requestTelemetry.Properties.Add( "JobId", context.BackgroundJob.Id ); requestTelemetry.Properties.Add( "JobCreatedAt", context.BackgroundJob.CreatedAt.ToString("O") ); try { requestTelemetry.Properties.Add( "JobArguments", System.Text.Json.JsonSerializer.Serialize(context.BackgroundJob.Job.Args) ); } catch { operation.Telemetry.Properties.Add("JobArguments", "Failed to serialize type"); } var result = _inner.Perform(context); requestTelemetry.Success = true; requestTelemetry.ResponseCode = "Success"; return(result); } catch (Exception exception) { requestTelemetry.Success = false; requestTelemetry.ResponseCode = "Failed"; _telemetryClient.TrackException(exception); throw; } finally { _telemetryClient.StopOperation(operation); } }
private object PerformJobWithFilters(PerformContext context, IEnumerable <IServerFilter> filters) { object result = null; var preContext = new PerformingContext(context); Func <PerformedContext> continuation = () => { result = _innerPerformer.Perform(context); return(new PerformedContext(context, result, false, null)); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokePerformFilter(filter, preContext, next)); thunk(); return(result); }
public object Perform(PerformContext context) { Console.WriteLine($"Perform {context.BackgroundJob.Id} ({context.BackgroundJob.Job.Type.FullName}.{context.BackgroundJob.Job.Method.Name})"); return(_inner.Perform(context)); }
private IState PerformJob(BackgroundProcessContext context, IStorageConnection connection, string jobId) { try { var jobData = connection.GetJobData(jobId); if (jobData == null) { // Job expired just after moving to a processing state. This is an // unreal scenario, but shit happens. Returning null instead of throwing // an exception and rescuing from en-queueing a poisoned jobId back // to a queue. return(null); } jobData.EnsureLoaded(); var backgroundJob = new BackgroundJob(jobId, jobData.Job, jobData.CreatedAt); var jobToken = new ServerJobCancellationToken(connection, jobId, context.ServerId, _workerId, context.CancellationToken); var jobActivatorContext = new JobActivatorContext(connection, backgroundJob, jobToken); var scope = _activator.BeginScope(jobActivatorContext); if (scope != null) { using (scope) { var performContext = new PerformContext(connection, backgroundJob, jobToken, _profiler, scope); var latency = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds; var duration = Stopwatch.StartNew(); var result = _performer.Perform(performContext); duration.Stop(); return(new SucceededState(result, (long)latency, duration.ElapsedMilliseconds)); } } else { if (jobActivatorContext.ReEnqueueAt.HasValue) { return(new ScheduledState(jobActivatorContext.ReEnqueueAt.Value)); } else { return(new FailedState(new InvalidOperationException("Scope could not be started"))); } } } catch (JobAbortedException) { // Background job performance was aborted due to a // state change, so it's idenfifier should be removed // from a queue. return(null); } catch (JobPerformanceException ex) { return(new FailedState(ex.InnerException) { Reason = ex.Message }); } catch (Exception ex) { if (ex is OperationCanceledException && context.IsShutdownRequested) { throw; } return(new FailedState(ex) { Reason = "An exception occurred during processing of a background job." }); } }