View Javadoc
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 }