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());
        }
Example #2
0
        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("");
        }
Example #4
0
        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);
        }
Example #10
0
        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);
                    }
                }
            }
        }
Example #11
0
        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));
            });
        }
Example #13
0
        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);
        }
Example #14
0
        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));
            });
        }
Example #20
0
        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());
            }
        }
Example #25
0
        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);
        }
Example #30
0
    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;
        }