Пример #1
0
 /// <summary>
 /// Write an exception to the console output.
 /// </summary>
 public static void WriteException(
     this PerformContext console,
     Exception exception) => console.WriteLine($"{exception.Message}\n{exception.StackTrace}");
Пример #2
0
 internal PerformContext([NotNull] PerformContext context)
     : this(context.Connection, context.BackgroundJob, context.CancellationToken)
 {
     Items = context.Items;
 }
Пример #3
0
 /// <summary>
 /// Write an empty line to the console output.
 /// </summary>
 public static void Flush(
     this PerformContext console) => console.WriteLine();
Пример #4
0
 public PerformContext([NotNull] PerformContext context)
     : this(context.Connection, context.BackgroundJob, context.CancellationToken, context.Profiler, context._scope)
 {
     Items = context.Items;
 }
Пример #5
0
        private void ProcessJob(
            string jobId,
            IStorageConnection connection,
            IJobPerformanceProcess process,
            CancellationToken shutdownToken)
        {
            var stateMachine    = _context.StateMachineFactory.Create(connection);
            var processingState = new ProcessingState(_context.ServerId, _context.WorkerNumber);

            if (!stateMachine.TryToChangeState(
                    jobId,
                    processingState,
                    new[] { EnqueuedState.StateName, ProcessingState.StateName }))
            {
                return;
            }

            // Checkpoint #3. Job is in the Processing state. However, there are
            // no guarantees that it was performed. We need to re-queue it even
            // it was performed to guarantee that it was performed AT LEAST once.
            // It will be re-queued after the JobTimeout was expired.

            IState state;

            try
            {
                var jobData = connection.GetJobData(jobId);
                jobData.EnsureLoaded();

                var cancellationToken = new ServerJobCancellationToken(
                    jobId, connection, _context, shutdownToken);

                var performContext = new PerformContext(
                    _context, connection, jobId, jobData.Job, jobData.CreatedAt, cancellationToken);

                var latency  = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds;
                var duration = Stopwatch.StartNew();

                process.Run(performContext, jobData.Job);
                duration.Stop();

                state = new SucceededState((long)latency, duration.ElapsedMilliseconds);
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (JobPerformanceException ex)
            {
                state = new FailedState(ex.InnerException)
                {
                    Reason = ex.Message
                };
            }
            catch (Exception ex)
            {
                state = new FailedState(ex)
                {
                    Reason = "Internal Hangfire Server exception occurred. Please, report it to Hangfire developers."
                };
            }

            // Ignore return value, because we should not do
            // anything when current state is not Processing.
            stateMachine.TryToChangeState(jobId, state, new[] { ProcessingState.StateName });
        }
Пример #6
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."
                });
            }
        }
Пример #7
0
 internal PerformContext(PerformContext context)
     : this(context, context.Connection, context.JobId, context.Job, context.CreatedAt, context.JobExecutionContext)
 {
     Items = context.Items;
 }