在 ColdFusion 9 中,有没有一种快速的方法来找出计划任务下次尝试运行的时间?
问问题
1209 次
1 回答
5
我宁愿调用较低级别的 API 或类似的方法让 CF 以与通常相同的方式计算它。我已经抛弃了各种服务,但没有发现明显的调用方法会有所帮助。
AFAIK,没有单一的解决方案。CF 用来计算日期的主要方法是CronTabEntry.NextRunTime
. 该类CronTabEntry
表示单个任务的设置。方法根据任务的设置NextRunTime
计算下一个可能的运行日期。过期和暂停任务的处理在运行时在别处完成。
要复制结果,您需要调用NextRunTime
并添加一些逻辑来处理过期任务。虽然NextRunTime
方法是私有的,但它仍然可以在Method.setAccessible(boolean)的帮助下通过反射访问。
我把下面的函数放在一起来演示。其中大部分是反射调用(在 CF 中它比它的 java 等价物更冗长)。无论如何,它应该返回 CF 调度程序使用的相同日期。
规则:
- 如果任务结束日期/时间已过,则返回一个空字符串“”
- 如果是一次性任务,已经执行,返回空字符串“”
- 对于所有其他任务(包括暂停的任务),返回下一个计划日期
用法:
result = new TaskUtil().getNextRunTime("SomeTask");
WriteDump(result);
氟氯化碳
component {
public struct function getNextRunTime(required string scheduledTaskName) {
// load task settings from factory
local.cron = createobject("java","coldfusion.server.ServiceFactory").getCronService();
local.task = local.cron.findTask( arguments.scheduledTaskName );
// abort if we cannot find the task ..
if ( isNull(local.task) ) {
throw ("The specified task was not found: ["& arguments.scheduledTaskName &"]");
}
// Calculate the next POTENTIAL schedule date
local.isRecurring = listFindNoCase("daily,weekly,monthly", local.task.interval);
local.dateClass = createObject("java", "java.util.Date").getClass();
local.longClass = createObject("java", "java.lang.Long").TYPE;
local.stringClass = createObject("java", "java.lang.String").getClass();
// Construct the appropriate arguments
// Note: must load arguments / class types into arrays for java reflection
if (local.isRecurring) {
local.args = [ local.task.getStartDate(), local.task.getStartTime(), local.task.interval ];
local.types = [ local.dateClass, local.dateClass, local.stringClass ];
}
else {
local.args = [ local.task.getStartDate(), local.task.getStartTime(), local.task.getEndTime(), javacast("long", val(local.task.interval) * 1000) ];
local.types = [ local.dateClass, local.dateClass, local.dateClass, local.longClass ];
}
// Call CF's internal method to calculate the next date (UNDOCUMENTED)
local.internalMethod = local.task.getClass().getDeclaredMethod("NextRunTime", local.types );
local.internalMethod.setAccessible( true );
local.nextRunOnDate = local.internalMethod.invoke( local.task, local.args );
// Determine if the task will be rescheduled
local.isExpired = false;
if ( local.task.interval != "once" && structKeyExists( local.task, "end_date") ) {
// It is non-recurring, so determine if it already expired
local.expiresOnDate = local.task.mergeDates( local.task.getEndDate(), local.task.getEndTime() );
local.isExpired = dateCompare( local.nextRunOnDate, local.expiresOnDate, "s") >= 0;
}
else if ( local.task.interval == "once" && local.task.disabled) {
// It is a one time task that already executed
local.isExpired = true;
}
// construct and return results
local.result = {};
local.result.name = local.task.task;
local.result.isPaused = local.task.paused;
local.result.isExpired = local.isExpired;
local.result.nextRunTime = local.isExpired ? "" : local.nextRunOnDate;
return local.result;
}
}
于 2012-05-25T08:20:17.160 回答