/** * The contents of this file are subject to the OpenMRS Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://license.openmrs.org * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * Copyright (C) OpenMRS, LLC. All Rights Reserved. */ package org.openmrs.module.sync; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openmrs.api.context.Context; import org.openmrs.module.sync.api.SyncService; import org.openmrs.module.sync.ingest.SyncTransmissionResponse; import org.openmrs.module.sync.server.RemoteServer; import org.openmrs.scheduler.TaskDefinition; import org.openmrs.scheduler.tasks.AbstractTask; /** * Represents scheduled task to perform full data synchronization with a remote server as identified * during the task setup. */ public class SyncTask extends AbstractTask { // Logger private static Log log = LogFactory.getLog(SyncTask.class); // Instance of configuration information for task private Integer serverId = 0; private static Boolean isExecuting = false; // allow only one running /** * Default Constructor (Uses SchedulerConstants.username and SchedulerConstants.password */ public SyncTask() { // do nothing for now } /** * Runs 'full' data synchronization (i.e. both send local changes and receive changes from the * remote server as identified in the task setup). * <p> * NOTE: Any exception (outside of session open/close) is caught and reported in the error log * thus creating retry behavior based on the scheduled frequency. */ public void execute() { Context.openSession(); synchronized (isExecuting) { if (isExecuting) { log.warn("SyncTask processor aborting (another SyncTask already running)"); return; } isExecuting = true; } try { log.debug("Synchronizing data to a server."); if (Context.isAuthenticated() == false && serverId > 0) authenticate(); RemoteServer server = Context.getService(SyncService.class).getRemoteServer(serverId); if (server != null) { //auto syncing is only via web, so apply the web limit for sync records to send SyncTransmissionResponse response = SyncUtilTransmission.doFullSynchronize(server, null, SyncUtil.getGlobalPropetyValueAsInteger(SyncConstants.PROPERTY_NAME_MAX_RECORDS_WEB)); try { response.createFile(false, SyncConstants.DIR_JOURNAL); } catch (Exception e) { log.error("Unable to create file to store SyncTransmissionResponse: " + response.getFileName(), e); } } } catch (Exception e) { log.error("Scheduler error while trying to synchronize data. Will retry per schedule.", e); } finally { isExecuting = false; Context.closeSession(); log.debug("Synchronization complete."); } } /** * Initializes task. Note serverId is in most cases an Id (as stored in sync server table) of * parent. As such, parent Id does not need to be stored separately with the task as it can * always be determined from sync server table. serverId is stored here as we envision using * this feature to also 'export' data to another server -- essentially 'shadow' copying data to * a separate server for other uses such as reporting. * * @param config */ @Override public void initialize(final TaskDefinition definition) { super.initialize(definition); try { this.serverId = Integer.valueOf(definition.getProperty(SyncConstants.SCHEDULED_TASK_PROPERTY_SERVER_ID)); } catch (Exception e) { this.serverId = 0; log.error("Could not find serverId for this sync scheduled task.", e); } } /** * Checks if the sync task is running. * * @return true if running, else false. */ public static Boolean getIsExecuting() { synchronized (isExecuting) { return isExecuting; } } }