예제 #1
0
        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);
            }
        }
예제 #3
0
        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);
        }
예제 #4
0
 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));
 }
예제 #5
0
        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."
                });
            }
        }