View Javadoc
1   /*
2    * Copyright 2012-2021 CodeLibs Project and the Others.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13   * either express or implied. See the License for the specific language
14   * governing permissions and limitations under the License.
15   */
16  package org.codelibs.fess.helper;
17  
18  import java.util.HashMap;
19  import java.util.Map;
20  
21  import org.apache.logging.log4j.LogManager;
22  import org.apache.logging.log4j.Logger;
23  import org.codelibs.core.lang.StringUtil;
24  import org.codelibs.core.timer.TimeoutManager;
25  import org.codelibs.core.timer.TimeoutTarget;
26  import org.codelibs.core.timer.TimeoutTask;
27  import org.codelibs.fess.Constants;
28  import org.codelibs.fess.es.config.exbhv.JobLogBhv;
29  import org.codelibs.fess.es.config.exbhv.ScheduledJobBhv;
30  import org.codelibs.fess.es.config.exentity.JobLog;
31  import org.codelibs.fess.es.config.exentity.ScheduledJob;
32  import org.codelibs.fess.exception.ScheduledJobException;
33  import org.codelibs.fess.mylasta.direction.FessConfig;
34  import org.codelibs.fess.util.ComponentUtil;
35  import org.dbflute.optional.OptionalThing;
36  import org.lastaflute.job.JobManager;
37  import org.lastaflute.job.LaCron;
38  import org.lastaflute.job.LaJobRuntime;
39  import org.lastaflute.job.LaScheduledJob;
40  import org.lastaflute.job.key.LaJobUnique;
41  import org.lastaflute.job.subsidiary.CronParamsSupplier;
42  
43  public class JobHelper {
44      private static final Logger logger = LogManager.getLogger(JobHelper.class);
45  
46      protected int monitorInterval = 60 * 60;// 1hour
47  
48      protected ThreadLocal<LaJobRuntime> jobRuntimeLocal = new ThreadLocal<>();
49  
50      public void register(final ScheduledJob scheduledJob) {
51          final JobManager jobManager = ComponentUtil.getJobManager();
52          jobManager.schedule(cron -> register(cron, scheduledJob));
53      }
54  
55      public void register(final LaCron cron, final ScheduledJob scheduledJob) {
56          if (scheduledJob == null) {
57              throw new ScheduledJobException("No job.");
58          }
59  
60          final String id = scheduledJob.getId();
61          if (!Constants.T.equals(scheduledJob.getAvailable())) {
62              logger.info("Inactive Job {}:{}", id, scheduledJob.getName());
63              try {
64                  unregister(scheduledJob);
65              } catch (final Exception e) {
66                  if (logger.isDebugEnabled()) {
67                      logger.debug("Failed to delete Job {}", scheduledJob, e);
68                  }
69              }
70              return;
71          }
72  
73          final FessConfig fessConfig = ComponentUtil.getFessConfig();
74          final CronParamsSupplier paramsOp = () -> {
75              final Map<String, Object> params = new HashMap<>();
76              ComponentUtil.getComponent(ScheduledJobBhv.class).selectByPK(scheduledJob.getId())
77                      .ifPresent(e -> params.put(Constants.SCHEDULED_JOB, e)).orElse(() -> {
78                          logger.warn("Job {} is not found.", scheduledJob.getId());
79                      });
80              return params;
81          };
82          findJobByUniqueOf(LaJobUnique.of(id)).ifPresent(job -> {
83              if (!job.isUnscheduled()) {
84                  if (StringUtil.isNotBlank(scheduledJob.getCronExpression())) {
85                      logger.info("Starting Job {}:{}", id, scheduledJob.getName());
86                      final String cronExpression = scheduledJob.getCronExpression();
87                      job.reschedule(cronExpression, op -> op.changeNoticeLogToDebug().params(paramsOp));
88                  } else {
89                      logger.info("Inactive Job {}:{}", id, scheduledJob.getName());
90                      job.becomeNonCron();
91                  }
92              } else if (StringUtil.isNotBlank(scheduledJob.getCronExpression())) {
93                  logger.info("Starting Job {}:{}", id, scheduledJob.getName());
94                  final String cronExpression = scheduledJob.getCronExpression();
95                  job.reschedule(cronExpression, op -> op.changeNoticeLogToDebug().params(paramsOp));
96              }
97          }).orElse(() -> {
98              if (StringUtil.isNotBlank(scheduledJob.getCronExpression())) {
99                  logger.info("Starting Job {}:{}", id, scheduledJob.getName());
100                 final String cronExpression = scheduledJob.getCronExpression();
101                 cron.register(cronExpression, fessConfig.getSchedulerJobClassAsClass(), fessConfig.getSchedulerConcurrentExecModeAsEnum(),
102                         op -> op.uniqueBy(id).changeNoticeLogToDebug().params(paramsOp));
103             } else {
104                 logger.info("Inactive Job {}:{}", id, scheduledJob.getName());
105                 cron.registerNonCron(fessConfig.getSchedulerJobClassAsClass(), fessConfig.getSchedulerConcurrentExecModeAsEnum(),
106                         op -> op.uniqueBy(id).changeNoticeLogToDebug().params(paramsOp));
107             }
108         });
109     }
110 
111     private OptionalThing<LaScheduledJob> findJobByUniqueOf(final LaJobUnique jobUnique) {
112         final JobManager jobManager = ComponentUtil.getJobManager();
113         try {
114             return jobManager.findJobByUniqueOf(jobUnique);
115         } catch (final Exception e) {
116             return OptionalThing.empty();
117         }
118     }
119 
120     public void unregister(final ScheduledJob scheduledJob) {
121         try {
122             final JobManager jobManager = ComponentUtil.getJobManager();
123             if (jobManager.isSchedulingDone()) {
124                 jobManager.findJobByUniqueOf(LaJobUnique.of(scheduledJob.getId())).ifPresent(job -> {
125                     job.unschedule();
126                 }).orElse(() -> logger.debug("Job {} is not scheduled.", scheduledJob.getId()));
127             }
128         } catch (final Exception e) {
129             throw new ScheduledJobException("Failed to delete Job: " + scheduledJob, e);
130         }
131     }
132 
133     public void remove(final ScheduledJob scheduledJob) {
134         try {
135             final JobManager jobManager = ComponentUtil.getJobManager();
136             if (jobManager.isSchedulingDone()) {
137                 jobManager.findJobByUniqueOf(LaJobUnique.of(scheduledJob.getId())).ifPresent(job -> {
138                     job.disappear();
139                 }).orElse(() -> logger.debug("Job {} is not scheduled.", scheduledJob.getId()));
140             }
141         } catch (final Exception e) {
142             throw new ScheduledJobException("Failed to delete Job: " + scheduledJob, e);
143         }
144     }
145 
146     public boolean isAvailable(final String id) {
147         return ComponentUtil.getComponent(ScheduledJobBhv.class).selectByPK(id).filter(e -> Boolean.TRUE.equals(e.getAvailable()))
148                 .isPresent();
149     }
150 
151     public void store(final JobLog jobLog) {
152         ComponentUtil.getComponent(JobLogBhv.class).insertOrUpdate(jobLog, op -> {
153             op.setRefreshPolicy(Constants.TRUE);
154         });
155     }
156 
157     public TimeoutTask startMonitorTask(final JobLog jobLog) {
158         final TimeoutTarget target = new MonitorTarget(jobLog);
159         return TimeoutManager.getInstance().addTimeoutTarget(target, monitorInterval, true);
160     }
161 
162     public void setMonitorInterval(final int monitorInterval) {
163         this.monitorInterval = monitorInterval;
164     }
165 
166     static class MonitorTarget implements TimeoutTarget {
167 
168         private final JobLog jobLog;
169 
170         public MonitorTarget(final JobLog jobLog) {
171             this.jobLog = jobLog;
172         }
173 
174         @Override
175         public void expired() {
176             if (jobLog.getEndTime() == null) {
177                 jobLog.setLastUpdated(ComponentUtil.getSystemHelper().getCurrentTimeAsLong());
178                 if (logger.isDebugEnabled()) {
179                     logger.debug("Update {}", jobLog);
180                 }
181                 ComponentUtil.getComponent(JobLogBhv.class).insertOrUpdate(jobLog, op -> {
182                     op.setRefreshPolicy(Constants.TRUE);
183                 });
184             }
185         }
186 
187     }
188 
189     public void setJobRuntime(final LaJobRuntime runtime) {
190         jobRuntimeLocal.set(runtime);
191     }
192 
193     public LaJobRuntime getJobRuntime() {
194         return jobRuntimeLocal.get();
195     }
196 }