Added code to push on save to check for sql constraint exceptions and try to recover

pull/14/head
Sam Bosley 12 years ago committed by Tim Su
parent 4389118e91
commit 02bcbff4e2

@ -441,7 +441,7 @@ public final class ActFmSyncService {
}
task.putTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC, true);
taskDao.saveExisting(task);
taskDao.saveExistingWithSqlConstraintCheck(task);
}
/**

@ -234,7 +234,7 @@ public final class GtasksSyncService {
gtasksMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
metadataService.save(gtasksMetadata);
task.putTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC, true);
taskDao.saveExisting(task);
taskDao.saveExistingWithSqlConstraintCheck(task);
}
public void pushMetadataOnSave(Metadata model, GtasksInvoker invoker) throws IOException {

@ -10,6 +10,7 @@ import android.database.sqlite.SQLiteConstraintException;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.DatabaseDao;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
@ -19,6 +20,7 @@ import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.data.SyncFlags;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.TaskApiDao;
import com.todoroo.astrid.reminders.Notifications;
@ -282,6 +284,68 @@ public class TaskDao extends DatabaseDao<Task> {
return result;
}
private static final Property<?>[] SQL_CONSTRAINT_MERGE_PROPERTIES = new Property<?>[] {
Task.ID,
Task.REMOTE_ID,
Task.TITLE,
Task.IMPORTANCE,
Task.DUE_DATE,
Task.CREATION_DATE,
Task.DELETION_DATE,
Task.NOTES,
Task.HIDE_UNTIL,
Task.RECURRENCE
};
public void saveExistingWithSqlConstraintCheck(Task item) {
try {
saveExisting(item);
} catch (SQLiteConstraintException e) {
Long remoteId = item.getValue(Task.REMOTE_ID);
TodorooCursor<Task> tasksWithRemoteId = query(Query.select(SQL_CONSTRAINT_MERGE_PROPERTIES)
.where(Task.REMOTE_ID.eq(remoteId)));
try {
if (tasksWithRemoteId.getCount() > 0) {
for (tasksWithRemoteId.moveToFirst();
!tasksWithRemoteId.isAfterLast(); tasksWithRemoteId.moveToNext()) {
Task curr = new Task(tasksWithRemoteId);
if (curr.getId() == item.getId())
continue;
compareAndMergeAfterConflict(curr, fetch(item.getId(), SQL_CONSTRAINT_MERGE_PROPERTIES));
return;
}
} else {
// We probably want to know about this case, because
// it means that the constraint error isn't caused by
// REMOTE_ID
throw e;
}
} finally {
tasksWithRemoteId.close();
}
}
}
private void compareAndMergeAfterConflict(Task existing, Task newConflict) {
boolean match = true;
for (Property<?> p : SQL_CONSTRAINT_MERGE_PROPERTIES) {
if (!existing.getValue(p).equals(newConflict.getValue(p))) {
match = false;
}
}
if (!match) {
if (existing.getValue(Task.CREATION_DATE).equals(newConflict.getValue(Task.CREATION_DATE)))
newConflict.setValue(Task.CREATION_DATE, newConflict.getValue(Task.CREATION_DATE) + 1000L);
newConflict.clearValue(Task.REMOTE_ID);
newConflict.clearTransitory(SyncFlags.ACTFM_SUPPRESS_SYNC);
newConflict.clearTransitory(SyncFlags.GTASKS_SUPPRESS_SYNC);
saveExisting(newConflict);
} else {
delete(newConflict.getId());
}
}
/**
* Called after the task is saved. This differs from the call in
* TaskApiDao in that it runs hooks that need to be run from within

Loading…
Cancel
Save