public void CopyCtor_CopiesItemsDictionary_FromTheGivenContext() { var context = CreateContext(); var contextCopy = new CreateContext(context); Assert.Same(context.Items, contextCopy.Items); }
public BackgroundJob Create(CreateContext context) { var parameters = context.Parameters.ToDictionary(x => x.Key, x => JobHelper.ToJson(x.Value)); var createdAt = DateTime.UtcNow; var jobId = context.Connection.CreateExpiredJob( context.Job, parameters, createdAt, TimeSpan.FromHours(1)); var backgroundJob = new BackgroundJob(jobId, context.Job, createdAt); if (context.InitialState != null) { using (var transaction = context.Connection.CreateWriteTransaction()) { var applyContext = new ApplyStateContext( context.Storage, context.Connection, transaction, backgroundJob, context.InitialState, null); _stateMachine.ApplyState(applyContext); transaction.Commit(); } } return backgroundJob; }
internal ClientExceptionContext(CreateContext createContext, Exception exception) : base(createContext) { if (exception == null) throw new ArgumentNullException("exception"); Exception = exception; }
public string Run(CreateContext context, IJobCreator creator) { if (context == null) throw new ArgumentNullException("context"); if (creator == null) throw new ArgumentNullException("creator"); var filterInfo = GetFilters(context.Job); try { var createdContext = CreateWithFilters(context, creator, filterInfo.ClientFilters); return createdContext.JobId; } catch (Exception ex) { var exceptionContext = new ClientExceptionContext(context, ex); InvokeExceptionFilters(exceptionContext, filterInfo.ClientExceptionFilters); if (!exceptionContext.ExceptionHandled) { throw; } return null; } }
private CreatedContext CreateContext() { var connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => TestMethod()); var state = new Mock<IState>(); var createContext = new CreateContext(connection.Object, job, state.Object); return new CreatedContext(createContext, JobId, true, _exception); }
internal CreatedContext( CreateContext context, bool canceled, Exception exception) : base(context) { Canceled = canceled; Exception = exception; }
public ClientExceptionContextFacts() { var connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => TestMethod()); var state = new Mock<IState>(); _createContext = new CreateContext( connection.Object, job, state.Object); }
public void Ctor_CanceledProperty_IsFalseByDefault() { var connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => TestMethod()); var state = new Mock<IState>(); var stateMachineFactory = new Mock<IStateMachineFactory>(); var createContext = new CreateContext( connection.Object, stateMachineFactory.Object, job, state.Object); var context = new CreatingContext(createContext); Assert.False(context.Canceled); }
public void Ctor_CorrectlySetsAllProperties() { var connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => TestMethod()); var state = new Mock<IState>(); var exception = new Exception(); var stateMachineFactory = new Mock<IStateMachineFactory>(); var createContext = new CreateContext( connection.Object, stateMachineFactory.Object, job, state.Object); var context = new CreatedContext(createContext, true, exception); Assert.True(context.Canceled); Assert.Same(exception, context.Exception); }
private static void CreateWithFilters( CreateContext context, IEnumerable<IClientFilter> filters) { var preContext = new CreatingContext(context); Func<CreatedContext> continuation = () => { context.CreateJob(); return new CreatedContext(context, false, null); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); thunk(); }
private CreatedContext CreateWithFilters( CreateContext context, IEnumerable <IClientFilter> filters) { var preContext = new CreatingContext(context); Func <CreatedContext> continuation = () => { var backgroundJob = _innerFactory.Create(context); return(new CreatedContext(context, backgroundJob, false, null)); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); return(thunk()); }
private CreatedContext CreateWithFilters( CreateContext context, IEnumerable<IClientFilter> filters) { var preContext = new CreatingContext(context); Func<CreatedContext> continuation = () => { var backgroundJob = _innerFactory.Create(context); return new CreatedContext(context, backgroundJob, false, null); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); return thunk(); }
private static void CreateWithFilters( CreateContext context, IEnumerable <IClientFilter> filters) { var preContext = new CreatingContext(context); Func <CreatedContext> continuation = () => { context.CreateJob(); return(new CreatedContext(context, false, null)); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); thunk(); }
private static CreatedContext CreateWithFilters( CreateContext context, IJobCreator creator, IEnumerable<IClientFilter> filters) { var preContext = new CreatingContext(context); Func<CreatedContext> continuation = () => { var jobId = creator.CreateJob(context.Job, preContext.Parameters, context.InitialState); return new CreatedContext(context, jobId, false, null); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); return thunk(); }
public PreserveCultureAttributeFacts() { _connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => Sample()); var state = new Mock<IState>(); var createContext = new CreateContext( _connection.Object, job, state.Object); _creatingContext = new CreatingContext(createContext); var workerContext = new WorkerContextMock(); var performContext = new PerformContext( workerContext.Object, _connection.Object, JobId, job, DateTime.UtcNow, new Mock<IJobExecutionContext>().Object); _performingContext = new PerformingContext(performContext); _performedContext = new PerformedContext(performContext, null, false, null); }
private static CreatedContext CreateWithFilters( CreateContext context, IJobCreator creator, IEnumerable <IClientFilter> filters) { var preContext = new CreatingContext(context); Func <CreatedContext> continuation = () => { var jobId = creator.CreateJob(context.Job, preContext.Parameters, context.InitialState); return(new CreatedContext(context, jobId, false, null)); }; var thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeClientFilter(filter, preContext, next)); return(thunk()); }
public PreserveCultureAttributeFacts() { _connection = new Mock<IStorageConnection>(); var storage = new Mock<JobStorage>(); var backgroundJob = new BackgroundJobMock { Id = JobId }; var state = new Mock<IState>(); var createContext = new CreateContext( storage.Object, _connection.Object, backgroundJob.Job, state.Object); _creatingContext = new CreatingContext(createContext); var performContext = new PerformContext( _connection.Object, backgroundJob.Object, new Mock<IJobCancellationToken>().Object); _performingContext = new PerformingContext(performContext); _performedContext = new PerformedContext(performContext, null, false, null); }
public void Run(CreateContext context) { if (context == null) throw new ArgumentNullException("context"); var filterInfo = GetFilters(context.Job); try { CreateWithFilters(context, filterInfo.ClientFilters); } catch (Exception ex) { var exceptionContext = new ClientExceptionContext(context, ex); InvokeExceptionFilters(exceptionContext, filterInfo.ClientExceptionFilters); if (!exceptionContext.ExceptionHandled) { throw; } } }
public BackgroundJob Create(CreateContext context) { if (context == null) throw new ArgumentNullException(nameof(context)); var filterInfo = GetFilters(context.Job); try { var createdContext = CreateWithFilters(context, filterInfo.ClientFilters); return createdContext.BackgroundJob; } catch (Exception ex) { var exceptionContext = new ClientExceptionContext(context, ex); InvokeExceptionFilters(exceptionContext, filterInfo.ClientExceptionFilters); if (!exceptionContext.ExceptionHandled) { throw; } return null; } }
public BackgroundJob Create(CreateContext context) { var parameters = context.Parameters.ToDictionary( x => x.Key, x => SerializationHelper.Serialize(x.Value, SerializationOption.User)); var createdAt = DateTime.UtcNow; var jobId = context.Connection.CreateExpiredJob( context.Job, parameters, createdAt, TimeSpan.FromDays(30)); var backgroundJob = new BackgroundJob(jobId, context.Job, createdAt); if (context.InitialState != null) { using (var transaction = context.Connection.CreateWriteTransaction()) { var applyContext = new ApplyStateContext( context.Storage, context.Connection, transaction, backgroundJob, context.InitialState, oldStateName: null, profiler: context.Profiler); _stateMachine.ApplyState(applyContext); transaction.Commit(); } } return(backgroundJob); }
public void Run(CreateContext context) { if (context == null) { throw new ArgumentNullException("context"); } var filterInfo = GetFilters(context.Job); try { CreateWithFilters(context, filterInfo.ClientFilters); } catch (Exception ex) { var exceptionContext = new ClientExceptionContext(context, ex); InvokeExceptionFilters(exceptionContext, filterInfo.ClientExceptionFilters); if (!exceptionContext.ExceptionHandled) { throw; } } }
internal CreateContext(CreateContext context) : this(context.Connection, context.Job, context.InitialState) { Items = context.Items; }
public void CopyCtor_CopiesTheFactThatJobWasCreated() { var context = CreateContext(); context.CreateJob(); var contextCopy = new CreateContext(context); Assert.Throws<InvalidOperationException>( () => contextCopy.SetJobParameter("name", "value")); }
/// <inheritdoc /> public string Create(Job job, IState state) { if (job == null) throw new ArgumentNullException("job"); if (state == null) throw new ArgumentNullException("state"); try { using (var connection = _storage.GetConnection()) { var context = new CreateContext(connection, _stateMachineFactory, job, state); _process.Run(context); return context.JobId; } } catch (Exception ex) { throw new CreateJobFailedException("Job creation process has bee failed. See inner exception for details", ex); } }
internal CreateContext([NotNull] CreateContext context) : this(context.Storage, context.Connection, context.Job, context.InitialState) { Items = context.Items; Parameters = context.Parameters; }
private CreatingContext CreateContext() { var storage = new Mock<JobStorage>(); var connection = new Mock<IStorageConnection>(); var job = Job.FromExpression(() => TestMethod()); var state = new Mock<IState>(); var createContext = new CreateContext(storage.Object, connection.Object, job, state.Object); return new CreatingContext(createContext); }
/// <inheritdoc /> public string Create(Job job, IState state) { if (job == null) throw new ArgumentNullException("job"); if (state == null) throw new ArgumentNullException("state"); try { using (var connection = _storage.GetConnection()) { var context = new CreateContext(_storage, connection, job, state); var backroundJob = _factory.Create(context); return backroundJob != null ? backroundJob.Id : null; } } catch (Exception ex) { throw new BackgroundJobClientException("Background job creation failed. See inner exception for details.", ex); } }
public void CopyCtor_CopiesJobId_WhenItWasSet() { _stateMachine.Setup(x => x.CreateInState( _job, It.IsAny<Dictionary<string, string>>(), _state.Object)) .Returns("id"); var context = CreateContext(); context.CreateJob(); var contextCopy = new CreateContext(context); Assert.Equal("id", contextCopy.JobId); }
public BackgroundJob Create(CreateContext context) { var attemptsLeft = Math.Max(RetryAttempts, 0); var parameters = context.Parameters.ToDictionary( x => x.Key, x => SerializationHelper.Serialize(x.Value, SerializationOption.User)); var createdAt = DateTime.UtcNow; // Retry may cause multiple background jobs to be created, especially when there's // a timeout-related exception. But initialization attempt will be performed only // for the most recent job, leaving all the previous ones in a non-initialized state // and making them invisible to other parts of the system, since no one knows their // identifiers. Since they also will be eventually expired leaving no trace, we can // consider that only one background job is created, regardless of retry attempts // number. var jobId = RetryOnException(ref attemptsLeft, _ => context.Connection.CreateExpiredJob( context.Job, parameters, createdAt, TimeSpan.FromDays(30))); if (String.IsNullOrEmpty(jobId)) { return(null); } var backgroundJob = new BackgroundJob(jobId, context.Job, createdAt); if (context.InitialState != null) { RetryOnException(ref attemptsLeft, attempt => { if (attempt > 0) { // Normally, a distributed lock should be applied when making a retry, since // it's possible to get a timeout exception, when transaction was actually // committed. But since background job can't be returned to a position where // its state is null, and since only the current thread knows the job's identifier // when its state is null, and since we shouldn't do anything when it's non-null, // there will be no any race conditions. var data = context.Connection.GetJobData(jobId); if (data == null) { throw new InvalidOperationException($"Was unable to initialize a background job '{jobId}', because it doesn't exists."); } if (!String.IsNullOrEmpty(data.State)) { return; } } using (var transaction = context.Connection.CreateWriteTransaction()) { var applyContext = new ApplyStateContext( context.Storage, context.Connection, transaction, backgroundJob, context.InitialState, oldStateName: null, profiler: context.Profiler); StateMachine.ApplyState(applyContext); transaction.Commit(); } }); } return(backgroundJob); }
private void TryScheduleJob( JobStorage storage, IStorageConnection connection, string recurringJobId, IReadOnlyDictionary<string, string> recurringJob) { var serializedJob = JobHelper.FromJson<InvocationData>(recurringJob["Job"]); var job = serializedJob.Deserialize(); var cron = recurringJob["Cron"]; var cronSchedule = CrontabSchedule.Parse(cron); try { var timeZone = recurringJob.ContainsKey("TimeZoneId") ? TimeZoneInfo.FindSystemTimeZoneById(recurringJob["TimeZoneId"]) : TimeZoneInfo.Utc; var nowInstant = _instantFactory(cronSchedule, timeZone); var changedFields = new Dictionary<string, string>(); var lastInstant = GetLastInstant(recurringJob, nowInstant); if (nowInstant.GetNextInstants(lastInstant).Any()) { var state = new EnqueuedState { Reason = "Triggered by recurring job scheduler" }; if (recurringJob.ContainsKey("Queue") && !String.IsNullOrEmpty(recurringJob["Queue"])) { state.Queue = recurringJob["Queue"]; } var context = new CreateContext(storage, connection, job, state); context.Parameters["RecurringJobId"] = recurringJobId; var backgroundJob = _factory.Create(context); var jobId = backgroundJob?.Id; if (String.IsNullOrEmpty(jobId)) { Logger.Debug($"Recurring job '{recurringJobId}' execution at '{nowInstant.NowInstant}' has been canceled."); } changedFields.Add("LastExecution", JobHelper.SerializeDateTime(nowInstant.NowInstant)); changedFields.Add("LastJobId", jobId ?? String.Empty); } // Fixing old recurring jobs that doesn't have the CreatedAt field if (!recurringJob.ContainsKey("CreatedAt")) { changedFields.Add("CreatedAt", JobHelper.SerializeDateTime(nowInstant.NowInstant)); } changedFields.Add("NextExecution", nowInstant.NextInstant.HasValue ? JobHelper.SerializeDateTime(nowInstant.NextInstant.Value) : null); connection.SetRangeInHash( $"recurring-job:{recurringJobId}", changedFields); } #if NETFULL catch (TimeZoneNotFoundException ex) { #else catch (Exception ex) { // https://github.com/dotnet/corefx/issues/7552 if (!ex.GetType().Name.Equals("TimeZoneNotFoundException")) throw; #endif Logger.ErrorException( $"Recurring job '{recurringJobId}' was not triggered: {ex.Message}.", ex); } }
public CreatingContext(CreateContext context) : base(context) { }
public void CopyCtor_CopiesJobParameters_FromTheGivenContext() { var context = CreateContext(); context.SetJobParameter("name", "value"); var contextCopy = new CreateContext(context); var value = contextCopy.GetJobParameter<string>("name"); Assert.Equal("value", value); }
public void Trigger(string recurringJobId) { if (recurringJobId == null) throw new ArgumentNullException(nameof(recurringJobId)); using (var connection = _storage.GetConnection()) { var hash = connection.GetAllEntriesFromHash($"recurring-job:{recurringJobId}"); if (hash == null) { return; } var job = JobHelper.FromJson<InvocationData>(hash["Job"]).Deserialize(); var state = new EnqueuedState { Reason = "Triggered using recurring job manager" }; if (hash.ContainsKey("Queue")) { state.Queue = hash["Queue"]; } var context = new CreateContext(_storage, connection, job, state); context.Parameters["RecurringJobId"] = recurringJobId; _factory.Create(context); } }
public void CopyCtor_CopiesJobId_FromTheGivenContext() { var context = CreateContext(); var contextCopy = new CreateContext(context); Assert.Same(context.JobId, contextCopy.JobId); }