1 /*
2 * Copyright 2012-2025 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.app.service;
17
18 import java.util.List;
19
20 import org.codelibs.core.beans.util.BeanUtil;
21 import org.codelibs.fess.Constants;
22 import org.codelibs.fess.app.pager.JobLogPager;
23 import org.codelibs.fess.mylasta.direction.FessConfig;
24 import org.codelibs.fess.opensearch.config.cbean.JobLogCB;
25 import org.codelibs.fess.opensearch.config.exbhv.JobLogBhv;
26 import org.codelibs.fess.opensearch.config.exentity.JobLog;
27 import org.codelibs.fess.util.ComponentUtil;
28 import org.dbflute.cbean.result.PagingResultBean;
29 import org.dbflute.optional.OptionalEntity;
30
31 import jakarta.annotation.Resource;
32
33 /**
34 * Service class for managing job logs in the Fess application.
35 * Provides functionality to create, read, update, and delete job log entries,
36 * as well as manage job status and perform cleanup operations.
37 */
38 public class JobLogService {
39
40 /**
41 * Behavior class for job log database operations.
42 */
43 @Resource
44 protected JobLogBhv jobLogBhv;
45
46 /**
47 * Default constructor.
48 */
49 public JobLogService() {
50 // Default constructor
51 }
52
53 /**
54 * Configuration settings for the Fess application.
55 */
56 @Resource
57 protected FessConfig fessConfig;
58
59 /**
60 * Time interval in milliseconds after which jobs are considered expired.
61 * Default is 2 hours (2 * 60 * 60 * 1000L).
62 */
63 protected long expiredJobInterval = 2 * 60 * 60 * 1000L; // 2hours
64
65 /**
66 * Retrieves a paginated list of job logs based on the provided pager configuration.
67 *
68 * @param jobLogPager the pager configuration for pagination and filtering
69 * @return a list of job logs matching the criteria
70 */
71 public List<JobLog> getJobLogList(final JobLogPager jobLogPager) {
72
73 final PagingResultBean<JobLog> jobLogList = jobLogBhv.selectPage(cb -> {
74 cb.paging(jobLogPager.getPageSize(), jobLogPager.getCurrentPageNumber());
75 setupListCondition(cb, jobLogPager);
76 });
77
78 // update pager
79 BeanUtil.copyBeanToBean(jobLogList, jobLogPager, option -> option.include(Constants.PAGER_CONVERSION_RULE));
80 jobLogPager.setPageNumberList(jobLogList.pageRange(op -> {
81 op.rangeSize(fessConfig.getPagingPageRangeSizeAsInteger());
82 }).createPageNumberList());
83
84 return jobLogList;
85 }
86
87 /**
88 * Retrieves a specific job log by its ID.
89 *
90 * @param id the unique identifier of the job log
91 * @return an optional entity containing the job log if found
92 */
93 public OptionalEntity<JobLog> getJobLog(final String id) {
94 return jobLogBhv.selectByPK(id);
95 }
96
97 /**
98 * Stores a job log entry in the database.
99 * Performs an insert or update operation based on whether the job log already exists.
100 *
101 * @param jobLog the job log to store
102 */
103 public void store(final JobLog jobLog) {
104
105 jobLogBhv.insertOrUpdate(jobLog, op -> {
106 op.setRefreshPolicy(Constants.TRUE);
107 });
108
109 }
110
111 /**
112 * Deletes a specific job log from the database.
113 *
114 * @param jobLog the job log to delete
115 */
116 public void delete(final JobLog jobLog) {
117
118 jobLogBhv.delete(jobLog, op -> {
119 op.setRefreshPolicy(Constants.TRUE);
120 });
121
122 }
123
124 /**
125 * Sets up the query conditions for retrieving job logs based on the pager configuration.
126 * Configures filtering and ordering for the database query.
127 *
128 * @param cb the condition bean for building the query
129 * @param jobLogPager the pager containing filter and search criteria
130 */
131 protected void setupListCondition(final JobLogCB cb, final JobLogPager jobLogPager) {
132 if (jobLogPager.id != null) {
133 cb.query().docMeta().setId_Equal(jobLogPager.id);
134 }
135 // TODO Long, Integer, String supported only.
136
137 // setup condition
138 cb.query().addOrderBy_StartTime_Desc();
139 cb.query().addOrderBy_EndTime_Desc();
140
141 // search
142
143 }
144
145 /**
146 * Deletes job logs that ended before the specified number of days ago.
147 * Used for cleaning up old log entries.
148 *
149 * @param days the number of days to look back from the current time
150 */
151 public void deleteBefore(final int days) {
152 final long oneday = 24 * 60 * 60 * 1000L;
153 final long targetTime = ComponentUtil.getSystemHelper().getCurrentTimeAsLong() - days * oneday;
154 jobLogBhv.queryDelete(cb -> {
155 cb.query().setEndTime_LessThan(targetTime);
156 });
157 }
158
159 /**
160 * Deletes job logs that have any of the specified job statuses.
161 *
162 * @param jobStatusList the list of job statuses to match for deletion
163 */
164 public void deleteByJobStatus(final List<String> jobStatusList) {
165 jobLogBhv.queryDelete(cb -> {
166 cb.query().setJobStatus_InScope(jobStatusList);
167 });
168 }
169
170 /**
171 * Updates the status of expired jobs that haven't finished.
172 * Jobs that have been running longer than the expired job interval
173 * without an end time are marked as failed.
174 */
175 public void updateStatus() {
176 final long expiry = ComponentUtil.getSystemHelper().getCurrentTimeAsLong() - expiredJobInterval;
177 final List<JobLog> list = jobLogBhv.selectList(cb -> {
178 cb.query().bool((must, should, mustNot, filter) -> {
179 must.setLastUpdated_LessEqual(expiry);
180 mustNot.setEndTime_Exists();
181 });
182 });
183 if (!list.isEmpty()) {
184 list.forEach(jobLog -> {
185 jobLog.setJobStatus(Constants.FAIL);
186 jobLog.setScriptResult("No response from Job.");
187 jobLog.setEndTime(ComponentUtil.getSystemHelper().getCurrentTimeAsLong());
188 });
189 jobLogBhv.batchUpdate(list);
190 }
191 }
192
193 /**
194 * Sets the time interval after which jobs are considered expired.
195 *
196 * @param expiredJobInterval the time interval in milliseconds
197 */
198 public void setExpiredJobInterval(final long expiredJobInterval) {
199 this.expiredJobInterval = expiredJobInterval;
200 }
201
202 }