diff --git a/pom.xml b/pom.xml index 07656aaba..8479c2723 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.codelibs.fess fess @@ -40,8 +41,9 @@ 1.1.1 - 0.7.8-RC2 + 0.7.9-RC2 0.6.8 + 0.2.0-RCB 3.1.0 2.3.1 0.4.8 @@ -58,7 +60,7 @@ 0.6.0E - 1.0.2 + 1.0.3-SNAPSHOT 2.1.1 @@ -75,7 +77,7 @@ ${packaging.fess.home.dir}/app ${packaging.fess.home.dir}/bin /etc/fess - /var/lib/fess + /var/lib/fess ${packaging.fess.home.dir}/lib /var/log/fess /var/tmp/fess @@ -95,7 +97,7 @@ - src/packaging/common/packaging.properties @@ -759,9 +761,9 @@ - org.quartz-scheduler - quartz - 2.2.2 + org.lastaflute.job + lasta-job + ${lasta.job.version} diff --git a/src/main/java/org/codelibs/fess/Constants.java b/src/main/java/org/codelibs/fess/Constants.java index 920d98094..b2b4266e7 100644 --- a/src/main/java/org/codelibs/fess/Constants.java +++ b/src/main/java/org/codelibs/fess/Constants.java @@ -56,6 +56,8 @@ public class Constants extends CoreLibConstants { public static final String FAIL = "fail"; + public static final String STOP = "stop"; + public static final String ITEM_LABEL = "label"; public static final String ITEM_VALUE = "value"; @@ -66,13 +68,13 @@ public class Constants extends CoreLibConstants { public static final String MS932 = "MS932"; - public static final String DEFAULT_CRON_EXPRESSION = "0 0 0 * * ?"; + public static final String DEFAULT_CRON_EXPRESSION = "0 0 * * *"; - public static final String DEFAULT_SEARCH_LOG_CRON_EXPRESSION = "0 * * * * ?"; + public static final String DEFAULT_SEARCH_LOG_CRON_EXPRESSION = "* * * * *"; - public static final String DEFAULT_DAILY_CRON_EXPRESSION = "0 0 0 * * ?"; + public static final String DEFAULT_DAILY_CRON_EXPRESSION = "0 0 * * *"; - public static final String DEFAULT_HOURLY_CRON_EXPRESSION = "0 0 * * * ?"; + public static final String DEFAULT_HOURLY_CRON_EXPRESSION = "0 * * * *"; public static final int DEFAULT_INTERVAL_TIME_FOR_FS = 1000; @@ -279,12 +281,9 @@ public class Constants extends CoreLibConstants { public static final String OPTION_QUERY_NQ = "nq"; // job - public static final String JOB_ID_PREFIX = "job"; public static final String SCHEDULED_JOB = "scheduledJob"; - public static final String JOB_EXECUTOR_TYPE = "jobExecutor"; - public static final String DEFAULT_JOB_TARGET = "all"; public static final String DEFAULT_JOB_SCRIPT_TYPE = "groovy"; diff --git a/src/main/java/org/codelibs/fess/app/job/AllJobScheduler.java b/src/main/java/org/codelibs/fess/app/job/AllJobScheduler.java new file mode 100644 index 000000000..edb742408 --- /dev/null +++ b/src/main/java/org/codelibs/fess/app/job/AllJobScheduler.java @@ -0,0 +1,101 @@ +/* + * Copyright 2012-2016 CodeLibs Project and the Others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.codelibs.fess.app.job; + +import javax.annotation.Resource; + +import org.codelibs.core.lang.StringUtil; +import org.codelibs.fess.Constants; +import org.codelibs.fess.app.logic.AccessContextLogic; +import org.codelibs.fess.app.service.ScheduledJobService; +import org.codelibs.fess.es.config.exbhv.JobLogBhv; +import org.codelibs.fess.helper.SystemHelper; +import org.codelibs.fess.mylasta.direction.FessConfig; +import org.codelibs.fess.util.ComponentUtil; +import org.dbflute.optional.OptionalThing; +import org.lastaflute.core.time.TimeManager; +import org.lastaflute.di.core.exception.TooManyRegistrationComponentException; +import org.lastaflute.di.core.smart.hot.HotdeployUtil; +import org.lastaflute.job.LaCron; +import org.lastaflute.job.LaJob; +import org.lastaflute.job.LaJobRunner; +import org.lastaflute.job.LaJobRuntime; +import org.lastaflute.job.LaJobScheduler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AllJobScheduler implements LaJobScheduler { + private static final Logger logger = LoggerFactory.getLogger(AllJobScheduler.class); + + protected static final String APP_TYPE = "JOB"; + + @Resource + private TimeManager timeManager; + + @Resource + private FessConfig fessConfig; + + @Resource + private AccessContextLogic accessContextLogic; + + @Resource + private ScheduledJobService scheduledJobService; + + @Resource + private SystemHelper systemHelper; + + protected Class jobClass = ScriptExecutorJob.class; + + @Override + public void schedule(LaCron cron) { + scheduledJobService.start(cron); + + final String myName = fessConfig.getSchedulerTargetName(); + if (StringUtil.isNotBlank(myName)) { + ComponentUtil.getComponent(JobLogBhv.class).queryDelete(cb -> { + cb.query().setJobStatus_Equal(Constants.RUNNING); + cb.query().setTarget_Equal(myName); + }); + } + + } + + @Override + public LaJobRunner createRunner() { + return new LaJobRunner() { + @Override + protected boolean isSuppressHotdeploy() { // TODO workaround + return true; + } + + @Override + protected void actuallyRun(Class jobType, LaJobRuntime runtime) { // TODO workaround + try { + super.actuallyRun(jobType, runtime); + } catch (TooManyRegistrationComponentException e) { + if (HotdeployUtil.isHotdeploy()) { + logger.warn("Failed to start job {}", jobType); + } else { + throw e; + } + } + } + }.useAccessContext(resource -> { + return accessContextLogic.create(resource, () -> OptionalThing.empty(), () -> OptionalThing.empty(), () -> APP_TYPE); + }); + } + +} diff --git a/src/main/java/org/codelibs/fess/job/TriggeredJob.java b/src/main/java/org/codelibs/fess/app/job/ScriptExecutorJob.java similarity index 69% rename from src/main/java/org/codelibs/fess/job/TriggeredJob.java rename to src/main/java/org/codelibs/fess/app/job/ScriptExecutorJob.java index d8160fd54..babac6cee 100644 --- a/src/main/java/org/codelibs/fess/job/TriggeredJob.java +++ b/src/main/java/org/codelibs/fess/app/job/ScriptExecutorJob.java @@ -13,50 +13,44 @@ * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ -package org.codelibs.fess.job; +package org.codelibs.fess.app.job; import org.codelibs.fess.Constants; import org.codelibs.fess.app.service.JobLogService; import org.codelibs.fess.es.config.exentity.JobLog; import org.codelibs.fess.es.config.exentity.ScheduledJob; -import org.codelibs.fess.helper.JobHelper; import org.codelibs.fess.helper.SystemHelper; +import org.codelibs.fess.job.JobExecutor; +import org.codelibs.fess.job.ScheduledJobException; import org.codelibs.fess.util.ComponentUtil; import org.lastaflute.di.core.SingletonLaContainer; -import org.quartz.Job; -import org.quartz.JobDataMap; -import org.quartz.JobExecutionContext; -import org.quartz.JobExecutionException; +import org.lastaflute.job.JobManager; +import org.lastaflute.job.LaJob; +import org.lastaflute.job.LaJobRuntime; +import org.lastaflute.job.key.LaJobUnique; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TriggeredJob implements Job { - private static final Logger logger = LoggerFactory.getLogger(TriggeredJob.class); +public class ScriptExecutorJob implements LaJob { + private static final Logger logger = LoggerFactory.getLogger(ScriptExecutorJob.class); @Override - public void execute(final JobExecutionContext context) throws JobExecutionException { - final JobDataMap data = context.getMergedJobDataMap(); - final ScheduledJob scheduledJob = (ScheduledJob) data.get(Constants.SCHEDULED_JOB); - - execute(scheduledJob); - } - - public void execute(final ScheduledJob scheduledJob) { + public void run(LaJobRuntime runtime) { + final ScheduledJob scheduledJob = (ScheduledJob) runtime.getParameterMap().get(Constants.SCHEDULED_JOB); // TODO null check final SystemHelper systemHelper = ComponentUtil.getSystemHelper(); - final JobHelper jobHelper = ComponentUtil.getJobHelper(); + final JobManager jobManager = ComponentUtil.getJobManager(); final JobLog jobLog = new JobLog(scheduledJob); final String scriptType = scheduledJob.getScriptType(); final String script = scheduledJob.getScriptData(); final String id = scheduledJob.getId(); - final String jobId = Constants.JOB_ID_PREFIX + id; final JobExecutor jobExecutor = ComponentUtil.getJobExecutor(scriptType); if (jobExecutor == null) { throw new ScheduledJobException("No jobExecutor: " + scriptType); } - if (jobHelper.startJobExecutoer(id, jobExecutor) != null) { + if (!jobManager.findJobByUniqueOf(LaJobUnique.of(id)).isPresent()) { if (logger.isDebugEnabled()) { - logger.debug(jobId + " is running."); + logger.debug("Job " + id + " is running."); } return; } @@ -67,29 +61,28 @@ public class TriggeredJob implements Job { } if (logger.isDebugEnabled()) { - logger.debug("Starting Job " + jobId + ". scriptType: " + scriptType + ", script: " + script); + logger.debug("Starting Job " + id + ". scriptType: " + scriptType + ", script: " + script); } else if (scheduledJob.isLoggingEnabled() && logger.isInfoEnabled()) { - logger.info("Starting Job " + jobId + "."); + logger.info("Starting Job " + id + "."); } final Object ret = jobExecutor.execute(script); if (ret == null) { if (scheduledJob.isLoggingEnabled() && logger.isInfoEnabled()) { - logger.info("Finished Job " + jobId + "."); + logger.info("Finished Job " + id + "."); } } else { if (scheduledJob.isLoggingEnabled() && logger.isInfoEnabled()) { - logger.info("Finished Job " + jobId + ". The return value is:\n" + ret); + logger.info("Finished Job " + id + ". The return value is:\n" + ret); } jobLog.setScriptResult(ret.toString()); } jobLog.setJobStatus(Constants.OK); - } catch (final Throwable t) { // NOPMD - logger.error("Failed to execute " + jobId + ": " + script, t); + } catch (final Throwable t) { + logger.error("Failed to execute " + id + ": " + script, t); jobLog.setJobStatus(Constants.FAIL); jobLog.setScriptResult(systemHelper.abbreviateLongText(t.getLocalizedMessage())); } finally { - jobHelper.finishJobExecutoer(id); jobLog.setEndTime(ComponentUtil.getSystemHelper().getCurrentTimeAsLong()); if (logger.isDebugEnabled()) { logger.debug("jobLog: " + jobLog); diff --git a/src/main/java/org/codelibs/fess/app/logic/AccessContextLogic.java b/src/main/java/org/codelibs/fess/app/logic/AccessContextLogic.java new file mode 100644 index 000000000..b09b0b1cc --- /dev/null +++ b/src/main/java/org/codelibs/fess/app/logic/AccessContextLogic.java @@ -0,0 +1,72 @@ +/* + * Copyright 2012-2016 CodeLibs Project and the Others. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific language + * governing permissions and limitations under the License. + */ +package org.codelibs.fess.app.logic; + +import javax.annotation.Resource; + +import org.codelibs.fess.mylasta.action.FessUserBean; +import org.dbflute.hook.AccessContext; +import org.dbflute.optional.OptionalThing; +import org.lastaflute.core.time.TimeManager; +import org.lastaflute.db.dbflute.accesscontext.AccessContextResource; + +public class AccessContextLogic { + + // =================================================================================== + // Attribute + // ========= + @Resource + private TimeManager timeManager; + + // =================================================================================== + // Resource Interface + // ================== + @FunctionalInterface + public static interface UserTypeSupplier { + OptionalThing supply(); + } + + @FunctionalInterface + public static interface UserBeanSupplier { + OptionalThing supply(); + } + + @FunctionalInterface + public static interface AppTypeSupplier { + String supply(); + } + + // =================================================================================== + // Create Context + // ============== + public AccessContext create(AccessContextResource resource, UserTypeSupplier userTypeSupplier, UserBeanSupplier userBeanSupplier, + AppTypeSupplier appTypeSupplier) { + final AccessContext context = new AccessContext(); + context.setAccessLocalDateTimeProvider(() -> timeManager.currentDateTime()); + context.setAccessUserProvider(() -> buildAccessUserTrace(resource, userTypeSupplier, userBeanSupplier, appTypeSupplier)); + return context; + } + + private String buildAccessUserTrace(AccessContextResource resource, UserTypeSupplier userTypeSupplier, + UserBeanSupplier userBeanSupplier, AppTypeSupplier appTypeSupplier) { + final StringBuilder sb = new StringBuilder(); + sb.append(userTypeSupplier.supply().orElse("_")); + sb.append(",").append(appTypeSupplier.supply()).append(",").append(resource.getModuleName()); + final String trace = sb.toString(); + final int columnSize = 200; + return trace.length() > columnSize ? trace.substring(0, columnSize) : trace; + } +} diff --git a/src/main/java/org/codelibs/fess/app/service/ScheduledJobService.java b/src/main/java/org/codelibs/fess/app/service/ScheduledJobService.java index 6ee8ce7cf..5073c6249 100644 --- a/src/main/java/org/codelibs/fess/app/service/ScheduledJobService.java +++ b/src/main/java/org/codelibs/fess/app/service/ScheduledJobService.java @@ -16,27 +16,44 @@ package org.codelibs.fess.app.service; import java.io.Serializable; +import java.util.HashMap; import java.util.List; +import java.util.Map; import javax.annotation.Resource; import org.codelibs.core.beans.util.BeanUtil; +import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; import org.codelibs.fess.app.pager.SchedulerPager; import org.codelibs.fess.es.config.cbean.ScheduledJobCB; import org.codelibs.fess.es.config.exbhv.ScheduledJobBhv; import org.codelibs.fess.es.config.exentity.ScheduledJob; -import org.codelibs.fess.job.JobScheduler; +import org.codelibs.fess.job.ScheduledJobException; +import org.codelibs.fess.mylasta.direction.FessConfig; +import org.codelibs.fess.util.ComponentUtil; import org.dbflute.cbean.result.PagingResultBean; import org.dbflute.optional.OptionalEntity; +import org.dbflute.optional.OptionalThing; +import org.lastaflute.job.JobManager; +import org.lastaflute.job.LaCron; +import org.lastaflute.job.LaScheduledJob; +import org.lastaflute.job.key.LaJobUnique; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ScheduledJobService implements Serializable { private static final long serialVersionUID = 1L; + private static final Logger logger = LoggerFactory.getLogger(ScheduledJobService.class); + @Resource protected ScheduledJobBhv scheduledJobBhv; + @Resource + protected FessConfig fessConfig; + public List getScheduledJobList(final SchedulerPager scheduledJobPager) { final PagingResultBean scheduledJobList = scheduledJobBhv.selectPage(cb -> { @@ -65,9 +82,6 @@ public class ScheduledJobService implements Serializable { } - @Resource - protected JobScheduler jobScheduler; - protected void setupListCondition(final ScheduledJobCB cb, final SchedulerPager scheduledJobPager) { if (scheduledJobPager.id != null) { cb.query().docMeta().setId_Equal(scheduledJobPager.id); @@ -90,15 +104,12 @@ public class ScheduledJobService implements Serializable { } public void store(final ScheduledJob scheduledJob) { - final boolean isNew = scheduledJob.getId() == null; scheduledJobBhv.insertOrUpdate(scheduledJob, op -> { op.setRefresh(true); }); - if (!isNew) { - jobScheduler.unregister(scheduledJob); - } - jobScheduler.register(scheduledJob); + JobManager jobManager = ComponentUtil.getJobManager(); + jobManager.schedule(cron -> register(cron, scheduledJob)); } public List getCrawlerJobList() { @@ -109,4 +120,99 @@ public class ScheduledJobService implements Serializable { }); } + protected void register(LaCron cron, final ScheduledJob scheduledJob) { + if (scheduledJob == null) { + throw new ScheduledJobException("No job."); + } + + final String id = scheduledJob.getId(); + if (!Constants.T.equals(scheduledJob.getAvailable())) { + logger.info("Inactive Job " + id + ":" + scheduledJob.getName()); + try { + unregister(scheduledJob); + } catch (final Exception e) { + // ignore + } + return; + } + + final String target = scheduledJob.getTarget(); + if (!isTarget(target)) { + logger.info("Ignore Job " + id + ":" + scheduledJob.getName() + " because of not target: " + scheduledJob.getTarget()); + return; + } + + if (StringUtil.isNotBlank(scheduledJob.getCronExpression())) { + logger.info("Starting Job " + id + ":" + scheduledJob.getName()); + findJobByUniqueOf(LaJobUnique.of(id)).ifPresent(job -> { + job.reschedule(scheduledJob.getCronExpression(), option -> option.uniqueBy(id).changeNoticeLogToDebug().params(() -> { + Map params = new HashMap<>(); + params.put(Constants.SCHEDULED_JOB, scheduledJob); + return params; + })); + }).orElse( + () -> { + cron.register(scheduledJob.getCronExpression(), fessConfig.getSchedulerJobClassAsClass(), + fessConfig.getSchedulerConcurrentExecModeAsEnum(), option -> option.uniqueBy(id).changeNoticeLogToDebug() + .params(() -> { + Map params = new HashMap<>(); + params.put(Constants.SCHEDULED_JOB, scheduledJob); + return params; + })); + }); + } else { + logger.info("Inactive Job " + id + ":" + scheduledJob.getName()); + unregister(scheduledJob); + } + } + + private OptionalThing findJobByUniqueOf(LaJobUnique jobUnique) { + final JobManager jobManager = ComponentUtil.getJobManager(); + try { + return jobManager.findJobByUniqueOf(jobUnique); + } catch (Exception e) { + return OptionalThing.empty(); + } + } + + public void unregister(final ScheduledJob scheduledJob) { + try { + JobManager jobManager = ComponentUtil.getJobManager(); + jobManager.findJobByUniqueOf(LaJobUnique.of(scheduledJob.getId())).ifPresent(job -> { + job.unschedule(); + }).orElse(() -> logger.debug("Job {} is not scheduled.", scheduledJob.getId())); + } catch (final Exception e) { + throw new ScheduledJobException("Failed to delete Job: " + scheduledJob, e); + } + } + + protected boolean isTarget(final String target) { + if (StringUtil.isBlank(target)) + + { + return true; + } + + final FessConfig fessConfig = ComponentUtil.getFessConfig(); + final String myName = fessConfig.getSchedulerTargetName(); + + final String[] targets = target.split(","); + for (String name : targets) { + name = name.trim(); + if (Constants.DEFAULT_JOB_TARGET.equalsIgnoreCase(name)) { + return true; + } else if (StringUtil.isNotBlank(myName) && myName.equalsIgnoreCase(name)) { + return true; + } + } + return false; + } + + public void start(LaCron cron) { + scheduledJobBhv.selectCursor(cb -> { + cb.query().setAvailable_Equal(Constants.T); + cb.query().addOrderBy_SortOrder_Asc(); + cb.query().addOrderBy_Name_Asc(); + }, scheduledJob -> register(cron, scheduledJob)); + } } diff --git a/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java b/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java index 9247e543c..7d9e1f1da 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/crawlinginfo/AdminCrawlinginfoAction.java @@ -22,7 +22,7 @@ import org.codelibs.fess.app.pager.CrawlingInfoPager; import org.codelibs.fess.app.service.CrawlingInfoService; import org.codelibs.fess.app.web.CrudMode; import org.codelibs.fess.app.web.base.FessAdminAction; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.SystemHelper; import org.codelibs.fess.util.RenderDataUtil; import org.lastaflute.web.Execute; @@ -46,7 +46,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction { @Resource private SystemHelper systemHelper; @Resource - protected JobHelper jobHelper; + protected ProcessHelper processHelper; // =================================================================================== // Hook @@ -154,7 +154,7 @@ public class AdminCrawlinginfoAction extends FessAdminAction { @Execute public HtmlResponse deleteall() { verifyToken(() -> asListHtml()); - crawlingInfoService.deleteOldSessions(jobHelper.getRunningSessionIdSet()); + crawlingInfoService.deleteOldSessions(processHelper.getRunningSessionIdSet()); crawlingInfoPager.clear(); saveInfo(messages -> messages.addSuccessCrawlingInfoDeleteAll(GLOBAL)); return redirect(getClass()); diff --git a/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java b/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java index 23e57f325..9ba64c6d2 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/scheduler/AdminSchedulerAction.java @@ -25,9 +25,8 @@ import org.codelibs.fess.app.service.ScheduledJobService; import org.codelibs.fess.app.web.CrudMode; import org.codelibs.fess.app.web.base.FessAdminAction; import org.codelibs.fess.es.config.exentity.ScheduledJob; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.SystemHelper; -import org.codelibs.fess.job.JobExecutor; import org.codelibs.fess.util.RenderDataUtil; import org.dbflute.optional.OptionalEntity; import org.dbflute.optional.OptionalThing; @@ -53,7 +52,7 @@ public class AdminSchedulerAction extends FessAdminAction { @Resource private SystemHelper systemHelper; @Resource - protected JobHelper jobHelper; + protected ProcessHelper processHelper; // =================================================================================== // Hook @@ -271,8 +270,7 @@ public class AdminSchedulerAction extends FessAdminAction { verifyToken(() -> asDetailsHtml(id)); scheduledJobService.getScheduledJob(id).ifPresent(entity -> { try { - final JobExecutor jobExecutoer = jobHelper.getJobExecutoer(entity.getId()); - jobExecutoer.shutdown(); + entity.stop(); saveInfo(messages -> messages.addSuccessJobStopped(GLOBAL, entity.getName())); } catch (final Exception e) { throwValidationError(messages -> { diff --git a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java index 3578e5df2..1f49d7c55 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/searchlist/AdminSearchlistAction.java @@ -29,7 +29,7 @@ import org.codelibs.fess.entity.SearchRenderData; import org.codelibs.fess.es.client.FessEsClient; import org.codelibs.fess.exception.InvalidQueryException; import org.codelibs.fess.exception.ResultOffsetExceededException; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.QueryHelper; import org.codelibs.fess.helper.SystemHelper; import org.codelibs.fess.util.RenderDataUtil; @@ -66,7 +66,7 @@ public class AdminSearchlistAction extends FessAdminAction { protected QueryHelper queryHelper; @Resource - protected JobHelper jobHelper; + protected ProcessHelper processHelper; @Resource protected SearchService searchService; @@ -194,7 +194,7 @@ public class AdminSearchlistAction extends FessAdminAction { verifyToken(() -> asListHtml()); validate(form, messages -> {}, () -> asListHtml()); final String docId = form.docId; - if (jobHelper.isProcessRunning()) { + if (processHelper.isProcessRunning()) { throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml()); } try { @@ -211,7 +211,7 @@ public class AdminSearchlistAction extends FessAdminAction { public HtmlResponse deleteall(final ListForm form) { verifyToken(() -> asListHtml()); validate(form, messages -> {}, () -> asListHtml()); - if (jobHelper.isProcessRunning()) { + if (processHelper.isProcessRunning()) { throwValidationError(messages -> messages.addErrorsCannotDeleteDocBecauseOfRunning(GLOBAL), () -> asListHtml()); } try { @@ -227,7 +227,7 @@ public class AdminSearchlistAction extends FessAdminAction { } public boolean isSolrProcessRunning() { - return jobHelper.isProcessRunning(); + return processHelper.isProcessRunning(); } // =================================================================================== diff --git a/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java b/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java index 78e91631d..d7f71e99f 100644 --- a/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java +++ b/src/main/java/org/codelibs/fess/app/web/admin/wizard/AdminWizardAction.java @@ -33,11 +33,12 @@ import org.codelibs.fess.crawler.util.CharUtil; import org.codelibs.fess.es.config.exentity.FileConfig; import org.codelibs.fess.es.config.exentity.ScheduledJob; import org.codelibs.fess.es.config.exentity.WebConfig; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.SystemHelper; -import org.codelibs.fess.job.TriggeredJob; import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.StreamUtil; +import org.lastaflute.job.JobManager; +import org.lastaflute.job.key.LaJobUnique; import org.lastaflute.web.Execute; import org.lastaflute.web.response.HtmlResponse; import org.lastaflute.web.ruts.process.ActionRuntime; @@ -67,7 +68,7 @@ public class AdminWizardAction extends FessAdminAction { protected SystemHelper systemHelper; @Resource - protected JobHelper jobHelper; + protected ProcessHelper processHelper; @Resource protected ScheduledJobService scheduledJobService; @@ -289,10 +290,13 @@ public class AdminWizardAction extends FessAdminAction { @Execute public HtmlResponse startCrawling(final StartCrawlingForm form) { verifyToken(() -> asIndexHtml()); - if (!jobHelper.isProcessRunning()) { + if (!processHelper.isProcessRunning()) { final List scheduledJobList = scheduledJobService.getCrawlerJobList(); + JobManager jobManager = ComponentUtil.getJobManager(); for (final ScheduledJob scheduledJob : scheduledJobList) { - new Thread(() -> new TriggeredJob().execute(scheduledJob)).start(); + jobManager.findJobByUniqueOf(LaJobUnique.of(scheduledJob.getId())).ifPresent(job -> { + job.launchNow(); + }); } saveInfo(messages -> messages.addSuccessStartCrawlProcess(GLOBAL)); } else { diff --git a/src/main/java/org/codelibs/fess/es/config/exentity/ScheduledJob.java b/src/main/java/org/codelibs/fess/es/config/exentity/ScheduledJob.java index de78a066f..53ac1e427 100644 --- a/src/main/java/org/codelibs/fess/es/config/exentity/ScheduledJob.java +++ b/src/main/java/org/codelibs/fess/es/config/exentity/ScheduledJob.java @@ -15,10 +15,11 @@ */ package org.codelibs.fess.es.config.exentity; +import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; import org.codelibs.fess.es.config.bsentity.BsScheduledJob; -import org.codelibs.fess.job.TriggeredJob; import org.codelibs.fess.util.ComponentUtil; +import org.lastaflute.job.key.LaJobUnique; /** * @author FreeGen @@ -27,6 +28,14 @@ public class ScheduledJob extends BsScheduledJob { private static final long serialVersionUID = 1L; + public String getScriptType() { + String st = super.getScriptType(); + if (StringUtil.isBlank(st)) { + return "groovy"; + } + return st; + } + public boolean isLoggingEnabled() { return Constants.T.equals(getJobLogging()); } @@ -40,12 +49,19 @@ public class ScheduledJob extends BsScheduledJob { } public boolean isRunning() { - return ComponentUtil.getJobHelper().getJobExecutoer(getId()) != null; + return ComponentUtil.getJobManager().findJobByUniqueOf(LaJobUnique.of(getId())).map(job -> job.isExecutingNow()).orElse(false); } public void start() { - final ScheduledJob scheduledJob = this; - new Thread(() -> new TriggeredJob().execute(scheduledJob)).start(); + ComponentUtil.getJobManager().findJobByUniqueOf(LaJobUnique.of(getId())).ifPresent(job -> { + job.launchNow(); + }); + } + + public void stop() { + ComponentUtil.getJobManager().findJobByUniqueOf(LaJobUnique.of(getId())).ifPresent(job -> { + job.stopNow(); + }); } public String getId() { diff --git a/src/main/java/org/codelibs/fess/helper/JobHelper.java b/src/main/java/org/codelibs/fess/helper/ProcessHelper.java similarity index 87% rename from src/main/java/org/codelibs/fess/helper/JobHelper.java rename to src/main/java/org/codelibs/fess/helper/ProcessHelper.java index e983bc262..619554a76 100644 --- a/src/main/java/org/codelibs/fess/helper/JobHelper.java +++ b/src/main/java/org/codelibs/fess/helper/ProcessHelper.java @@ -27,19 +27,16 @@ import javax.annotation.PreDestroy; import org.apache.commons.io.IOUtils; import org.codelibs.fess.exception.FessSystemException; -import org.codelibs.fess.job.JobExecutor; import org.codelibs.fess.util.InputStreamThread; import org.codelibs.fess.util.JobProcess; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class JobHelper { - private static final Logger logger = LoggerFactory.getLogger(JobHelper.class); +public class ProcessHelper { + private static final Logger logger = LoggerFactory.getLogger(ProcessHelper.class); private final ConcurrentHashMap runningProcessMap = new ConcurrentHashMap<>(); - private final ConcurrentHashMap runningJobExecutorMap = new ConcurrentHashMap<>(); - @PreDestroy public void destroy() { for (final String sessionId : runningProcessMap.keySet()) { @@ -117,16 +114,4 @@ public class JobHelper { return runningProcessMap.keySet(); } - public JobExecutor startJobExecutoer(final String id, final JobExecutor jobExecutor) { - return runningJobExecutorMap.putIfAbsent(id, jobExecutor); - } - - public void finishJobExecutoer(final String id) { - runningJobExecutorMap.remove(id); - } - - public JobExecutor getJobExecutoer(final String id) { - return runningJobExecutorMap.get(id); - } - } diff --git a/src/main/java/org/codelibs/fess/helper/SystemHelper.java b/src/main/java/org/codelibs/fess/helper/SystemHelper.java index 208969c27..a7757d935 100644 --- a/src/main/java/org/codelibs/fess/helper/SystemHelper.java +++ b/src/main/java/org/codelibs/fess/helper/SystemHelper.java @@ -35,6 +35,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; import org.apache.commons.lang3.LocaleUtils; import org.apache.commons.lang3.StringUtils; @@ -49,6 +50,8 @@ import org.codelibs.fess.util.ComponentUtil; import org.lastaflute.di.core.SingletonLaContainer; import org.lastaflute.web.servlet.request.RequestManager; import org.lastaflute.web.util.LaRequestUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; @@ -56,6 +59,7 @@ import com.google.common.cache.LoadingCache; import com.ibm.icu.util.ULocale; public class SystemHelper implements Serializable { + private static final Logger logger = LoggerFactory.getLogger(SystemHelper.class); private static final long serialVersionUID = 1L; @@ -71,6 +75,8 @@ public class SystemHelper implements Serializable { private String[] supportedLanguages; + private List shutdownHookList = new ArrayList<>(); + @PostConstruct public void init() { final FessConfig fessConfig = ComponentUtil.getFessConfig(); @@ -103,6 +109,17 @@ public class SystemHelper implements Serializable { }); } + @PreDestroy + public void destroy() { + shutdownHookList.forEach(action -> { + try { + action.run(); + } catch (Exception e) { + logger.warn("Failed to process shutdown task.", e); + } + }); + } + public String getUsername() { final RequestManager requestManager = ComponentUtil.getRequestManager(); return requestManager.findUserBean(FessUserBean.class).map(user -> { @@ -252,4 +269,16 @@ public class SystemHelper implements Serializable { } } + public void sleep(int sec) { + try { + Thread.sleep(sec * 1000L); + } catch (InterruptedException e) { + // ignore + } + } + + public void addShutdownHook(Runnable hook) { + shutdownHookList.add(hook); + } + } diff --git a/src/main/java/org/codelibs/fess/job/CrawlJob.java b/src/main/java/org/codelibs/fess/job/CrawlJob.java index c88c58a15..bfc195ec7 100644 --- a/src/main/java/org/codelibs/fess/job/CrawlJob.java +++ b/src/main/java/org/codelibs/fess/job/CrawlJob.java @@ -32,7 +32,7 @@ import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; import org.codelibs.fess.exception.FessSystemException; import org.codelibs.fess.exec.Crawler; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.SystemHelper; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.util.ComponentUtil; @@ -231,7 +231,7 @@ public class CrawlJob { final String cpSeparator = SystemUtils.IS_OS_WINDOWS ? ";" : ":"; final ServletContext servletContext = SingletonLaContainer.getComponent(ServletContext.class); final SystemHelper systemHelper = ComponentUtil.getSystemHelper(); - final JobHelper jobHelper = ComponentUtil.getJobHelper(); + final ProcessHelper processHelper = ComponentUtil.getJobHelper(); final FessConfig fessConfig = ComponentUtil.getFessConfig(); cmdList.add(fessConfig.getJavaCommandPath()); @@ -361,7 +361,7 @@ public class CrawlJob { logger.info("Crawler: \nDirectory=" + baseDir + "\nOptions=" + cmdList); } - final JobProcess jobProcess = jobHelper.startProcess(sessionId, cmdList, pb -> { + final JobProcess jobProcess = processHelper.startProcess(sessionId, cmdList, pb -> { pb.directory(baseDir); pb.redirectErrorStream(true); }); @@ -389,7 +389,7 @@ public class CrawlJob { throw new FessSystemException("Crawler Process terminated.", e); } finally { try { - jobHelper.destroyProcess(sessionId); + processHelper.destroyProcess(sessionId); } finally { if (propFile != null && !propFile.delete()) { logger.warn("Failed to delete {}.", propFile.getAbsolutePath()); diff --git a/src/main/java/org/codelibs/fess/job/JobScheduler.java b/src/main/java/org/codelibs/fess/job/JobScheduler.java deleted file mode 100644 index cf4f683fa..000000000 --- a/src/main/java/org/codelibs/fess/job/JobScheduler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2012-2016 CodeLibs Project and the Others. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific language - * governing permissions and limitations under the License. - */ -package org.codelibs.fess.job; - -import static org.quartz.CronScheduleBuilder.cronSchedule; -import static org.quartz.JobBuilder.newJob; -import static org.quartz.JobKey.jobKey; -import static org.quartz.TriggerBuilder.newTrigger; - -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - -import org.codelibs.core.lang.StringUtil; -import org.codelibs.fess.Constants; -import org.codelibs.fess.es.config.exbhv.JobLogBhv; -import org.codelibs.fess.es.config.exbhv.ScheduledJobBhv; -import org.codelibs.fess.es.config.exentity.ScheduledJob; -import org.codelibs.fess.helper.JobHelper; -import org.codelibs.fess.mylasta.direction.FessConfig; -import org.codelibs.fess.util.ComponentUtil; -import org.quartz.Job; -import org.quartz.JobDataMap; -import org.quartz.JobDetail; -import org.quartz.Scheduler; -import org.quartz.SchedulerException; -import org.quartz.SchedulerFactory; -import org.quartz.Trigger; -import org.quartz.impl.StdSchedulerFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class JobScheduler { - private static final Logger logger = LoggerFactory.getLogger(JobScheduler.class); - - private static final String TRIGGER_ID_PREFIX = "trigger"; - - private Scheduler scheduler; - - public Class jobClass = TriggeredJob.class; - - @PostConstruct - public void init() { - final SchedulerFactory sf = new StdSchedulerFactory(); - try { - scheduler = sf.getScheduler(); - scheduler.start(); - } catch (final SchedulerException e) { - throw new ScheduledJobException("Failed to start a scheduler.", e); - } - - ComponentUtil.getComponent(ScheduledJobBhv.class).selectCursor(cb -> { - cb.query().setAvailable_Equal(Constants.T); - cb.query().addOrderBy_SortOrder_Asc(); - cb.query().addOrderBy_Name_Asc(); - }, scheduledJob -> register(scheduledJob)); - - final FessConfig fessConfig = ComponentUtil.getFessConfig(); - final String myName = fessConfig.getSchedulerTargetName(); - if (StringUtil.isNotBlank(myName)) { - ComponentUtil.getComponent(JobLogBhv.class).queryDelete(cb -> { - cb.query().setJobStatus_Equal(Constants.RUNNING); - cb.query().setTarget_Equal(myName); - }); - } - } - - @PreDestroy - public void destroy() { - final JobHelper jobHelper = ComponentUtil.getJobHelper(); - for (final String sessionId : jobHelper.getRunningSessionIdSet()) { - jobHelper.destroyProcess(sessionId); - } - try { - scheduler.shutdown(true); - } catch (final SchedulerException e) { - logger.error("Failed to shutdown the scheduler.", e); - } - } - - public void register(final ScheduledJob scheduledJob) { - if (scheduledJob == null) { - throw new ScheduledJobException("No job."); - } - - if (!Constants.T.equals(scheduledJob.getAvailable())) { - logger.info("Inactive Job " + scheduledJob.getId() + ":" + scheduledJob.getName()); - try { - unregister(scheduledJob); - } catch (final Exception e) { - // ignore - } - return; - } - - final String target = scheduledJob.getTarget(); - if (!isTarget(target)) { - logger.info("Ignore Job " + scheduledJob.getId() + ":" + scheduledJob.getName() + " because of not target: " - + scheduledJob.getTarget()); - return; - } - - String scriptType = scheduledJob.getScriptType(); - if (scriptType == null) { - scriptType = "groovy"; - } - - final String id = scheduledJob.getId(); - final String jobId = Constants.JOB_ID_PREFIX + id; - final String triggerId = TRIGGER_ID_PREFIX + id; - - final JobDataMap jobDataMap = new JobDataMap(); - jobDataMap.put(Constants.SCHEDULED_JOB, scheduledJob); - jobDataMap.put(Constants.JOB_EXECUTOR_TYPE, scriptType); - final JobDetail jobDetail = newJob(jobClass).withIdentity(jobId).usingJobData(jobDataMap).build(); - - if (StringUtil.isNotBlank(scheduledJob.getCronExpression())) { - final Trigger trigger = - newTrigger().withIdentity(triggerId).withSchedule(cronSchedule(scheduledJob.getCronExpression())).startNow().build(); - - try { - scheduler.scheduleJob(jobDetail, trigger); - } catch (final SchedulerException e) { - throw new ScheduledJobException("Failed to add Job: " + scheduledJob, e); - } - - logger.info("Starting Job " + scheduledJob.getId() + ":" + scheduledJob.getName()); - } - } - - public void unregister(final ScheduledJob scheduledJob) { - final String jobId = Constants.JOB_ID_PREFIX + scheduledJob.getId(); - try { - scheduler.deleteJob(jobKey(jobId)); - } catch (final SchedulerException e) { - throw new ScheduledJobException("Failed to delete Job: " + scheduledJob, e); - } - } - - protected boolean isTarget(final String target) { - if (StringUtil.isBlank(target)) { - return true; - } - - final FessConfig fessConfig = ComponentUtil.getFessConfig(); - final String myName = fessConfig.getSchedulerTargetName(); - - final String[] targets = target.split(","); - for (String name : targets) { - name = name.trim(); - if (Constants.DEFAULT_JOB_TARGET.equalsIgnoreCase(name)) { - return true; - } else if (StringUtil.isNotBlank(myName) && myName.equalsIgnoreCase(name)) { - return true; - } - } - return false; - } -} diff --git a/src/main/java/org/codelibs/fess/job/SuggestJob.java b/src/main/java/org/codelibs/fess/job/SuggestJob.java index 6585dde50..7b6344102 100644 --- a/src/main/java/org/codelibs/fess/job/SuggestJob.java +++ b/src/main/java/org/codelibs/fess/job/SuggestJob.java @@ -31,7 +31,7 @@ import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; import org.codelibs.fess.exception.FessSystemException; import org.codelibs.fess.exec.SuggestCreator; -import org.codelibs.fess.helper.JobHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.mylasta.direction.FessConfig; import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.InputStreamThread; @@ -122,7 +122,7 @@ public class SuggestJob { final List cmdList = new ArrayList<>(); final String cpSeparator = SystemUtils.IS_OS_WINDOWS ? ";" : ":"; final ServletContext servletContext = SingletonLaContainer.getComponent(ServletContext.class); - final JobHelper jobHelper = ComponentUtil.getJobHelper(); + final ProcessHelper processHelper = ComponentUtil.getJobHelper(); final FessConfig fessConfig = ComponentUtil.getFessConfig(); cmdList.add(fessConfig.getJavaCommandPath()); @@ -233,7 +233,7 @@ public class SuggestJob { logger.info("SuggestCreator: \nDirectory=" + baseDir + "\nOptions=" + cmdList); } - final JobProcess jobProcess = jobHelper.startProcess(sessionId, cmdList, pb -> { + final JobProcess jobProcess = processHelper.startProcess(sessionId, cmdList, pb -> { pb.directory(baseDir); pb.redirectErrorStream(true); }); @@ -261,7 +261,7 @@ public class SuggestJob { throw new FessSystemException("SuggestCreator Process terminated.", e); } finally { try { - jobHelper.destroyProcess(sessionId); + processHelper.destroyProcess(sessionId); } finally { if (propFile != null && !propFile.delete()) { logger.warn("Failed to delete {}.", propFile.getAbsolutePath()); diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java index 4f0262a99..466dff5bd 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessConfig.java @@ -384,6 +384,12 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction /** The key of the configuration. e.g. */ String SCHEDULER_TARGET_NAME = "scheduler.target.name"; + /** The key of the configuration. e.g. org.codelibs.fess.app.job.ScriptExecutorJob */ + String SCHEDULER_JOB_CLASS = "scheduler.job.class"; + + /** The key of the configuration. e.g. QUIT */ + String SCHEDULER_CONCURRENT_EXEC_MODE = "scheduler.concurrent.exec.mode"; + /** The key of the configuration. e.g. http://fess.codelibs.org/{lang}/{version}/admin/ */ String ONLINE_HELP_BASE_LINK = "online.help.base.link"; @@ -1773,6 +1779,20 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction */ Integer getSchedulerTargetNameAsInteger(); + /** + * Get the value for the key 'scheduler.job.class'.
+ * The value is, e.g. org.codelibs.fess.app.job.ScriptExecutorJob
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + */ + String getSchedulerJobClass(); + + /** + * Get the value for the key 'scheduler.concurrent.exec.mode'.
+ * The value is, e.g. QUIT
+ * @return The value of found property. (NotNull: if not found, exception but basically no way) + */ + String getSchedulerConcurrentExecMode(); + /** * Get the value for the key 'online.help.base.link'.
* The value is, e.g. http://fess.codelibs.org/{lang}/{version}/admin/
@@ -2834,6 +2854,14 @@ public interface FessConfig extends FessEnv, org.codelibs.fess.mylasta.direction return getAsInteger(FessConfig.SCHEDULER_TARGET_NAME); } + public String getSchedulerJobClass() { + return get(FessConfig.SCHEDULER_JOB_CLASS); + } + + public String getSchedulerConcurrentExecMode() { + return get(FessConfig.SCHEDULER_CONCURRENT_EXEC_MODE); + } + public String getOnlineHelpBaseLink() { return get(FessConfig.ONLINE_HELP_BASE_LINK); } diff --git a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java index a4b9ecd2f..1f261de07 100644 --- a/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java +++ b/src/main/java/org/codelibs/fess/mylasta/direction/FessProp.java @@ -15,10 +15,13 @@ */ package org.codelibs.fess.mylasta.direction; +import org.codelibs.core.exception.ClassNotFoundRuntimeException; import org.codelibs.core.lang.StringUtil; import org.codelibs.fess.Constants; import org.codelibs.fess.util.ComponentUtil; import org.codelibs.fess.util.StreamUtil; +import org.lastaflute.job.LaJob; +import org.lastaflute.job.subsidiary.ConcurrentExec; public interface FessProp { @@ -280,4 +283,22 @@ public interface FessProp { return "None"; } + String getSchedulerJobClass(); + + public default Class getSchedulerJobClassAsClass() { + try { + @SuppressWarnings("unchecked") + Class clazz = (Class) Class.forName(getSchedulerJobClass()); + return clazz; + } catch (ClassNotFoundException e) { + throw new ClassNotFoundRuntimeException(e); + } + } + + String getSchedulerConcurrentExecMode(); + + public default ConcurrentExec getSchedulerConcurrentExecModeAsEnum() { + return ConcurrentExec.valueOf(getSchedulerConcurrentExecMode()); + } + } diff --git a/src/main/java/org/codelibs/fess/util/ComponentUtil.java b/src/main/java/org/codelibs/fess/util/ComponentUtil.java index 603fc6e8e..fc09d75bc 100644 --- a/src/main/java/org/codelibs/fess/util/ComponentUtil.java +++ b/src/main/java/org/codelibs/fess/util/ComponentUtil.java @@ -30,11 +30,11 @@ import org.codelibs.fess.helper.DuplicateHostHelper; import org.codelibs.fess.helper.FileTypeHelper; import org.codelibs.fess.helper.IndexingHelper; import org.codelibs.fess.helper.IntervalControlHelper; -import org.codelibs.fess.helper.JobHelper; import org.codelibs.fess.helper.KeyMatchHelper; import org.codelibs.fess.helper.LabelTypeHelper; import org.codelibs.fess.helper.PathMappingHelper; import org.codelibs.fess.helper.PopularWordHelper; +import org.codelibs.fess.helper.ProcessHelper; import org.codelibs.fess.helper.QueryHelper; import org.codelibs.fess.helper.RoleQueryHelper; import org.codelibs.fess.helper.SambaHelper; @@ -51,6 +51,7 @@ import org.codelibs.fess.mylasta.direction.FessConfig; import org.lastaflute.core.message.MessageManager; import org.lastaflute.di.core.SingletonLaContainer; import org.lastaflute.di.core.factory.SingletonLaContainerFactory; +import org.lastaflute.job.JobManager; import org.lastaflute.web.servlet.request.RequestManager; public final class ComponentUtil { @@ -86,7 +87,7 @@ public final class ComponentUtil { private static final String WEB_API_MANAGER_FACTORY = "webApiManagerFactory"; - private static final String JOB_HELPER = "jobHelper"; + private static final String JOB_HELPER = "processHelper"; private static final String DUPLICATE_HOST_HELPER = "duplicateHostHelper"; @@ -187,7 +188,7 @@ public final class ComponentUtil { return SingletonLaContainer.getComponent(DUPLICATE_HOST_HELPER); } - public static JobHelper getJobHelper() { + public static ProcessHelper getJobHelper() { return SingletonLaContainer.getComponent(JOB_HELPER); } @@ -279,6 +280,10 @@ public final class ComponentUtil { return SingletonLaContainer.getComponent(RequestManager.class); } + public static JobManager getJobManager() { + return SingletonLaContainer.getComponent(JobManager.class); + } + public static T getComponent(final Class clazz) { return SingletonLaContainer.getComponent(clazz); } diff --git a/src/main/java/org/codelibs/fess/validation/CronExpressionValidator.java b/src/main/java/org/codelibs/fess/validation/CronExpressionValidator.java index f63cc3002..4598bca8e 100644 --- a/src/main/java/org/codelibs/fess/validation/CronExpressionValidator.java +++ b/src/main/java/org/codelibs/fess/validation/CronExpressionValidator.java @@ -19,6 +19,7 @@ import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.codelibs.core.lang.StringUtil; +import org.lastaflute.job.util.LaCronUtil; public class CronExpressionValidator implements ConstraintValidator { @@ -32,7 +33,7 @@ public class CronExpressionValidator implements ConstraintValidator + diff --git a/src/main/resources/fess.xml b/src/main/resources/fess.xml index 84a5d7f09..f9824fb86 100644 --- a/src/main/resources/fess.xml +++ b/src/main/resources/fess.xml @@ -18,7 +18,7 @@ - + diff --git a/src/main/resources/fess_config.properties b/src/main/resources/fess_config.properties index 70670f26e..3c804149c 100644 --- a/src/main/resources/fess_config.properties +++ b/src/main/resources/fess_config.properties @@ -222,6 +222,8 @@ mail.from.address = root@localhost # Scheduler # ------ scheduler.target.name= +scheduler.job.class=org.codelibs.fess.app.job.ScriptExecutorJob +scheduler.concurrent.exec.mode=QUIT # ---------------------------------------------------------- # OnlineHelp diff --git a/src/main/resources/fess_indices/.fess_config/scheduled_job.bulk b/src/main/resources/fess_indices/.fess_config/scheduled_job.bulk index 877516b81..fd8ee9555 100644 --- a/src/main/resources/fess_indices/.fess_config/scheduled_job.bulk +++ b/src/main/resources/fess_indices/.fess_config/scheduled_job.bulk @@ -1,10 +1,10 @@ {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"default_crawler"}} -{"name":"Default Crawler","target":"all","cronExpression":"0 0 0 * * ?","scriptType":"groovy","scriptData":"return container.getComponent(\"crawlJob\").logLevel(\"info\").execute(executor);","jobLogging":true,"crawler":true,"available":true,"sortOrder":1,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} +{"name":"Default Crawler","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"crawlJob\").logLevel(\"info\").execute(executor);","jobLogging":true,"crawler":true,"available":true,"sortOrder":1,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"suggest_indexer"}} -{"name":"Suggest Indexer","target":"all","cronExpression":"0 0 0 * * ?","scriptType":"groovy","scriptData":"return container.getComponent(\"suggestJob\").logLevel(\"info\").sessionId(\"SUGGEST\").execute(executor);","jobLogging":true,"crawler":false,"available":true,"sortOrder":2,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} +{"name":"Suggest Indexer","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"suggestJob\").logLevel(\"info\").sessionId(\"SUGGEST\").execute(executor);","jobLogging":true,"crawler":false,"available":true,"sortOrder":2,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"log_aggregator"}} -{"name":"Log Aggregator","target":"all","cronExpression":"0 * * * * ?","scriptType":"groovy","scriptData":"return container.getComponent(\"aggregateLogJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":3,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} +{"name":"Log Aggregator","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"aggregateLogJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":3,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"log_purger"}} -{"name":"Log Purger","target":"all","cronExpression":"0 0 0 * * ?","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeLogJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":4,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} +{"name":"Log Purger","target":"all","cronExpression":"0 0 * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeLogJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":4,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} {"index":{"_index":".fess_config","_type":"scheduled_job","_id":"doc_purger"}} -{"name":"Doc Purger","target":"all","cronExpression":"0 * * * * ?","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeDocJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":5,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} +{"name":"Doc Purger","target":"all","cronExpression":"* * * * *","scriptType":"groovy","scriptData":"return container.getComponent(\"purgeDocJob\").execute();","jobLogging":false,"crawler":false,"available":true,"sortOrder":5,"createdBy":"system","createdTime":0,"updatedBy":"system","updatedTime":0} diff --git a/src/main/resources/fess_job.xml b/src/main/resources/fess_job.xml index 0d0040be8..69250538a 100644 --- a/src/main/resources/fess_job.xml +++ b/src/main/resources/fess_job.xml @@ -2,8 +2,6 @@ - - diff --git a/src/main/resources/quartz.properties b/src/main/resources/quartz.properties deleted file mode 100644 index 3180faeaa..000000000 --- a/src/main/resources/quartz.properties +++ /dev/null @@ -1,3 +0,0 @@ -org.quartz.scheduler.instanceName=JobScheduler -org.quartz.threadPool.threadCount=5 -