/// <summary> /// Creates job execution details. /// </summary> /// <param name="schedulerGuid">The Guid of the scheduler that is running the job</param> /// <param name="startTimeUtc">The UTC start time</param> public JobExecutionDetails(Guid schedulerGuid, DateTime startTimeUtc) { this.schedulerGuid = schedulerGuid; this.startTimeUtc = DateTimeUtils.AssumeUniversalTime(startTimeUtc); statusMessage = "Unknown"; }
/// <summary> /// Gets the next job to process for the specified scheduler. /// </summary> /// <param name="clusterName">The cluster name, never null</param> /// <param name="schedulerGuid">The scheduler GUID</param> /// <param name="timeBasisUtc">The UTC time to consider as "now"</param> /// <param name="nextTriggerFireTimeUtc">Set to the UTC next trigger fire time, or null if there are /// no triggers currently scheduled to fire</param> /// <param name="schedulerExpirationTimeInSeconds">The scheduler expiration time in seconds, always greater than zero</param> /// <returns>The details of job to process or null if none</returns> /// <exception cref="SchedulerException">Thrown if an error occurs</exception> public virtual VersionedJobDetails GetNextJobToProcess(string clusterName, Guid schedulerGuid, DateTime timeBasisUtc, int schedulerExpirationTimeInSeconds, out DateTime?nextTriggerFireTimeUtc) { try { using (IDbConnection connection = CreateConnection()) { IDbCommand command = CreateStoredProcedureCommand(connection, "spSCHED_GetNextJobToProcess"); AddInputParameter(command, "ClusterName", DbType.String, clusterName); AddInputParameter(command, "SchedulerGUID", DbType.Guid, schedulerGuid); AddInputParameter(command, "TimeBasis", DbType.DateTime, timeBasisUtc); AddInputParameter(command, "SchedulerExpirationTimeInSeconds", DbType.Int32, schedulerExpirationTimeInSeconds); IDbDataParameter nextTriggerFireTimeParam = AddOutputParameter(command, "NextTriggerFireTime", DbType.DateTime); connection.Open(); VersionedJobDetails jobDetails; using (IDataReader reader = command.ExecuteReader(CommandBehavior.SingleResult | CommandBehavior.SingleRow)) { jobDetails = reader.Read() ? BuildJobDetailsFromResultSet(reader) : null; } nextTriggerFireTimeUtc = DateTimeUtils.AssumeUniversalTime(DbUtils.MapDbValueToNullable <DateTime>(nextTriggerFireTimeParam.Value)); return(jobDetails); } } catch (Exception ex) { throw new SchedulerException( "The job store was unable to get job details for the next job to process from the database.", ex); } }
public virtual int ComputeNumTimesFiredBetween(DateTime?startTimeUtc, DateTime?endTimeUtc) { startTimeUtc = DateTimeUtils.AssumeUniversalTime(startTimeUtc); endTimeUtc = DateTimeUtils.AssumeUniversalTime(endTimeUtc); TimeSpan span = endTimeUtc.Value - startTimeUtc.Value; long totalMilliseconds = (long)span.TotalMilliseconds; return((int)(totalMilliseconds / this._repeatInterval)); }
/// <summary> /// Computes the number of times fired between the two UTC date times. /// </summary> /// <param name="startTimeUtc">The UTC start date and time.</param> /// <param name="endTimeUtc">The UTC end date and time.</param> /// <returns></returns> public virtual int ComputeNumTimesFiredBetween(NullableDateTime startTimeUtc, NullableDateTime endTimeUtc) { startTimeUtc = DateTimeUtils.AssumeUniversalTime(startTimeUtc); endTimeUtc = DateTimeUtils.AssumeUniversalTime(endTimeUtc); long time = (long)(endTimeUtc.Value - startTimeUtc.Value).TotalMilliseconds; return((int)(time / _repeatInterval)); }
/// <summary> /// Creates job details for a newly created job. /// </summary> /// <param name="jobSpec">The job's specification</param> /// <param name="creationTimeUtc">The UTC time when the job was created</param> /// <exception cref="ArgumentNullException">Thrown when <paramref name="jobSpec"/> is null</exception> public JobDetails(JobSpec jobSpec, DateTime creationTimeUtc) { if (jobSpec == null) { throw new ArgumentNullException("jobSpec"); } this.jobSpec = jobSpec; this.creationTimeUtc = DateTimeUtils.AssumeUniversalTime(creationTimeUtc); }
public TriggerFiredBundle(IScheduledJob job, FluorineFx.Scheduling.Trigger trigger, bool jobIsRecovering, DateTime?fireTimeUtc, DateTime?scheduledFireTimeUtc, DateTime?prevFireTimeUtc, DateTime?nextFireTimeUtc) { this._job = job; this._trigger = trigger; this._jobIsRecovering = jobIsRecovering; this._fireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); this._scheduledFireTimeUtc = DateTimeUtils.AssumeUniversalTime(scheduledFireTimeUtc); this._prevFireTimeUtc = DateTimeUtils.AssumeUniversalTime(prevFireTimeUtc); this._nextFireTimeUtc = DateTimeUtils.AssumeUniversalTime(nextFireTimeUtc); }
public virtual DateTime?GetFireTimeBefore(DateTime?endUtc) { endUtc = DateTimeUtils.AssumeUniversalTime(endUtc); if (endUtc.Value < this.StartTimeUtc) { return(null); } int num = this.ComputeNumTimesFiredBetween(new DateTime?(this.StartTimeUtc), endUtc); return(new DateTime?(this.StartTimeUtc.AddMilliseconds((double)(num * this._repeatInterval)))); }
/// <summary> /// Returns the next UTC time at which the <see cref="Trigger" /> will /// fire, after the given UTC time. If the trigger will not fire after the given /// time, <see langword="null" /> will be returned. /// </summary> public NullableDateTime GetFireTimeAfter(NullableDateTime afterTimeUtc) { afterTimeUtc = DateTimeUtils.AssumeUniversalTime(afterTimeUtc); if (_complete) { return(null); } if ((_timesTriggered > _repeatCount) && (_repeatCount != RepeatIndefinitely)) { return(null); } if (!afterTimeUtc.HasValue) { afterTimeUtc = DateTime.UtcNow; } if (_repeatCount == 0 && afterTimeUtc.Value.CompareTo(StartTimeUtc) >= 0) { return(null); } DateTime startMillis = StartTimeUtc; DateTime afterMillis = afterTimeUtc.Value; DateTime endMillis = !EndTimeUtc.HasValue ? DateTime.MaxValue : EndTimeUtc.Value; if (endMillis <= afterMillis) { return(null); } if (afterMillis < startMillis) { return(startMillis); } long numberOfTimesExecuted = ((long)(afterMillis - startMillis).TotalMilliseconds / _repeatInterval) + 1; if ((numberOfTimesExecuted > _repeatCount) && (_repeatCount != RepeatIndefinitely)) { return(null); } DateTime time = startMillis.AddMilliseconds(numberOfTimesExecuted * _repeatInterval); if (endMillis <= time) { return(null); } return(time); }
/// <summary> /// Returns the last UTC time at which the <see cref="Trigger" /> will /// fire, before the given time. If the trigger will not fire before the /// given time, <see langword="null" /> will be returned. /// </summary> public virtual NullableDateTime GetFireTimeBefore(NullableDateTime endUtc) { endUtc = DateTimeUtils.AssumeUniversalTime(endUtc); if (endUtc.Value < StartTimeUtc) { return(null); } int numFires = ComputeNumTimesFiredBetween(StartTimeUtc, endUtc); return(StartTimeUtc.AddMilliseconds(numFires * _repeatInterval)); }
/// <summary> /// Builds a job details object from the result set returned by the spSCHED_GetJobDetails /// and spSCHED_GetNextJob stored procedures. /// </summary> /// <param name="reader">The reader for the result set</param> /// <returns>The job details object</returns> protected virtual VersionedJobDetails BuildJobDetailsFromResultSet(IDataReader reader) { string jobName = reader.GetString(0); string jobDescription = reader.GetString(1); string jobKey = reader.GetString(2); Trigger trigger = (Trigger)DbUtils.DeserializeObject(DbUtils.MapDbValueToObject <byte[]>(reader.GetValue(3))); JobData jobData = (JobData)DbUtils.DeserializeObject(DbUtils.MapDbValueToObject <byte[]>(reader.GetValue(4))); DateTime creationTimeUtc = DateTimeUtils.AssumeUniversalTime(reader.GetDateTime(5)); JobState jobState = (JobState)reader.GetInt32(6); DateTime?nextTriggerFireTimeUtc = DateTimeUtils.AssumeUniversalTime(DbUtils.MapDbValueToNullable <DateTime>(reader.GetValue(7))); int? nextTriggerMisfireThresholdSeconds = DbUtils.MapDbValueToNullable <int>(reader.GetValue(8)); TimeSpan?nextTriggerMisfireThreshold = nextTriggerMisfireThresholdSeconds.HasValue ? new TimeSpan(0, 0, nextTriggerMisfireThresholdSeconds.Value) : (TimeSpan?)null; Guid? lastExecutionSchedulerGuid = DbUtils.MapDbValueToNullable <Guid>(reader.GetValue(9)); DateTime?lastExecutionStartTimeUtc = DateTimeUtils.AssumeUniversalTime(DbUtils.MapDbValueToNullable <DateTime>(reader.GetValue(10))); DateTime?lastExecutionEndTimeUtc = DateTimeUtils.AssumeUniversalTime(DbUtils.MapDbValueToNullable <DateTime>(reader.GetValue(11))); bool? lastExecutionSucceeded = DbUtils.MapDbValueToNullable <bool>(reader.GetValue(12)); string lastExecutionStatusMessage = DbUtils.MapDbValueToObject <string>(reader.GetValue(13)); int version = reader.GetInt32(14); JobSpec jobSpec = new JobSpec(jobName, jobDescription, jobKey, trigger); jobSpec.JobData = jobData; VersionedJobDetails details = new VersionedJobDetails(jobSpec, creationTimeUtc, version); details.JobState = jobState; details.NextTriggerFireTimeUtc = nextTriggerFireTimeUtc; details.NextTriggerMisfireThreshold = nextTriggerMisfireThreshold; if (lastExecutionSchedulerGuid.HasValue && lastExecutionStartTimeUtc.HasValue) { JobExecutionDetails execution = new JobExecutionDetails(lastExecutionSchedulerGuid.Value, lastExecutionStartTimeUtc.Value); execution.EndTimeUtc = lastExecutionEndTimeUtc; execution.Succeeded = lastExecutionSucceeded.GetValueOrDefault(); execution.StatusMessage = lastExecutionStatusMessage == null ? "" : lastExecutionStatusMessage; details.LastJobExecutionDetails = execution; } return(details); }
/// <summary> /// Initializes a new instance of the <see cref="TriggerFiredBundle"/> class. /// </summary> /// <param name="job">The job.</param> /// <param name="trigger">The trigger.</param> /// <param name="jobIsRecovering">if set to <c>true</c> [job is recovering].</param> /// <param name="fireTimeUtc">The fire time.</param> /// <param name="scheduledFireTimeUtc">The scheduled fire time.</param> /// <param name="prevFireTimeUtc">The previous fire time.</param> /// <param name="nextFireTimeUtc">The next fire time.</param> public TriggerFiredBundle(IScheduledJob job, Trigger trigger, bool jobIsRecovering, NullableDateTime fireTimeUtc, NullableDateTime scheduledFireTimeUtc, NullableDateTime prevFireTimeUtc, NullableDateTime nextFireTimeUtc) { _job = job; _trigger = trigger; _jobIsRecovering = jobIsRecovering; _fireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); _scheduledFireTimeUtc = DateTimeUtils.AssumeUniversalTime(scheduledFireTimeUtc); _prevFireTimeUtc = DateTimeUtils.AssumeUniversalTime(prevFireTimeUtc); _nextFireTimeUtc = DateTimeUtils.AssumeUniversalTime(nextFireTimeUtc); }
public DateTime?GetFireTimeAfter(DateTime?afterTimeUtc) { afterTimeUtc = DateTimeUtils.AssumeUniversalTime(afterTimeUtc); if (this._complete) { return(null); } if ((this._timesTriggered > this._repeatCount) && (this._repeatCount != -1)) { return(null); } if (!afterTimeUtc.HasValue) { afterTimeUtc = new DateTime?(DateTime.UtcNow); } if ((this._repeatCount == 0) && (afterTimeUtc.Value.CompareTo(this.StartTimeUtc) >= 0)) { return(null); } DateTime startTimeUtc = this.StartTimeUtc; DateTime time2 = afterTimeUtc.Value; DateTime?endTimeUtc = this.EndTimeUtc; DateTime time3 = !endTimeUtc.HasValue ? DateTime.MaxValue : (endTimeUtc = this.EndTimeUtc).Value; if (time3 <= time2) { return(null); } if (time2 < startTimeUtc) { return(new DateTime?(startTimeUtc)); } TimeSpan span = (TimeSpan)(time2 - startTimeUtc); long num = (((long)span.TotalMilliseconds) / this._repeatInterval) + 1L; if ((num > this._repeatCount) && (this._repeatCount != -1)) { return(null); } DateTime time4 = startTimeUtc.AddMilliseconds((double)(num * this._repeatInterval)); if (time3 <= time4) { return(null); } return(new DateTime?(time4)); }
/// <summary> /// Creates a periodic trigger. /// </summary> /// <param name="startTimeUtc">The UTC date and time when the trigger will first fire</param> /// <param name="endTimeUtc">The UTC date and time when the trigger must stop firing. /// If the time is set to null, the trigger may continue firing indefinitely.</param> /// <param name="period">The recurrence period of the trigger. /// If the period is set to null, the trigger will fire exactly once /// and never recur.</param> /// <param name="jobExecutionCount">The number of job executions remaining before the trigger /// stops firing. This number is decremented each time the job executes /// until it reaches zero. If the count is set to null, the number of times the job /// may execute is unlimited.</param> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="period"/> is negative or zero</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown if <paramref name="jobExecutionCount"/> is negative</exception> public PeriodicTrigger(DateTime startTimeUtc, DateTime?endTimeUtc, TimeSpan?period, int?jobExecutionCount) { if (period.HasValue && period.Value.Ticks <= 0) { throw new ArgumentOutOfRangeException("period", "The recurrence period must not be negative or zero."); } if (jobExecutionCount.HasValue && jobExecutionCount.Value < 0) { throw new ArgumentOutOfRangeException("jobExecutionCount", "The job execution count remaining must not be negative."); } this.startTimeUtc = DateTimeUtils.AssumeUniversalTime(startTimeUtc); this.endTimeUtc = DateTimeUtils.AssumeUniversalTime(endTimeUtc); this.period = period; jobExecutionCountRemaining = jobExecutionCount; isFirstTime = true; misfireAction = DefaultMisfireAction; }
/// <inheritdoc /> public override TriggerScheduleAction Schedule(TriggerScheduleCondition condition, DateTime timeBasisUtc, JobExecutionDetails lastJobExecutionDetails) { timeBasisUtc = DateTimeUtils.AssumeUniversalTime(timeBasisUtc); switch (condition) { case TriggerScheduleCondition.Latch: return(ScheduleSuggestedAction(TriggerScheduleAction.Skip, timeBasisUtc)); case TriggerScheduleCondition.Misfire: isFirstTime = false; return(ScheduleSuggestedAction(misfireAction, timeBasisUtc)); case TriggerScheduleCondition.Fire: isFirstTime = false; return(ScheduleSuggestedAction(TriggerScheduleAction.ExecuteJob, timeBasisUtc)); default: throw new SchedulerException(String.Format(CultureInfo.CurrentCulture, "Unrecognized trigger schedule condition '{0}'.", condition)); } }
/// <summary> /// Set the previous UTC time at which the <see cref="SimpleTrigger" /> fired. /// <strong>This method should not be invoked by client code.</strong> /// </summary> public virtual void SetPreviousFireTime(NullableDateTime fireTimeUtc) { _previousFireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); }
public void AssumeUniversalTime_NonNull() { DateTimeAssert.AreEqualIncludingKind(new DateTime(2000, 3, 4, 0, 0, 0, DateTimeKind.Utc), DateTimeUtils.AssumeUniversalTime((DateTime?)new DateTime(2000, 3, 4))); }
public void SetNextFireTime(DateTime?fireTimeUtc) { this._nextFireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); }
public virtual void SetPreviousFireTime(DateTime?fireTimeUtc) { this._previousFireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); }
public void AssumeUniversalTime_Null() { Assert.IsNull(DateTimeUtils.AssumeUniversalTime(null)); }
/// <summary> /// Set the next UTC time at which the <see cref="SimpleTrigger" /> should fire. /// <strong>This method should not be invoked by client code.</strong> /// </summary> public void SetNextFireTime(NullableDateTime fireTimeUtc) { _nextFireTimeUtc = DateTimeUtils.AssumeUniversalTime(fireTimeUtc); }