diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncThread.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncThread.java index a38d6a6c3..025add434 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncThread.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/ActFmSyncThread.java @@ -15,6 +15,7 @@ import android.util.Log; import com.todoroo.andlib.service.Autowired; import com.todoroo.andlib.service.ContextManager; import com.todoroo.andlib.service.DependencyInjectionService; +import com.todoroo.andlib.utility.AndroidUtilities; import com.todoroo.andlib.utility.DateUtilities; import com.todoroo.astrid.actfm.sync.messages.BriefMe; import com.todoroo.astrid.actfm.sync.messages.ClientToServerMessage; @@ -132,6 +133,7 @@ public class ActFmSyncThread { while ((pendingMessages.isEmpty() && !timeForBackgroundSync()) || !actFmPreferenceService.isLoggedIn()) { try { monitor.wait(); + AndroidUtilities.sleepDeep(500L); // Wait briefly for large database operations to finish (e.g. adding a task with several tags may trigger a message before all saves are done--fix this?) } catch (InterruptedException e) { // Ignored } @@ -188,7 +190,9 @@ public class ActFmSyncThread { } } } -// replayOutstandingChanges(); + JSONArray errors = response.optJSONArray("errors"); + boolean errorsExist = (errors != null && errors.length() > 0); + replayOutstandingChanges(errorsExist); } batchSize = Math.min(batchSize, messageBatch.size()) * 2; @@ -212,9 +216,9 @@ public class ActFmSyncThread { // Reapplies changes still in the outstanding tables to the local database // Called after a batch has finished processing - private void replayOutstandingChanges() { - new ReplayOutstandingEntries(Task.class, NameMaps.TABLE_ID_TASKS, taskDao, taskOutstandingDao).execute(); - new ReplayOutstandingEntries(TagData.class, NameMaps.TABLE_ID_TAGS, tagDataDao, tagOutstandingDao).execute(); + private void replayOutstandingChanges(boolean afterErrors) { + new ReplayOutstandingEntries(Task.class, NameMaps.TABLE_ID_TASKS, taskDao, taskOutstandingDao, afterErrors).execute(); + new ReplayOutstandingEntries(TagData.class, NameMaps.TABLE_ID_TAGS, tagDataDao, tagOutstandingDao, afterErrors).execute(); } private boolean timeForBackgroundSync() { diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/MakeChanges.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/MakeChanges.java index 09860e4cb..1d377ba84 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/MakeChanges.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/MakeChanges.java @@ -160,15 +160,25 @@ public class MakeChanges extends ServerToClientMessage super(model, changes, uuid); } + @SuppressWarnings("null") @Override public void performChanges() { JSONArray addTags = changes.optJSONArray("tag_added"); - if (addTags != null && addTags.length() > 0) { - if (!model.isSaved()) { // We don't have the local task id - long localId = dao.localIdFromUuid(uuid); - model.setId(localId); - } + JSONArray removeTags = changes.optJSONArray("tag_removed"); + boolean tagsAdded = (addTags != null && addTags.length() > 0); + boolean tagsRemoved = (removeTags != null && removeTags.length() > 0); + if (!tagsAdded && !tagsRemoved) + return; + + long localId; + if (!model.isSaved()) { // We don't have the local task id + localId = dao.localIdFromUuid(uuid); + model.setId(localId); + } else { + localId = model.getId(); + } + if (tagsAdded) { if (model.isSaved()) { TagService tagService = TagService.getInstance(); for (int i = 0; i < addTags.length(); i++) { @@ -182,8 +192,7 @@ public class MakeChanges extends ServerToClientMessage } } - JSONArray removeTags = changes.optJSONArray("tag_removed"); - if (removeTags != null) { + if (tagsRemoved) { ArrayList toRemove = new ArrayList(removeTags.length()); for (int i = 0; i < removeTags.length(); i++) { try { @@ -193,7 +202,7 @@ public class MakeChanges extends ServerToClientMessage // } } - TagService.getInstance().deleteLinks(uuid, toRemove.toArray(new String[toRemove.size()])); + TagService.getInstance().deleteLinks(localId, uuid, toRemove.toArray(new String[toRemove.size()])); } } diff --git a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ReplayOutstandingEntries.java b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ReplayOutstandingEntries.java index d95bc6971..471bdf702 100644 --- a/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ReplayOutstandingEntries.java +++ b/astrid/plugin-src/com/todoroo/astrid/actfm/sync/messages/ReplayOutstandingEntries.java @@ -24,13 +24,15 @@ public class ReplayOutstandingEntries dao; private final OutstandingEntryDao outstandingDao; + private final boolean afterErrors; - public ReplayOutstandingEntries(Class modelClass, String table, RemoteModelDao dao, OutstandingEntryDao outstandingDao) { + public ReplayOutstandingEntries(Class modelClass, String table, RemoteModelDao dao, OutstandingEntryDao outstandingDao, boolean afterErrors) { this.modelClass = modelClass; this.outstandingClass = DaoReflectionHelpers.getOutstandingClass(modelClass); this.table = table; this.dao = dao; this.outstandingDao = outstandingDao; + this.afterErrors = afterErrors; } public void execute() { @@ -65,14 +67,13 @@ public class ReplayOutstandingEntries property = NameMaps.localColumnNameToProperty(table, column); - if (property == null) - throw new RuntimeException("No local property found for local column " + column + " in table " + table); - // set values to model - property.accept(visitor, instance); + if (property != null) + property.accept(visitor, instance); } - model.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); + if (afterErrors) + model.putTransitory(SyncFlags.ACTFM_SUPPRESS_OUTSTANDING_ENTRIES, true); dao.saveExisting(model); outstanding.moveToPrevious(); // Move back one to undo the last iteration of the for loop diff --git a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java index d95718b35..bb53af011 100644 --- a/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java +++ b/astrid/plugin-src/com/todoroo/astrid/tags/TagService.java @@ -300,8 +300,9 @@ public final class TagService { * @param taskUuid * @param tagUuid */ - public void deleteLink(String taskUuid, String tagUuid) { + public void deleteLink(long taskId, String taskUuid, String tagUuid) { Metadata deleteTemplate = new Metadata(); + deleteTemplate.setValue(Metadata.TASK, taskId); // Need this for recording changes in outstanding table deleteTemplate.setValue(Metadata.DELETION_DATE, DateUtilities.now()); metadataDao.update(Criterion.and(MetadataCriteria.withKey(TagMetadata.KEY), Metadata.DELETION_DATE.eq(0), TagMetadata.TASK_UUID.eq(taskUuid), TagMetadata.TAG_UUID.eq(tagUuid)), deleteTemplate); @@ -312,8 +313,9 @@ public final class TagService { * @param taskUuid * @param tagUuids */ - public void deleteLinks(String taskUuid, String[] tagUuids) { + public void deleteLinks(long taskId, String taskUuid, String[] tagUuids) { Metadata deleteTemplate = new Metadata(); + deleteTemplate.setValue(Metadata.TASK, taskId); // Need this for recording changes in outstanding table deleteTemplate.setValue(Metadata.DELETION_DATE, DateUtilities.now()); if (tagUuids != null) { // TODO: We have this as a loop until I can figure out how to make update with multiple rows record outstanding @@ -513,7 +515,7 @@ public final class TagService { // Mark as deleted links that don't exist anymore Metadata deletedLinkTemplate = new Metadata(); deletedLinkTemplate.setValue(Metadata.DELETION_DATE, DateUtilities.now()); - deleteLinks(taskUuid, existingLinks.toArray(new String[existingLinks.size()])); + deleteLinks(taskId, taskUuid, existingLinks.toArray(new String[existingLinks.size()])); return true; }