This is an automated email from the git hooks/post-receive script. New commit to branch feature/1365_problem_synchro in repository jtimer. See https://gitlab.nuiton.org/chorem/jtimer.git commit 40a925478ec0fc329ea76b67bae52a56c85da7a2 Author: servantie <servantie.c@gmail.com> Date: Tue Jul 26 11:58:47 2016 +0200 reworked sync to make one sync at startup, and then sync the tasks when the time changes --- src/main/java/org/chorem/jtimer/JTimerConfig.java | 9 - src/main/java/org/chorem/jtimer/JTimerFactory.java | 4 - .../java/org/chorem/jtimer/entities/TimerTask.java | 7 +- .../chorem/jtimer/entities/TimerTaskHelper.java | 6 +- .../chorem/jtimer/io/GTimerIncrementalSaver.java | 4 +- .../chorem/jtimer/io/TimerTaskSynchronizer.java | 218 +++++++++++---------- .../jtimer/ui/report/TimerTaskSyncInfoEditor.java | 4 +- src/main/resources/log4j2.xml | 4 +- 8 files changed, 126 insertions(+), 130 deletions(-) diff --git a/src/main/java/org/chorem/jtimer/JTimerConfig.java b/src/main/java/org/chorem/jtimer/JTimerConfig.java index cab25b0..758cb43 100644 --- a/src/main/java/org/chorem/jtimer/JTimerConfig.java +++ b/src/main/java/org/chorem/jtimer/JTimerConfig.java @@ -176,14 +176,6 @@ public class JTimerConfig { } /** - * Returns autosync delay in seconds - * @return auto sync delay - */ - public long getIOSyncAutoSyncDelay() { - return appConfig.getOptionAsLong(JTimerOption.IO_SYNC_AUTOSYNCDELAY.key); - } - - /** * Returns timezone for sync * @return timezone */ @@ -304,7 +296,6 @@ public class JTimerConfig { IO_SAVER_AUTOSAVEDELAY("jtimer.io.saver.autosavedelay", "300"), IO_SYNC_CLASS("jtimer.io.synchronizer.class", "org.chorem.jtimer.io.TimerTaskSynchronizer"), - IO_SYNC_AUTOSYNCDELAY("jtimer.io.synchronizer.autosyncdelay", "3600"), IO_SYNC_TIMEZONE("jtimer.io.synchronizer.timezone", "+01:00"), UI_IDLE_TIME("jtimer.ui.idletime", "300"), diff --git a/src/main/java/org/chorem/jtimer/JTimerFactory.java b/src/main/java/org/chorem/jtimer/JTimerFactory.java index 9f8ab49..de4aef4 100644 --- a/src/main/java/org/chorem/jtimer/JTimerFactory.java +++ b/src/main/java/org/chorem/jtimer/JTimerFactory.java @@ -104,16 +104,12 @@ public class JTimerFactory { // log if (log.isInfoEnabled()) { log.info("Using synchronizer class : " + synchronizerClass); - log.info(" with auto synchronizer delay : " + JTimer.config.getIOSyncAutoSyncDelay()); } try { // get instance synchronizer = (TimerTaskSynchronizer) synchronizerClass.newInstance(); - // set delay to saver - synchronizer.setAutoSyncDelay(JTimer.config.getIOSyncAutoSyncDelay() * 1000); - //set timezone to synchronizer synchronizer.setTimezone(JTimer.config.getIOSyncTimeZone()); diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTask.java b/src/main/java/org/chorem/jtimer/entities/TimerTask.java index 91fd2f3..f59ddd7 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTask.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTask.java @@ -318,7 +318,9 @@ public class TimerTask implements Cloneable, * @param url a String */ public void addSyncInfo(String url) { - addSyncInfo(url, new Date(0)); + if (!url.isEmpty()) { + addSyncInfo(url, new Date(0)); + } } /** @@ -344,11 +346,12 @@ public class TimerTask implements Cloneable, } /** - * Returns all the synchronization info as a List + * Returns all the synchronization info as a List, removes the empty ones first if they exist * * @return a list of TimerTask.SyncInfo */ public List<SyncInfo> getSynchronizingInfoList() { + removeSyncInfo(new SyncInfo("")); return synchronisingInfoList; } diff --git a/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java b/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java index 6ea3066..ed9af7b 100644 --- a/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java +++ b/src/main/java/org/chorem/jtimer/entities/TimerTaskHelper.java @@ -24,7 +24,6 @@ package org.chorem.jtimer.entities; import com.google.gson.JsonArray; import com.google.gson.JsonObject; - import java.time.LocalDate; import java.time.ZoneId; import java.util.ArrayList; @@ -39,7 +38,6 @@ import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import org.apache.commons.lang3.time.DateUtils; -import org.nuiton.util.DateUtil; /** * Helper to remove process code from entity @@ -373,8 +371,8 @@ public class TimerTaskHelper { if (dates.size() != 0) { //iterate over active urls only for (String url : task.getActiveSynchronizingURLList()) { - JsonObject responseJSON = taskURLToJSONObject(task, url, startDate, endDate, withAnnotations, timezone); - jsonObjectList.add(responseJSON); + JsonObject responseJSON = taskURLToJSONObject(task, url, startDate, endDate, withAnnotations, timezone); + jsonObjectList.add(responseJSON); } } diff --git a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java index 7e5c741..e31a847 100644 --- a/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java +++ b/src/main/java/org/chorem/jtimer/io/GTimerIncrementalSaver.java @@ -1446,6 +1446,7 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, // remove task from running task and force save runningTasks.remove(task); saveTask(task); + saveSynchronizationInfo(task); } @Override @@ -1459,11 +1460,12 @@ public class GTimerIncrementalSaver extends AbstractSaver implements Saver, } /** - * Save runing tasks. + * Save runing tasks and their synchronization info */ protected void saveRunningTasks() { synchronized (runningTasks) { runningTasks.forEach(this::saveTask); + runningTasks.forEach(this::saveSynchronizationInfo); } } diff --git a/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java b/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java index b24131b..809ee45 100644 --- a/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java +++ b/src/main/java/org/chorem/jtimer/io/TimerTaskSynchronizer.java @@ -33,20 +33,21 @@ import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; -import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Timer; +import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.chorem.jtimer.data.DataEventListener; import org.chorem.jtimer.entities.SyncInfo; +import org.chorem.jtimer.entities.TimerProject; import org.chorem.jtimer.entities.TimerTask; import org.chorem.jtimer.entities.TimerTaskHelper; /** * - * Class dealing with automated synchronization of tasks + * Class dealing with synchronization of tasks * * Created by servantie on 01/06/16. */ @@ -55,15 +56,11 @@ public class TimerTaskSynchronizer implements DataEventListener { /** log */ private static Log log = LogFactory.getLog(TimerTaskSynchronizer.class); - /** auto sync delay */ - //every hour, check for modifications to sync - protected long autoSyncDelay = 1000 * 60 * 60L; - /** timer to schedule syncs */ protected Timer timer; /** Tasks to sync */ - protected Collection<TimerTask> tasksToSync; + protected Collection<TimerProject> projectsToSync; /** Timezone, defaulted to GMT +1 */ protected String timezone = "+01:00"; @@ -73,20 +70,10 @@ public class TimerTaskSynchronizer implements DataEventListener { */ public TimerTaskSynchronizer() { timer = new Timer(); - timer.schedule(new UpdateTask(), autoSyncDelay, autoSyncDelay); + // a first sync after data is loaded (to be sure of that, + // 60 seconds after start of timer should be enough?) + timer.schedule(new UpdateTask(), 10 * 1000L); log.info("Starting synchronizing thread"); - tasksToSync = Collections.synchronizedCollection(new ArrayList<>()); - - } - - /** - * Change the autosync delay - * @param autoSyncDelay - */ - public void setAutoSyncDelay(long autoSyncDelay) { - if (autoSyncDelay>0) { - this.autoSyncDelay = autoSyncDelay; - } } /** @@ -100,7 +87,7 @@ public class TimerTaskSynchronizer implements DataEventListener { } /** - * Inner Task class to make the automatic sync + * Inner Task class for the first sync */ protected class UpdateTask extends java.util.TimerTask { @@ -109,39 +96,86 @@ public class TimerTaskSynchronizer implements DataEventListener { if (log.isDebugEnabled()) { log.debug("Synchronizer wake up"); } - synchronizeTasks(); + syncAtStart(); } /** - * synchronizes Tasks in remainingTasks + * Does a sync attempt at start on tasks that have sync infos + * fixme:this sync doesn't trigger listener changes on the change of lastSync */ - public void synchronizeTasks(){ + public void syncAtStart() { + if (log.isDebugEnabled()) { + log.debug("Sync At Start"); + } - synchronized (tasksToSync) { - Collection<TimerTask> remainingTasks = new ArrayList<>(tasksToSync); - for (TimerTask task : tasksToSync) { - if (log.isDebugEnabled()){ - log.debug("task " + task.getName() + " being synced."); - } - synchronizeSingleTask(task); - //for now doesn't deal with failure in the update, just task already updated - if (remainingTasks.contains(task)) { - remainingTasks.remove(task); + for (TimerProject project : projectsToSync) { + if (log.isDebugEnabled()) { + log.info("project : " + project.getName()); + } + + List<TimerTask> taskList = project.getSubTasks(); + for (TimerTask task : taskList) { + if (!task.getSynchronizingInfoList().isEmpty()) { + if (log.isDebugEnabled()) { + log.info("task : " + task.getName()); } + synchronizeAtStart(task); + } + } + } + } + } + + /** + * Synchronize for the first sync at startup + * (tests current date against lastSync date, + * syncs if the date is not the same day) + * @param task + * + */ + public void synchronizeAtStart(TimerTask task) { + for (SyncInfo syncInfo : task.getSynchronizingInfoList()) { + if (log.isDebugEnabled()) { + log.debug("Synchronization info : " + syncInfo.getSyncURL()); + } + //if the last sync is not on the same day + if (!DateUtils.isSameDay(new Date(), syncInfo.getLastSync())) { + String syncURL = syncInfo.getSyncURL(); + if (log.isDebugEnabled()) { + log.debug("Sync hasn't been done today for " + syncURL + " " + task.getName() ); + } + JsonObject syncObject = TimerTaskHelper.taskURLToJSONObject(task, syncInfo.getSyncURL(), syncInfo.getLastSync(), new Date(), syncInfo.isWithAnnotations(), timezone); + int syncResult = synchronizeTaskOnURL(syncObject); + if (syncResult > 199 && syncResult < 300) { + if (log.isDebugEnabled()) { + log.debug("Synchronization successful on : " + syncURL); + } + Calendar cal = Calendar.getInstance(); + syncInfo.setLastSync(cal.getTime()); + + } + else if (syncResult == 0) { + if (log.isDebugEnabled()) { + log.debug("Error in connection " + syncURL); } - tasksToSync.clear(); - tasksToSync.addAll(remainingTasks); } } + } } /** - * Synchronizes one Task (calls to synchronizeTaskOnURL for each syncURLList element of the task) + * Synchronizes one Task (calls to synchronizeTaskOnURL + * for each syncURLList element of the task) * * @param task */ public void synchronizeSingleTask(TimerTask task) { - List<JsonObject> jsonObjectList = TimerTaskHelper.taskToJSONFormat(task, false, timezone); + + List<JsonObject> jsonObjectList = new ArrayList<>(); + for (SyncInfo sync : task.getSynchronizingInfoList()) { + JsonObject syncObject = TimerTaskHelper.taskURLToJSONObject(task, sync.getSyncURL(), sync.getLastSync(), new Date(), sync.isWithAnnotations(), timezone); + jsonObjectList.add(syncObject); + } for (JsonObject object : jsonObjectList) { int syncResult = synchronizeTaskOnURL(object); @@ -151,11 +185,6 @@ public class TimerTaskSynchronizer implements DataEventListener { if (syncResult > 199 && syncResult < 300) { successfulSync = true; } - else if (syncResult == 0) { - if (log.isDebugEnabled()) { - log.debug("Error in connection " + syncURL); - } - } //sync successful -> change the last sync time if (successfulSync) { if (log.isDebugEnabled()) { @@ -164,6 +193,11 @@ public class TimerTaskSynchronizer implements DataEventListener { } Calendar cal = Calendar.getInstance(); task.setLastSync(cal.getTime(), syncURL); + } else { + if (log.isDebugEnabled()) { + log.debug("Error in connection " + syncURL); + log.debug("Error code received " + syncResult); + } } } } @@ -222,88 +256,60 @@ public class TimerTaskSynchronizer implements DataEventListener { } /** - * Tasks are added to synchronization list when modified + * Tasks are synchronized when stopped * @param task modified task */ @Override - public void modifyTask(TimerTask task) { - //when a task is modified, add it to the to sync list (if it isn't already there) - if(!tasksToSync.contains(task) && (!tasksToSync.isEmpty())) { - //add it only if the URL is not empty - if ((!task.getSynchronizingInfoList().isEmpty()) && (!task.getSynchronizingURLList().isEmpty())) { - tasksToSync.add(task); + public void stopTask(TimerTask task) { + if (!task.getSynchronizingInfoList().isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("synchronizing task : " + task.getName()); } + synchronizeSingleTask(task); + } else if (!task.getParent().getSynchronizingInfoList().isEmpty()) { + if (log.isDebugEnabled()) { + log.debug("synchronizing parent task : " + task.getParent().getName()); + } + synchronizeSingleTask(task.getParent()); } } /** - * Tasks deleted are removed from synchronization list if they exist in it - * @param task modified task - */ - @Override - public void deleteTask(TimerTask task) { - if (tasksToSync.contains(task)) { - tasksToSync.remove(task); - } - } - - /** - * When the time is modified, the task is added to the sync list - * @param task task where time is changed - * @param date date - * @param time task time + * When tasktime is modified, if it's before the last sync, + * the task is synchronized */ @Override public void setTaskTime(TimerTask task, Date date, Long time) { - if (!tasksToSync.contains(task)) { - //add it only if the URL is not empty - if ((task.getSynchronizingURLList() != null) && !(task.getSynchronizingURLList().isEmpty())) { - tasksToSync.add(task); - + //check if it isn't the current day, to avoid sync every second + if (!DateUtils.isSameDay(new Date(), date)) { + if (!task.getSynchronizingInfoList().isEmpty()) { + for (SyncInfo syncInfo : task.getSynchronizingInfoList()) { + if (!DateUtils.isSameDay(date, syncInfo.getLastSync())) { + syncInfo.setLastSync(date); + } + } + synchronizeSingleTask(task); } - } - } - - /** - * Tasks are added to synchronization list when started - * @param task started task - */ - @Override - public void startTask(TimerTask task) { - if (!tasksToSync.contains(task)) { - //add it only if the URL is not empty - if ((task.getSynchronizingURLList() != null) && !(task.getSynchronizingURLList().isEmpty())) { - tasksToSync.add(task); + //if the task has a parent task with a synchronizing info, then set that sync info + //to that time and try to sync + else if (!task.getParent().getSynchronizingInfoList().isEmpty()) { + TimerTask parentTask = task.getParent(); + for (SyncInfo syncInfo : parentTask.getSynchronizingInfoList()) { + if (!DateUtils.isSameDay(date, syncInfo.getLastSync())) { + syncInfo.setLastSync(date); + } + } + synchronizeSingleTask(parentTask); } } } /** - * Tasks are added to synchronization list when stopped - * @param task modified task + * When data is loaded, get the data to work on */ @Override - public void stopTask(TimerTask task) { - if (!tasksToSync.contains(task)) { - //add it only if the URL is not empty - if ((task.getSynchronizingURLList() != null) && !(task.getSynchronizingURLList().isEmpty())) { - tasksToSync.add(task); - } - } + public void dataLoaded(Collection<TimerProject> projects) { + projectsToSync = projects; } - /** - * When the syncInfo is changed, add the task to sync list - * @param task the task to sync - * @param info the url to sync on (a String) - */ - @Override - public void syncInfoChanged(TimerTask task, SyncInfo info) { - if (!tasksToSync.contains(task)) { - //add it only if the URL is not empty - if ((task.getSynchronizingURLList() != null) && !(task.getSynchronizingURLList().isEmpty())) { - tasksToSync.add(task); - } - } - } } diff --git a/src/main/java/org/chorem/jtimer/ui/report/TimerTaskSyncInfoEditor.java b/src/main/java/org/chorem/jtimer/ui/report/TimerTaskSyncInfoEditor.java index f5088e1..c982917 100644 --- a/src/main/java/org/chorem/jtimer/ui/report/TimerTaskSyncInfoEditor.java +++ b/src/main/java/org/chorem/jtimer/ui/report/TimerTaskSyncInfoEditor.java @@ -366,8 +366,8 @@ public class TimerTaskSyncInfoEditor extends FrameView implements ActionListener */ public void remove(SyncInfo sync) { if (syncInfoList.contains(sync)) { - fireTableRowsDeleted(syncInfoList.indexOf(sync), syncInfoList.indexOf(sync)); syncInfoList.remove(sync); + fireTableRowsDeleted(syncInfoList.indexOf(sync), syncInfoList.indexOf(sync)); } } } @@ -425,7 +425,7 @@ public class TimerTaskSyncInfoEditor extends FrameView implements ActionListener //if the test button has been clicked, test the sync on the URL and returns a message to the user //tests only if the info exists if (task.getSynchronizingInfoList().contains(infoToUse)) { - JsonObject testObject = TimerTaskHelper.taskURLToJSONObject(task, infoToUse.getSyncURL(), false, timezone); + JsonObject testObject = TimerTaskHelper.taskURLToJSONObject(task, infoToUse.getSyncURL(), infoToUse.getLastSync(), new Date(), infoToUse.isWithAnnotations(), timezone); int responseCode = TimerTaskSynchronizer.synchronizeTaskOnURL(testObject); if (responseCode > 199 && responseCode < 300) { diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml index 39ee61a..6d4d800 100644 --- a/src/main/resources/log4j2.xml +++ b/src/main/resources/log4j2.xml @@ -29,9 +29,9 @@ </Appenders> <Loggers> - <Logger name="org.chorem.jtimer" level="info"/> + <Logger name="org.chorem.jtimer" level="debug"/> - <Root level="warn"> + <Root level="debug"> <AppenderRef ref="Console" /> </Root> </Loggers> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.