/* This program is free software: you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
package org.opentripplanner.updater;
import com.fasterxml.jackson.databind.JsonNode;
import org.opentripplanner.routing.graph.Graph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This abstract class implements logic that is shared between all polling updaters.
*
* Usage example ('polling' name is an example and 'polling-updater' should be the type of a
* concrete class derived from this abstract class):
*
* <pre>
* polling.type = polling-updater
* polling.frequencySec = 60
* </pre>
*
* @see GraphUpdater
*/
public abstract class PollingGraphUpdater implements GraphUpdater {
private static Logger LOG = LoggerFactory.getLogger(PollingGraphUpdater.class);
/**
* Mirrors GraphUpdater.run method. Only difference is that runPolling will be run multiple
* times with pauses in between. The length of the pause is defined in the preference
* frequencySec.
*/
abstract protected void runPolling() throws Exception;
/**
* Mirrors GraphUpdater.configure method.
*/
abstract protected void configurePolling(Graph graph, JsonNode config) throws Exception;
/**
* The number of seconds between two polls
*/
protected Integer frequencySec;
/**
* The type name in the preferences
*/
private String type;
@Override
final public void run() {
try {
LOG.info("Polling updater started: {}", this);
// Run "forever"
while (true) {
try {
// Run concrete class' method
runPolling();
if (frequencySec < 0) {
LOG.info("As requested in configuration, updater {} has run only once and will now stop.",
this.getClass().getSimpleName());
break;
}
} catch (InterruptedException e) {
// Throw further up the stack
throw e;
} catch (Exception e) {
LOG.error("Error while running polling updater of type {}", type, e);
// TODO Should we cancel the task? Or after n consecutive failures?
// cancel();
}
// Sleep a given number of seconds
Thread.sleep(frequencySec * 1000);
}
} catch (InterruptedException e) {
// When updater is interrupted
LOG.error("Polling updater {}@{} is interrupted, updater stops.", this.getClass()
.getName(), this.hashCode());
}
}
/** Shared configuration code for all polling graph updaters. */
@Override
final public void configure (Graph graph, JsonNode config) throws Exception {
// Configure polling system
frequencySec = config.path("frequencySec").asInt(60);
type = config.path("type").asText("");
// Additional configuration for the concrete subclass
configurePolling(graph, config);
}
}