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()) {
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  		} finally {
87  			myReindexingLock.release();
88  		}
89  
90  		synchronized (this) {
91  			if (count == null) {
92  				myDontReindexUntil = System.currentTimeMillis() + DateUtils.MILLIS_PER_HOUR;
93  			} else {
94  				myDontReindexUntil = null;
95  			}
96  		}
97  
98  	}
99  
100 	/**
101 	 * Calling this will cause a reindex loop to be triggered sooner that it would otherwise
102 	 */
103 	@Override
104 	public void requestReindex() {
105 		synchronized (this) {
106 			myDontReindexUntil = null;
107 		}
108 	}
109 
110 
111 }