View Javadoc
1   package ca.uhn.fhir.jpa.util;
2   
3   /*-
4    * #%L
5    * HAPI FHIR JPA Server
6    * %%
7    * Copyright (C) 2014 - 2018 University Health Network
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  import ca.uhn.fhir.jpa.dao.DaoConfig;
24  import ca.uhn.fhir.jpa.dao.IFhirSystemDao;
25  import org.apache.commons.lang3.time.DateUtils;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  import org.springframework.beans.factory.annotation.Autowired;
29  import org.springframework.scheduling.annotation.Scheduled;
30  import org.springframework.transaction.annotation.Propagation;
31  import org.springframework.transaction.annotation.Transactional;
32  
33  import java.util.concurrent.Semaphore;
34  
35  public class ReindexController implements IReindexController {
36  
37  	private static final Logger ourLog = LoggerFactory.getLogger(ReindexController.class);
38  	private final Semaphore myReindexingLock = new Semaphore(1);
39  	@Autowired
40  	private DaoConfig myDaoConfig;
41  	@Autowired
42  	private IFhirSystemDao<?, ?> mySystemDao;
43  	private Long myDontReindexUntil;
44  
45  	/**
46  	 * This method is called once per minute to perform any required re-indexing.
47  	 * <p>
48  	 * If nothing if found that requires reindexing, the query will not fire again for
49  	 * a longer amount of time.
50  	 * <p>
51  	 * During most passes this will just check and find that there are no resources
52  	 * requiring re-indexing. In that case the method just returns immediately.
53  	 * If the search finds that some resources require reindexing, the system will
54  	 * do a bunch of reindexing and then return.
55  	 */
56  	@Scheduled(fixedDelay = DateUtils.MILLIS_PER_MINUTE)
57  	@Transactional(propagation = Propagation.NEVER)
58  	@Override
59  	public void performReindexingPass() {
60  		if (myDaoConfig.isSchedulingDisabled() || myDaoConfig.isStatusBasedReindexingDisabled()) {
61  			return;
62  		}
63  
64  		synchronized (this) {
65  			if (myDontReindexUntil != null && myDontReindexUntil > System.currentTimeMillis()) {
66  				return;
67  			}
68  		}
69  
70  		if (!myReindexingLock.tryAcquire()) {
71  			ourLog.trace("Not going to reindex in parallel threads");
72  			return;
73  		}
74  		Integer count;
75  		try {
76  			count = mySystemDao.performReindexingPass(100);
77  
78  			for (int i = 0; i < 50 && count != null && count != 0; i++) {
79  				count = mySystemDao.performReindexingPass(100);
80  				try {
81  					Thread.sleep(DateUtils.MILLIS_PER_SECOND);
82  				} catch (InterruptedException e) {
83  					break;
84  				}
85  			}
86  		} catch (Exception e) {
87  			ourLog.error("Failure during reindex", e);
88  			count = -1;
89  		} finally {
90  			myReindexingLock.release();
91  		}
92  
93  		synchronized (this) {
94  			if (count == null) {
95  				ourLog.info("Reindex pass complete, no remaining resource to index");
96  				myDontReindexUntil = System.currentTimeMillis() + DateUtils.MILLIS_PER_HOUR;
97  			} else if (count == -1) {
98  				// Reindexing failed
99  				myDontReindexUntil = System.currentTimeMillis() + DateUtils.MILLIS_PER_HOUR;
100 			} else {
101 				ourLog.info("Reindex pass complete, {} remaining resource to index", count);
102 				myDontReindexUntil = null;
103 			}
104 		}
105 
106 	}
107 
108 	/**
109 	 * Calling this will cause a reindex loop to be triggered sooner that it would otherwise
110 	 */
111 	@Override
112 	public void requestReindex() {
113 		synchronized (this) {
114 			myDontReindexUntil = null;
115 		}
116 	}
117 
118 
119 }