public void AddOrUpdate_UsesTimeZoneResolver_WhenCalculatingNextExecution() { // Arrange var timeZone = TimeZoneInfo.FindSystemTimeZoneById(PlatformHelper.IsRunningOnWindows() ? "Hawaiian Standard Time" : "Pacific/Honolulu"); _timeZoneResolver.Setup(x => x.GetTimeZoneById(It.IsAny <string>())).Throws <InvalidOperationException>(); _timeZoneResolver .Setup(x => x.GetTimeZoneById(It.Is <string>(id => id == "Hawaiian Standard Time" || id == "Pacific/Honolulu"))) .Returns(timeZone); // We are returning IANA time zone on Windows and Windows time zone on Linux. _connection.Setup(x => x.GetAllEntriesFromHash($"recurring-job:{_id}")).Returns(new Dictionary <string, string> { { "Cron", "0 0 * * *" }, { "Job", InvocationData.Serialize(_job).SerializePayload() }, { "CreatedAt", JobHelper.SerializeDateTime(_now) }, { "TimeZoneId", PlatformHelper.IsRunningOnWindows() ? "Pacific/Honolulu" : "Hawaiian Standard Time" }, { "NextExecution", JobHelper.SerializeDateTime(_now.AddHours(18).AddMinutes(30)) }, { "Queue", "default" }, { "V", "2" } }); var manager = CreateManager(); // Act manager.AddOrUpdate(_id, _job, "0 0 * * *", timeZone, "default"); // Assert _transaction.Verify(x => x.SetRangeInHash($"recurring-job:{_id}", It.Is <Dictionary <string, string> >(dict => dict.ContainsKey("TimeZoneId") && !dict.ContainsKey("NextExecution")))); _transaction.Verify(x => x.AddToSet("recurring-jobs", _id, JobHelper.ToTimestamp(_now.AddHours(18).AddMinutes(30)))); _transaction.Verify(x => x.Commit()); }
public void GetJobData_ReturnsResult_WhenJobExists() { var job = Job.FromExpression(() => HangfireTestJobs.SampleMethod("wrong")); var jobDto = new JobDto { Id = ObjectId.GenerateNewId(), InvocationData = JobHelper.ToJson(InvocationData.Serialize(job)), Arguments = "[\"\\\"Arguments\\\"\"]", StateName = SucceededState.StateName, CreatedAt = DateTime.UtcNow }; _dbContext.JobGraph.InsertOne(jobDto); var result = _connection.GetJobData(jobDto.Id.ToString()); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.Equal(SucceededState.StateName, result.State); Assert.Equal("Arguments", result.Job.Args[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }
/// <summary> /// 获取job任务 /// </summary> /// <param name="name"></param> /// <returns></returns> public string GetJobdata(string name) { try { using (var connection = JobStorage.Current.GetConnection()) { Dictionary <string, string> dictionary = connection.GetAllEntriesFromHash("recurring-job:" + name); if (dictionary == null || dictionary.Count == 0) { return(""); } if (!dictionary.TryGetValue(nameof(Job), out var jobDetail)) { return(""); } var RecurringJob = InvocationData.DeserializePayload(jobDetail).DeserializeJob(); return(JsonConvert.SerializeObject(JsonConvert.DeserializeObject <RecurringJobItem>(RecurringJob.Args.FirstOrDefault()?.ToString()))); } } catch (Exception ex) { Logger.ErrorException("HttpJobDispatcher.GetJobdata", ex); } return(""); }
public void GetJobData_ReturnsResult_WhenJobExists() { string arrangeSql = @" insert into """ + GetSchemaName() + @""".""job"" (""invocationdata"", ""arguments"", ""statename"", ""createdat"") values (@invocationData, @arguments, @stateName, now() at time zone 'utc') returning ""id"""; UseConnections((sql, connection) => { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobId = (int)sql.Query( arrangeSql, new { invocationData = JobHelper.ToJson(InvocationData.Serialize(job)), stateName = "Succeeded", arguments = "[\"\\\"Arguments\\\"\"]" }).Single().id; var result = connection.GetJobData(jobId.ToString()); var now = DateTime.UtcNow.AddMinutes(-1); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.Equal("Succeeded", result.State); Assert.Equal("Arguments", result.Job.Args[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }); }
private JobList <T> GetJobsOnQueue <T>(string queue, int from, int count, Func <string, Common.Job, T> selector) { if (string.IsNullOrEmpty(queue)) { throw new ArgumentNullException(nameof(queue)); } // TODO: move to stored procedure List <KeyValuePair <string, T> > jobs = new List <KeyValuePair <string, T> >(); List <Entities.Queue> queues = storage.Client.CreateDocumentQuery <Entities.Queue>(storage.Collections.QueueDocumentCollectionUri, QueryOptions) .Where(q => q.Name == queue && q.DocumentType == DocumentTypes.Queue) .AsEnumerable() .Skip(from).Take(count) .ToList(); List <Entities.Job> filterJobs = storage.Client.CreateDocumentQuery <Entities.Job>(storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.DocumentType == DocumentTypes.Job) .AsEnumerable() .Where(j => queues.Any(q => q.JobId == j.Id)) .ToList(); queues.ForEach(queueItem => { Entities.Job job = filterJobs.Single(j => j.Id == queueItem.JobId); InvocationData invocationData = job.InvocationData; invocationData.Arguments = job.Arguments; T data = selector(job.StateName, invocationData.Deserialize()); jobs.Add(new KeyValuePair <string, T>(job.Id, data)); }); return(new JobList <T>(jobs)); }
public string CreateExpiredJob(Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { // TODO make this a transaction var invocationData = InvocationData.Serialize(job); var persistedJob = new Entities.Job() { InvocationData = JsonConvert.SerializeObject(invocationData), Arguments = invocationData.Arguments, CreatedAt = createdAt, ExpireAt = createdAt.Add(expireIn) }; return(UsingDatabase(db => { int jobId = Convert.ToInt32(db.InsertWithIdentity(persistedJob)); foreach (var parameter in parameters) { db.Insert(new JobParameter() { JobId = jobId, Name = parameter.Key, Value = parameter.Value }); } return jobId.ToString(CultureInfo.InvariantCulture); })); }
public override string CreateExpiredJob(Common.Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { if (job == null) { throw new ArgumentNullException(nameof(job)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } InvocationData invocationData = InvocationData.Serialize(job); PushResponse response = Client.Push("jobs", new Entities.Job { InvocationData = invocationData, Arguments = invocationData.Arguments, CreatedOn = createdAt, ExpireOn = createdAt.Add(expireIn), Parameters = parameters.Select(p => new Parameter { Name = p.Key, Value = p.Value }).ToArray() }); if (response.StatusCode == HttpStatusCode.OK) { return(response.Result.name); } return(string.Empty); }
public void Deserialize_WrapsAnException_WithTheJobLoadException() { var serializedData = new InvocationData(null, null, null, null); Assert.Throws <JobLoadException>( () => serializedData.Deserialize()); }
public RecurringJobSchedulerFacts() { _storage = new Mock <JobStorage>(); _client = new Mock <IBackgroundJobClient>(); _dateTimeProvider = new Mock <IDateTimeProvider>(); _token = new CancellationToken(); // Setting up the successful path _currentTime = new DateTime(2012, 12, 12, 12, 12, 0); _nextTime = _currentTime.AddHours(1); _dateTimeProvider.Setup(x => x.CurrentDateTime).Returns(() => _currentTime); _dateTimeProvider.Setup(x => x.GetNextOccurrence(It.IsNotNull <CrontabSchedule>())) .Returns(() => _nextTime); _recurringJob = new Dictionary <string, string> { { "NextExecution", JobHelper.SerializeDateTime(_currentTime) }, { "Cron", "* * * * *" }, { "Job", JobHelper.ToJson(InvocationData.Serialize(Job.FromExpression(() => Console.WriteLine()))) } }; _connection = new Mock <IStorageConnection>(); _storage.Setup(x => x.GetConnection()).Returns(_connection.Object); _connection.Setup(x => x.GetAllItemsFromSet("recurring-jobs")) .Returns(new HashSet <string> { RecurringJobId }); _connection.Setup(x => x.GetAllEntriesFromHash(String.Format("recurring-job:{0}", RecurringJobId))) .Returns(_recurringJob); }
private void InvocationPattern(long requestId, long registrationId, InvocationDetails details, Func <IWampRpcOperation, IWampRawRpcOperationRouterCallback, InvocationDetails, IWampCancellableInvocation> invocationAction) { IWampRpcOperation operation = TryGetOperation(registrationId); if (operation != null) { IWampRawRpcOperationRouterCallback callback = GetCallback(requestId); InvocationDetails modifiedDetails = new InvocationDetails(details) { Procedure = details.Procedure ?? operation.Procedure }; IWampCancellableInvocation invocation = invocationAction(operation, callback, modifiedDetails); if (invocation != null) { mInvocations[requestId] = new InvocationData(registrationId, invocation); lock (mLock) { mRegistrationsToInvocations.Add(registrationId, requestId); } } } }
public override string CreateExpiredJob( Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { var invocationData = InvocationData.Serialize(job); var jobModel = new JobModel(); _storage.ObjectRepository.Add(jobModel); jobModel.InvocationData = JobHelper.ToJson(invocationData); jobModel.Arguments = invocationData.Arguments; jobModel.CreatedAt = createdAt; jobModel.ExpireAt = createdAt.Add(expireIn); var jobId = jobModel.Id; foreach (var parameter in parameters) { var jpm = new JobParameterModel(jobId, parameter.Key) { Value = parameter.Value }; _storage.ObjectRepository.Add(jpm); } return(jobId.ToString()); }
public void GetJobData_ReturnsResult_WhenJobExists() { string arrangeSql = string.Format(CultureInfo.InvariantCulture, @" insert into ""{0}.JOB"" (invocationdata, arguments, statename, createdat) values (@invocationData, @arguments, @stateName, DATEADD(minute, -{1:N5}*60, current_timestamp)) returning id;", _options.Prefix, _options.UtcOffset); UseConnections((sql, connection) => { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobId = sql.ExecuteScalar <int>( arrangeSql, new { invocationData = JobHelper.ToJson(InvocationData.Serialize(job)), stateName = "Succeeded", arguments = "['Arguments']" }).ToString(); var result = connection.GetJobData(jobId); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.Equal("Succeeded", result.State); Assert.Equal("Arguments", result.Job.Args[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }); }
void ProcessRequests() { InvocationData data = null; do { lock (this) { if (_pendingInvokes.Count > 0) { data = _pendingInvokes[0]; _pendingInvokes.RemoveAt(0); } else { data = null; break; } } try { if (data != null) { //TracerHelper.Trace("Performing request."); data.Perform(); } } catch (Exception ex) { SystemMonitor.Error("Pending operation caused an exception [" + ex.Message + "]."); } }while (_keepRunning && data != null); }
public string CreateExpiredJob( Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { var jobId = Guid.NewGuid().ToString(); var invocationData = InvocationData.Serialize(job); // Do not modify the original parameters. var storedParameters = new Dictionary <string, string>(parameters); storedParameters.Add("Type", invocationData.Type); storedParameters.Add("Method", invocationData.Method); storedParameters.Add("ParameterTypes", invocationData.ParameterTypes); storedParameters.Add("Arguments", invocationData.Arguments); storedParameters.Add("CreatedAt", JobHelper.SerializeDateTime(createdAt)); using (var transaction = Redis.CreateTransaction()) { transaction.QueueCommand(x => x.SetRangeInHash( String.Format(RedisStorage.Prefix + "job:{0}", jobId), storedParameters)); transaction.QueueCommand(x => x.ExpireEntryIn( String.Format(RedisStorage.Prefix + "job:{0}", jobId), expireIn)); // TODO: check return value transaction.Commit(); } return(jobId); }
public void ForDeserializeCanUseCustomConfigurationOfJsonNetWithInvocationData() { try { JobHelper.SetSerializerSettings(new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All, TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple }); var method = typeof(BackgroundJob).GetMethod("DoWork"); var args = new object[] { "123", "Test" }; var job = new Job(typeof(BackgroundJob), method, args); var invocationData = InvocationData.Serialize(job); var deserializedJob = invocationData.Deserialize(); Assert.Equal(typeof(BackgroundJob), deserializedJob.Type); Assert.Equal(method, deserializedJob.Method); Assert.Equal(args, deserializedJob.Args); } finally { JobHelper.SetSerializerSettings(null); } }
public void GetJobData_ReturnsResult_WhenJobExists() { var job = Job.FromExpression(() => HangfireTestJobs.SampleMethod("wrong")); var jobDto = new JobDto { Id = Guid.NewGuid().ToString(), InvocationData = SerializationHelper.Serialize(InvocationData.SerializeJob(job)), Arguments = "[\"\\\"Arguments\\\"\"]", StateName = SucceededState.StateName, Created = DateTime.UtcNow }; var realm = _storage.GetRealm(); realm.Write(() => { realm.Add(jobDto); }); var result = _connection.GetJobData(jobDto.Id.ToString()); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.AreEqual(SucceededState.StateName, result.State); Assert.AreEqual("Arguments", result.Job.Args[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }
protected override async Task <object> InvokeCore(object[] parameters, FunctionInvocationContext context) { FunctionInstanceLogEntry item = new FunctionInstanceLogEntry { FunctionInstanceId = context.ExecutionContext.InvocationId, StartTime = DateTime.UtcNow, FunctionName = Metadata.Name, Properties = new Dictionary <string, object>() }; await _fastLogger.AddAsync(item); InvocationData invocation = parameters.OfType <InvocationData>().FirstOrDefault() ?? new InvocationData(); string error = "failed"; try { if (invocation.Throw) { throw new InvalidOperationException("Kaboom!"); } await Task.Delay(invocation.Delay); error = null; // success return(null); } finally { item.EndTime = DateTime.UtcNow; item.ErrorDetails = error; await _fastLogger.AddAsync(item); } }
private JobList <T> GetJobsOnState <T>(string stateName, int from, int count, Func <State, Common.Job, T> selector) { // TODO: move to stored procedure List <KeyValuePair <string, T> > jobs = new List <KeyValuePair <string, T> >(); List <Entities.Job> filterJobs = storage.Client.CreateDocumentQuery <Entities.Job>(storage.Collections.JobDocumentCollectionUri, QueryOptions) .Where(j => j.DocumentType == DocumentTypes.Job && j.StateName == stateName) .AsEnumerable() .Skip(from).Take(count) .ToList(); List <State> states = storage.Client.CreateDocumentQuery <State>(storage.Collections.StateDocumentCollectionUri, QueryOptions) .Where(s => s.DocumentType == DocumentTypes.State) .AsEnumerable() .Where(s => filterJobs.Any(j => j.StateId == s.Id)) .ToList(); filterJobs.ForEach(job => { State state = states.Single(s => s.Id == job.StateId); state.Data = state.Data; InvocationData invocationData = job.InvocationData; invocationData.Arguments = job.Arguments; T data = selector(state, invocationData.Deserialize()); jobs.Add(new KeyValuePair <string, T>(job.Id, data)); }); return(new JobList <T>(jobs)); }
public void GetJobData_ReturnsResult_WhenJobExists() { const string arrangeSql = @" insert into HangFire.Job (InvocationData, Arguments, StateName, CreatedAt) values (@invocationData, @arguments, @stateName, getutcdate()) select scope_identity() as Id"; UseConnections((sql, connection) => { var job = Job.FromExpression(() => SampleMethod("wrong")); var jobId = sql.Query( arrangeSql, new { invocationData = JobHelper.ToJson(InvocationData.Serialize(job)), stateName = "Succeeded", arguments = "['Arguments']" }).Single(); var result = connection.GetJobData(((int)jobId.Id).ToString()); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.Equal("Succeeded", result.State); Assert.Equal("Arguments", result.Job.Arguments[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }); }
public virtual string CreateExpiredJob(Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { if (job == null) { throw new ArgumentNullException(nameof(job)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var invocationData = InvocationData.Serialize(job); var jobDto = new JobDto { Id = ObjectId.GenerateNewId(), InvocationData = JobHelper.ToJson(invocationData), Arguments = invocationData.Arguments, Parameters = parameters.ToDictionary(kv => kv.Key, kv => kv.Value), CreatedAt = createdAt, ExpireAt = createdAt.Add(expireIn) }; var writeModel = new InsertOneModel <BsonDocument>(jobDto.ToBsonDocument()); _writeModels.Add(writeModel); var jobId = jobDto.Id.ToString(); return(jobId); }
public void GetJobData_ReturnsResult_WhenJobExists() { const string arrangeSql = @"insert into HANGFIRE_JOB (INVOCATIONDATA, ARGUMENTS, STATENAME, CREATEDAT) values (:invocationData, :arguments, :stateName, :createdat) returning ID into :jobid"; UseConnections((sql, connection) => { var job = Job.FromExpression(() => SampleMethod("wrong")); var param = new DynamicParameters(); param.Add(name: "invocationData", value: JobHelper.ToJson(InvocationData.Serialize(job)), direction: System.Data.ParameterDirection.Input); param.Add(name: "stateName", value: "Succeeded", direction: System.Data.ParameterDirection.Input); param.Add(name: "arguments", value: "['Arguments']", direction: System.Data.ParameterDirection.Input); param.Add(name: "createdat", value: DateTime.UtcNow, direction: System.Data.ParameterDirection.Input); param.Add(name: "jobid", dbType: System.Data.DbType.Int32, direction: System.Data.ParameterDirection.Output); sql.Execute(arrangeSql, param); var id = param.Get <int>("jobid"); string jobId = id.ToString(); var result = connection.GetJobData(jobId); Assert.NotNull(result); Assert.NotNull(result.Job); Assert.Equal("Succeeded", result.State); Assert.Equal("Arguments", result.Job.Args[0]); Assert.Null(result.LoadException); Assert.True(DateTime.UtcNow.AddMinutes(-1) < result.CreatedAt); Assert.True(result.CreatedAt < DateTime.UtcNow.AddMinutes(1)); }); }
public void Execute_HidesRecurringJob_FromScheduler_WhenJobCanNotBeLoaded() { // Arrange _context.StoppingTokenSource = new CancellationTokenSource(); SetupConnection(false); _connection.SetupSequence(x => x.GetFirstByLowestScoreFromSet("recurring-jobs", It.IsAny <double>(), It.IsAny <double>())) .Returns(RecurringJobId) .Returns((string)null); _recurringJob["Job"] = InvocationData.SerializeJob( Job.FromExpression(() => Console.WriteLine())).SerializePayload().Replace("Console", "SomeNonExistingClass"); var scheduler = CreateScheduler(); // Act scheduler.Execute(_context.Object); // Assert _transaction.Verify(x => x.SetRangeInHash(It.IsAny <string>(), It.Is <Dictionary <string, string> >(dict => dict.Count == 3 && dict["NextExecution"] == String.Empty && dict["Error"].StartsWith("Could not load the job") && dict["V"] == "2"))); _transaction.Verify(x => x.AddToSet("recurring-jobs", RecurringJobId, -1)); _transaction.Verify(x => x.Commit()); }
public override string CreateExpiredJob(Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { Guard.ArgumentNotNull(job, "job"); Guard.ArgumentNotNull(parameters, "parameters"); var invocationData = InvocationData.SerializeJob(job); var jobData = new JobDto { Id = Guid.NewGuid().ToString(), InvocationData = SerializationHelper.Serialize(invocationData, null, SerializationOption.User), Arguments = invocationData.Arguments, CreatedAt = createdAt, ExpireAt = createdAt.Add(expireIn) }; _data.Create(jobData); if (parameters.Count > 0) { var list = parameters.Select(kvp => new JobParameterDto { Id = AutoIncrementIdGenerator.GenerateId(typeof(JobParameterDto)), JobId = jobData.Id, Name = kvp.Key, Value = kvp.Value }).ToList(); jobData.Parameters = list; } return(jobData.Id); }
public override string CreateExpiredJob(Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { if (job == null) { throw new ArgumentNullException(nameof(job)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } lock (_lock) { var invocationData = InvocationData.Serialize(job); var jobDto = new LiteJob { InvocationData = SerializationHelper.Serialize(invocationData, SerializationOption.User), Arguments = invocationData.Arguments, Parameters = parameters.ToDictionary(kv => kv.Key, kv => kv.Value), CreatedAt = createdAt, ExpireAt = createdAt.Add(expireIn) }; Database.Job.Insert(jobDto); var jobId = jobDto.Id; return(jobId.ToString()); } }
public RecurringJobSchedulerFacts() { _storage = new Mock <JobStorage>(); _client = new Mock <IBackgroundJobClient>(); _instantFactory = new Mock <IScheduleInstantFactory>(); _throttler = new Mock <IThrottler>(); _token = new CancellationTokenSource().Token; // Setting up the successful path _instant = new Mock <IScheduleInstant>(); _instant.Setup(x => x.GetMatches(It.IsAny <DateTime?>())).Returns(new[] { _instant.Object.UtcTime }); _instantFactory.Setup(x => x.GetInstant(It.IsNotNull <CrontabSchedule>())) .Returns(() => _instant.Object); _recurringJob = new Dictionary <string, string> { { "Cron", "* * * * *" }, { "Job", JobHelper.ToJson(InvocationData.Serialize(Job.FromExpression(() => Console.WriteLine()))) } }; _connection = new Mock <IStorageConnection>(); _storage.Setup(x => x.GetConnection()).Returns(_connection.Object); _connection.Setup(x => x.GetAllItemsFromSet("recurring-jobs")) .Returns(new HashSet <string> { RecurringJobId }); _connection.Setup(x => x.GetAllEntriesFromHash(String.Format("recurring-job:{0}", RecurringJobId))) .Returns(_recurringJob); _client.Setup(x => x.Create(It.IsAny <Job>(), It.IsAny <IState>())).Returns("job-id"); }
public void AddOrUpdate_EnsuresExistingOldJobsAreUpdated() { // Arrange _connection.Setup(x => x.GetAllEntriesFromHash($"recurring-job:{_id}")).Returns(new Dictionary <string, string> { { "Cron", _cronExpression }, { "Job", InvocationData.Serialize(_job).SerializePayload() }, { "CreatedAt", JobHelper.SerializeDateTime(_now) }, { "NextExecution", JobHelper.SerializeDateTime(_now) }, { "Queue", "default" }, { "TimeZoneId", "UTC" }, { "LastJobId", "1384" } }); var manager = CreateManager(); // Act manager.AddOrUpdate(_id, _job, _cronExpression); // Assert _transaction.Verify(x => x.SetRangeInHash( $"recurring-job:{_id}", It.Is <Dictionary <string, string> >(dict => dict.Count == 1 && dict["V"] == "2"))); _transaction.Verify(x => x.AddToSet("recurring-jobs", _id, JobHelper.ToTimestamp(_now))); _transaction.Verify(x => x.Commit()); }
public override string CreateExpiredJob( Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { var jobId = Guid.NewGuid().ToString(); var invocationData = InvocationData.Serialize(job); // Do not modify the original parameters. var storedParameters = new Dictionary <string, string>(parameters); storedParameters.Add("Type", invocationData.Type); storedParameters.Add("Method", invocationData.Method); storedParameters.Add("ParameterTypes", invocationData.ParameterTypes); storedParameters.Add("Arguments", invocationData.Arguments); storedParameters.Add("CreatedAt", JobHelper.SerializeDateTime(createdAt)); var transaction = Redis.CreateTransaction(); transaction.HashSetAsync( string.Format(RedisStorage.Prefix + "job:{0}", jobId), storedParameters.ToHashEntries()); transaction.KeyExpireAsync( string.Format(RedisStorage.Prefix + "job:{0}", jobId), expireIn); // TODO: check return value transaction.Execute(); return(jobId); }
public void Trigger_CanTriggerRecurringJob_WithCronThatNeverFires() { // Arrange _connection.Setup(x => x.GetAllEntriesFromHash($"recurring-job:{_id}")) .Returns(new Dictionary <string, string> { { "Job", JobHelper.ToJson(InvocationData.Serialize(_job)) }, { "Cron", "0 0 31 2 *" }, }); var manager = CreateManager(); // Act manager.Trigger(_id); // Assert _stateMachine.Verify(x => x.ApplyState(It.IsAny <ApplyStateContext>())); _transaction.Verify(x => x.SetRangeInHash($"recurring-job:{_id}", It.Is <Dictionary <string, string> >(dict => dict.ContainsKey("LastExecution") && dict["LastExecution"] == JobHelper.SerializeDateTime(_now) && !dict.ContainsKey("NextExecution")))); _transaction.Verify(x => x.AddToSet("recurring-jobs", _id, -1.0D)); _transaction.Verify(x => x.Commit()); }
/// <summary> /// 创建已过期的作业 /// </summary> /// <param name="job">作业</param> /// <param name="parameters">参数字典</param> /// <param name="createdAt">创建时间</param> /// <param name="expireIn">过期时间</param> public override string CreateExpiredJob([NotNull] Job job, [NotNull] IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn) { if (job == null) { throw new ArgumentNullException(nameof(job)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } var jobId = Guid.NewGuid().ToString("n"); var invocationData = InvocationData.SerializeJob(job); // 不要修改原始参数 var storedParameters = new Dictionary <string, string>(parameters) { { "Type", invocationData.Type }, { "Method", invocationData.Method }, { "ParameterTypes", invocationData.ParameterTypes }, { "Arguments", invocationData.Arguments }, { "CreatedAt", JobHelper.SerializeDateTime(createdAt) } }; RedisClient.StartPipe() .HMSet(_storage.GetRedisKey($"job:{jobId}"), storedParameters.DicToObjectArray()) .Expire(_storage.GetRedisKey($"job:{jobId}"), expireIn) .EndPipe(); return(jobId); }
public override string CreateExpiredJob(Job job, IDictionary <string, string?> parameters, DateTime createdAt, TimeSpan expireIn) { if (job == null) { throw new ArgumentNullException(nameof(job)); } if (parameters == null) { throw new ArgumentNullException(nameof(parameters)); } InvocationData invocationData = InvocationData.SerializeJob(job); Documents.Job entityJob = new() { InvocationData = invocationData, Arguments = invocationData.Arguments, CreatedOn = createdAt, ExpireOn = createdAt.Add(expireIn), Parameters = parameters.Select(p => new Parameter { Name = p.Key, Value = p.Value }).ToArray() }; Documents.Job result = Storage.Container.CreateItemWithRetries(entityJob, PartitionKeys.Job); return(result.Id); }
/// <summary> /// Invoke synchronously. /// </summary> /// <param name="delegateInstance"></param> /// <param name="parameters"></param> public bool Invoke(Delegate delegateInstance, TimeSpan timeOut, out object result, params object[] parameters) { if (IsStarted == false) { Start(); } result = null; if (_blockingInvokeInProgress) { //SystemMonitor.Report("Another blocking invoke is already in progress."); } if (Thread.CurrentThread == _workerInternalThread) {// Invoke called from within the invoke thread, just execute directly to // evade "locking" problem (one invoke spawning another, and the other waiting for invocation). result = delegateInstance.Method.Invoke(delegateInstance.Target, parameters); return true; } _blockingInvokeInProgress = true; InvocationData data; lock (this) { data = new InvocationData(delegateInstance, parameters); _pendingInvokes.Add(data); } if (timeOut == TimeSpan.MaxValue) { if (data.CompletedEvent.WaitOne() == false) { return false; } } else { if (data.CompletedEvent.WaitOne(timeOut) == false) { return false; } } _blockingInvokeInProgress = false; result = data.Result; return true; }