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); }
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); }
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"]); }
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); }
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); }
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 }); }
internal override void TrySetSucceeded(out State state, out Func <bool> postscript, TResult result) { state = new SucceededState(result); postscript = TryPostscript; }
internal override void SetSucceeded(out State state, out Action postscript, TResult result) { state = new SucceededState(result); postscript = Postscript; }