Ejemplo n.º 1
0
        private IState GetNewState(OperateResult result, CapReceivedMessage message)
        {
            IState newState;

            if (!result.Succeeded)
            {
                var shouldRetry = UpdateMessageForRetry(message);
                if (shouldRetry)
                {
                    newState = new ScheduledState();
                    _logger.JobFailedWillRetry(result.Exception);
                }
                else
                {
                    newState = new FailedState();
                    _logger.JobFailed(result.Exception);
                }
                AddErrorReasonToContent(message, result.Exception);
            }
            else
            {
                newState = new SucceededState(_options.SucceedMessageExpiredAfter);
            }
            return(newState);
        }
Ejemplo n.º 2
0
        public void HangfireScheduler_ResumeJob_InSucceededState_Failed()
        {
            var dataObjectMock = new Mock <IDSFDataObject>();
            var values         = new Dictionary <string, StringBuilder>
            {
                { "resourceID", new StringBuilder("ab04663e-1e09-4338-8f61-a06a7ae5ebab") },
                { "environment", new StringBuilder("NewEnvironment") },
                { "startActivityId", new StringBuilder("4032a11e-4fb3-4208-af48-b92a0602ab4b") },
                { "versionNumber", new StringBuilder("1") },
                { "currentuserprincipal", new StringBuilder(WindowsIdentity.GetCurrent().Name) }
            };

            var jobstorage = new MemoryStorage();
            var client     = new BackgroundJobClient(jobstorage);
            var scheduler  = new Persistence.Drivers.HangfireScheduler(client, jobstorage);

            var jobId = scheduler.ScheduleJob(enSuspendOption.SuspendForSeconds, "1", values);
            var o     = new object();
            var state = new SucceededState(o, 1, 1);

            client.ChangeState(jobId, state, ScheduledState.StateName);

            var result = scheduler.ResumeJob(dataObjectMock.Object, jobId, false, "NewEnvironment");

            Assert.AreEqual(GlobalConstants.Failed, result);
        }
Ejemplo n.º 3
0
        public async Task <OperateResult> ExecuteAsync(IStorageConnection connection, IFetchedMessage fetched)
        {
            var message = await connection.GetReceivedMessageAsync(fetched.MessageId);

            try
            {
                var sp = Stopwatch.StartNew();
                await _stateChanger.ChangeStateAsync(message, new ProcessingState(), connection);

                if (message.Retries > 0)
                {
                    _logger.JobRetrying(message.Retries);
                }
                var result = await ExecuteSubscribeAsync(message);

                sp.Stop();

                var newState = default(IState);
                if (!result.Succeeded)
                {
                    var shouldRetry = await UpdateMessageForRetryAsync(message, connection);

                    if (shouldRetry)
                    {
                        newState = new ScheduledState();
                        _logger.JobFailedWillRetry(result.Exception);
                    }
                    else
                    {
                        newState = new FailedState();
                        _logger.JobFailed(result.Exception);
                    }
                }
                else
                {
                    newState = new SucceededState();
                }
                await _stateChanger.ChangeStateAsync(message, newState, connection);

                fetched.RemoveFromQueue();

                if (result.Succeeded)
                {
                    _logger.JobExecuted(sp.Elapsed.TotalSeconds);
                }

                return(OperateResult.Success);
            }
            catch (SubscriberNotFoundException ex)
            {
                _logger.LogError(ex.Message);
                return(OperateResult.Failed(ex));
            }
            catch (Exception ex)
            {
                _logger.ExceptionOccuredWhileExecutingJob(message?.Name, ex);
                return(OperateResult.Failed(ex));
            }
        }
        public void SerializeData_DoesNotAppendEntry_ForNullResult()
        {
            var state = new SucceededState(null, 0, 0);

            var data = state.SerializeData();

            Assert.False(data.ContainsKey("Result"));
        }
        public void SerializeData_CorrectlyHandlesResults_ThatCantBeSerialized()
        {
            var process = new Process();
            var state   = new SucceededState(process, 0, 0);

            var data = state.SerializeData();

            Assert.Contains("Can not serialize", data["Result"]);
        }
Ejemplo n.º 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 performContext = new PerformContext(connection, backgroundJob, jobToken);

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

                var result = _performer.Perform(performContext);
                duration.Stop();
                var state = new SucceededState(result, (long)latency, duration.ElapsedMilliseconds);
                state.Reason = GetJobName(jobData.Job);
                return(state);
            }
            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."
                });
            }
        }
        public void JsonSerialize_ReturnsCorrectString_After170()
        {
            var state = new SucceededState(null, 1, 2);

            var serialized = SerializationHelper.Serialize <IState>(state, SerializationOption.TypedInternal);

            Assert.Equal(
                "{\"$type\":\"Hangfire.States.SucceededState, Hangfire.Core\",\"Latency\":1,\"PerformanceDuration\":2}",
                serialized);
        }
Ejemplo n.º 8
0
        public async Task <OperateResult> ExecuteAsync(IStorageConnection connection, IFetchedMessage fetched)
        {
            var message = await connection.GetPublishedMessageAsync(fetched.MessageId);

            try
            {
                var sp = Stopwatch.StartNew();
                await _stateChanger.ChangeStateAsync(message, new ProcessingState(), connection);

                if (message.Retries > 0)
                {
                    _logger.JobRetrying(message.Retries);
                }
                var result = await PublishAsync(message.Name, message.Content);

                sp.Stop();

                IState newState;
                if (!result.Succeeded)
                {
                    var shouldRetry = UpdateMessageForRetryAsync(message);
                    if (shouldRetry)
                    {
                        newState = new ScheduledState();
                        _logger.JobFailedWillRetry(result.Exception);
                    }
                    else
                    {
                        newState = new FailedState();
                        _logger.JobFailed(result.Exception);
                    }
                    message.Content = Helper.AddExceptionProperty(message.Content, result.Exception);
                }
                else
                {
                    newState = new SucceededState(_options.SucceedMessageExpiredAfter);
                }
                await _stateChanger.ChangeStateAsync(message, newState, connection);

                fetched.RemoveFromQueue();

                if (result.Succeeded)
                {
                    _logger.JobExecuted(sp.Elapsed.TotalSeconds);
                }

                return(OperateResult.Success);
            }
            catch (Exception ex)
            {
                fetched.Requeue();
                _logger.ExceptionOccuredWhileExecuting(message?.Name, ex);
                return(OperateResult.Failed(ex));
            }
        }
    internal static DateTime?GetCreatedAt(this IState state)
    {
        if (state is null)
        {
            throw new ArgumentNullException(nameof(state));
        }

        return(state switch
        {
            ScheduledState scheduled => scheduled.ScheduledAt,
            EnqueuedState enqueued => enqueued.EnqueuedAt,
            ProcessingState processing => processing.StartedAt,
            SucceededState succeeded => succeeded.SucceededAt,
            FailedState failed => failed.FailedAt,
            DeletedState deleted => deleted.DeletedAt,
            _ => default(DateTime?),
        });
        private Task SetSuccessfulState(CapPublishedMessage message)
        {
            var succeededState = new SucceededState(_options.SucceedMessageExpiredAfter);

            return(_stateChanger.ChangeStateAsync(message, succeededState, _connection));
        }
        private async Task <bool> Step(ProcessingContext context)
        {
            var fetched = default(IFetchedJob);

            using (var scope = _provider.CreateScope())
            {
                var provider   = scope.ServiceProvider;
                var connection = provider.GetRequiredService <IStorageConnection>();

                if ((fetched = await connection.FetchNextJobAsync()) != null)
                {
                    using (fetched)
                        using (var scopedContext = context.CreateScope())
                        {
                            var job = await connection.GetJobAsync(fetched.JobId);

                            var invocationData = Helper.FromJson <InvocationData>(job.Data);
                            var method         = invocationData.Deserialize();
                            var factory        = scopedContext.Provider.GetService <IJobFactory>();

                            var instance = default(object);
                            if (!method.Method.IsStatic)
                            {
                                instance = factory.Create(method.Type);
                            }

                            try
                            {
                                var sp = Stopwatch.StartNew();
                                await _stateChanger.ChangeStateAsync(job, new ProcessingState(), connection);

                                if (job.Retries > 0)
                                {
                                    _logger.JobRetrying(job.Retries);
                                }

                                var result = await ExecuteJob(method, instance);

                                sp.Stop();

                                var newState = default(IState);
                                if (!result.Succeeded)
                                {
                                    var shouldRetry = await UpdateJobForRetryAsync(instance, job, connection);

                                    if (shouldRetry)
                                    {
                                        newState = new ScheduledState();
                                        _logger.JobFailedWillRetry(result.Exception);
                                    }
                                    else
                                    {
                                        newState = new FailedState();
                                        _logger.JobFailed(result.Exception);
                                    }
                                }
                                else
                                {
                                    newState = new SucceededState();
                                }

                                await _stateChanger.ChangeStateAsync(job, newState, connection);

                                fetched.RemoveFromQueue();
                                if (result.Succeeded)
                                {
                                    _logger.JobExecuted(sp.Elapsed.TotalSeconds);
                                }
                            }
                            catch (JobLoadException ex)
                            {
                                _logger.JobCouldNotBeLoaded(job.Id, ex);

                                await _stateChanger.ChangeStateAsync(job, new FailedState(), connection);

                                fetched.RemoveFromQueue();
                            }
                            catch (Exception ex)
                            {
                                _logger.ExceptionOccuredWhileExecutingJob(job.Id, ex);

                                fetched.Requeue();
                            }
                        }
                }
            }
            return(fetched != null);
        }
Ejemplo n.º 12
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 });
        }
Ejemplo n.º 13
0
 internal override void TrySetSucceeded(out State state, out Func <bool> postscript, TResult result)
 {
     state      = new SucceededState(result);
     postscript = TryPostscript;
 }
Ejemplo n.º 14
0
 internal override void SetSucceeded(out State state, out Action postscript, TResult result)
 {
     state      = new SucceededState(result);
     postscript = Postscript;
 }