XQuery/XQuery 批量作业
您想定期运行 XQuery 作业。
我们将使用 eXist 作业调度程序。eXist 作业调度程序是围绕 Quartz 系统构建的,eXist 为此系统提供了一个 XQuery API 来添加和删除作业。
如果您有一个需要定期运行的作业,您只需在 $EXIST_HOME/conf.xml 文件中添加一行。例如,如果您有一个简单的 XQuery 脚本将 dateTime 时间戳写入日志文件,您可以添加以下行
这行表示当每分钟、每小时、每月的每一天、每月的每一天和每周的每一天的秒数为 0 时,运行此作业。
<!-- run hello world to a log file every minute
Fields are: Sec, Min, Hrs, Day-of-Month, Month, Day-of-Week
-->
<job xquery="/db/test/sched/datetime-logger.xq" cron-trigger="0 * * * * ?"/>
xquery version "1.0";
(: append the current date and time to the log file :)
let $datetime := current-dateTime()
let $message := concat('Current date-time : ', $datetime)
let $log := util:log-system-out($message)
return
<results>
<log>{$message}</log>
</results>
(Line: 7) Current date-time: 2011-07-18T15:58:00-05:00 (Line: 7) Current date-time: 2011-07-18T15:59:00-05:00
将以下行添加到您的 $EXIST_HOME/conf.xml 文件中。
<!-- optimize the Lucene Indexes at 10:15AM Monday -->
<job xquery="/db/system/jobs/optimize-lucene-indexes.xq" cron-trigger="0 15 10 * * MON"/>
/db/system/jobs/optimize-lucene-indexes.xq 的内容
xquery version "1.0";
(: run the Lucene Optimize function after new content has been loaded :)
let $login := xmldb:login('/db', 'admin', 'YOUR-ADMIN-PASSWORD')
let $log-start := util:log-system-out(concat('Starting Lucene Optimize at :', current-dateTime()))
let $start-time := util:system-time()
let $optomize := ft:optimize()
let $end-time := util:system-time()
let $runtimems := (($end-time - $start-time) div xs:dayTimeDuration('PT1S')) * 1000
let $log-end := util:log-system-out(concat('Finished Lucene Optimize at :', current-dateTime()))
return
<results>
<message>Finished ft:optimize() in {$runtimems} ms</message>
</results>
在这种方法中,我们将使用 XQuery API 从作业调度程序中添加、查看和删除作业。
要启用 XQuery 调度程序,您可能需要在 $EXIST_HOME/extensions 中设置一行
include.module.scheduler = true
然后键入“build”重新编译代码。
还要确保 $EXIST_HOME/conf.xml 中的行未被注释掉。
<module uri="http://exist-db.org/xquery/scheduler" class="org.exist.xquery.modules.scheduler.SchedulerModule" />
以下是添加和删除作业的两个函数。
scheduler:schedule-xquery-cron-job($xquery-path, $cron-string, $job-id) scheduler:delete-scheduled-job($job-id)
注意:您必须确保您的系统中启用了 XQuery 作业调度程序模块。您可以通过以下 XQuery 验证这一点
cron 字符串的格式在 [1] 中有记录
您可以使用 scheduler:get-scheduled-jobs() XQuery 函数获取所有已安排作业的列表。这将返回一个具有以下格式的文档
<scheduler:jobs count="5" xmlns:scheduler="http://exist-db.org/xquery/scheduler">
<scheduler:group name="eXist.System">
<scheduler:job name="Sync">
<scheduler:trigger name="Sync Trigger">
<expression>2500</expression>
<state>1</state>
<start>2012-09-14T15:48:24.724Z</start>
<end/>
<previous>2012-09-25T17:31:12.224Z</previous>
<next>2012-09-25T17:31:13.57Z</next>
<final/>
</scheduler:trigger>
</scheduler:job>
</scheduler:group>
<scheduler:group name="eXist.User">
<scheduler:job name="REST_TimeoutCheck">
<scheduler:trigger name="REST_TimeoutCheck Trigger">
<expression>2000</expression>
<state>1</state>
<start>2012-09-14T15:48:25.337Z</start>
<end/>
<previous>2012-09-25T17:31:13.337Z</previous>
<next>2012-09-25T17:31:13.57Z</next>
<final/>
</scheduler:trigger>
</scheduler:job>
</scheduler:group>
以下是添加和删除作业的系统调用的示例
xquery version "1.0";
(: unit test to add a datetime logger job to the job scheduler
to monitor this you can do $tail -f $EXIST_HOME/webapp/WEB-INF/logs/exist.log :)
let $xquery-path := '/db/dma/apps/job-scheduler/scripts/log-datetime.xq'
(: run the logger every minute :)
let $cron := '0 * * * * ?'
(: https://wikibooks.cn/wiki/XQuery/XQuery_Batch_Jobs :)
let $add := scheduler:schedule-xquery-cron-job($xquery-path, $cron, 'Test of Schedule XQuery Cron Job')
return
<results>
<xquery-path>{$xquery-path}</xquery-path>
<cron>{$cron}</cron>
<result>{$add}</result>
</results>
有时您希望频繁运行轮询远程站点的作业,例如每五分钟一次。如果它找到一个文件,它可能希望传输文件。但有时传输文件的时间长于轮询频率。这将重新启动作业。
为了解决这个问题,您有两个选择。一个是能够配置 eXist 以不运行并发作业。这在 2.1 中不可用。在这种情况下,您可能需要设置一个标志来测试之前的作业是否已完成。您可以使用缓存模块为每个作业设置一个标志。
以下显示了如何使用 put/get 和 remove 函数来管理跨查询的全局状态
let $job-id := request:get-parameter('job-id', 'poll-customer-123')
let $delete := xs:boolean(request:get-parameter('delete', 'false'))
return
if ($delete)
then
let $remove := cache:remove('running-jobs', $job-id)
return <result><message>Job {$job-id} has finsihed.</message></result>
else
if (cache:get('running-jobs', $job-id) = 'true')
then <result><message>Job {$job-id} is already running.</message></result> (: if the job is running then exit :)
else
(: continue :)
let $set-running-flag := cache:put('running-jobs', $job-id, 'true')
return
<result>
<message>Job {$job-id} has been started</message>
</result>