Update google task sync

* Dont delete stale gtasks on initial or manual sync
* Delete gtask metadata when push returns 404 response

Impacts #114
pull/189/head
Alex Baker 10 years ago
parent 49dba7f57b
commit 1ee9c4a542

@ -209,13 +209,10 @@ public abstract class AbstractModel implements Parcelable, Cloneable {
// resolve properties that were retrieved with a different type than accessed
try {
if(value instanceof String && property instanceof LongProperty) {
log.debug("{}={} stored as string instead of long", columnName, value);
return (TYPE) Long.valueOf((String) value);
} else if(value instanceof String && property instanceof IntegerProperty) {
log.debug("{}={} stored as string instead of int", columnName, value);
return (TYPE) Integer.valueOf((String) value);
} else if(value instanceof Integer && property instanceof LongProperty) {
log.debug("{}={} stored as int instead of long", columnName, value);
return (TYPE) Long.valueOf(((Number) value).longValue());
}
return (TYPE) value;

@ -11,6 +11,9 @@ import android.database.Cursor;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@ -26,6 +29,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
*/
public class DatabaseDao<TYPE extends AbstractModel> {
private static final Logger log = LoggerFactory.getLogger(DatabaseDao.class);
private final Class<TYPE> modelClass;
private Table table;
@ -139,6 +144,7 @@ public class DatabaseDao<TYPE extends AbstractModel> {
* @return # of deleted items
*/
public int deleteWhere(Criterion where) {
log.debug("deleteWhere({})", where);
return database.delete(table.name,
where.toString(), null);
}

@ -58,7 +58,7 @@ public class GtasksBackgroundService extends InjectingService {
SyncV2Provider provider = gtasksSyncV2Provider;
if (provider.isActive()) {
provider.synchronizeActiveTasks(false, new SyncResultCallback() {
provider.synchronizeActiveTasks(new SyncResultCallback() {
@Override
public void started() {
}

@ -88,7 +88,7 @@ public class GtasksListFragment extends SubtasksListFragment {
private void refreshData(final boolean manual) {
((TextView)getView().findViewById(android.R.id.empty)).setText(R.string.DLG_loading);
syncService.synchronizeList(list, manual, new IndeterminateProgressBarSyncResultCallback(getActivity(), new Runnable() {
syncService.synchronizeList(list, new IndeterminateProgressBarSyncResultCallback(getActivity(), new Runnable() {
@Override
public void run() {
if (manual) {

@ -64,6 +64,8 @@ public class GtasksInvoker {
}
} else if (statusCode == 400 || statusCode == 500) {
throw h;
} else if (statusCode == 404) {
throw new HttpNotFoundException(h);
} else {
log.error(statusCode + ": " + h.getStatusMessage(), e);
}

@ -0,0 +1,11 @@
package com.todoroo.astrid.gtasks.api;
import com.google.api.client.http.HttpResponseException;
import java.io.IOException;
public class HttpNotFoundException extends IOException {
public HttpNotFoundException(HttpResponseException e) {
super(e.getMessage());
}
}

@ -23,6 +23,7 @@ import com.todoroo.astrid.gtasks.GtasksPreferenceService;
import com.todoroo.astrid.gtasks.api.CreateRequest;
import com.todoroo.astrid.gtasks.api.GtasksApiUtilities;
import com.todoroo.astrid.gtasks.api.GtasksInvoker;
import com.todoroo.astrid.gtasks.api.HttpNotFoundException;
import com.todoroo.astrid.gtasks.api.MoveRequest;
import com.todoroo.astrid.gtasks.auth.GtasksTokenValidator;
import com.todoroo.astrid.service.MetadataService;
@ -305,7 +306,13 @@ public class GtasksSyncService {
}
if (!newlyCreated) {
invoker.updateGtask(listId, remoteModel);
try {
invoker.updateGtask(listId, remoteModel);
} catch(HttpNotFoundException e) {
log.error("Received 404 response, deleting {}", gtasksMetadata);
metadataDao.delete(gtasksMetadata.getId());
return;
}
} else {
String parent = gtasksMetadataService.getRemoteParentId(gtasksMetadata);
String priorSibling = gtasksMetadataService.getRemoteSiblingId(listId, gtasksMetadata);

@ -48,7 +48,6 @@ import org.tasks.sync.SyncExecutor;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@ -121,10 +120,7 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
}
@Override
public void synchronizeActiveTasks(final boolean manual, final SyncResultCallback callback) {
// TODO: Improve this logic. Should only be able to import from settings or something.
final boolean isImport = false;
public void synchronizeActiveTasks(final SyncResultCallback callback) {
callback.started();
gtasksPreferenceService.recordSyncStart();
@ -152,7 +148,7 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
executor.execute(callback, new Runnable() {
@Override
public void run() {
synchronizeListHelper(list, invoker, manual, handler, isImport);
synchronizeListHelper(list, invoker, handler);
if (finisher.decrementAndGet() == 0) {
pushUpdated(invoker);
finishSync(callback);
@ -190,7 +186,7 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
}
@Override
public void synchronizeList(Object list, final boolean manual, final SyncResultCallback callback) {
public void synchronizeList(Object list, final SyncResultCallback callback) {
if (!(list instanceof StoreObject)) {
return;
}
@ -199,8 +195,6 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
return;
}
final boolean isImport = false;
callback.started();
executor.execute(callback, new Runnable() {
@ -210,7 +204,7 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
String authToken = getValidatedAuthToken();
gtasksSyncService.waitUntilEmpty();
final GtasksInvoker service = new GtasksInvoker(gtasksTokenValidator, authToken);
synchronizeListHelper(gtasksList, service, manual, null, isImport);
synchronizeListHelper(gtasksList, service, null);
} finally {
callback.finished();
}
@ -233,13 +227,11 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
}
private synchronized void synchronizeListHelper(StoreObject list, GtasksInvoker invoker,
boolean manual, SyncExceptionHandler errorHandler, boolean isImport) {
SyncExceptionHandler errorHandler) {
String listId = list.getValue(GtasksList.REMOTE_ID);
long lastSyncDate;
if (!manual && list.containsNonNullValue(GtasksList.LAST_SYNC)) {
long lastSyncDate = 0;
if (list.containsNonNullValue(GtasksList.LAST_SYNC)) {
lastSyncDate = list.getValue(GtasksList.LAST_SYNC);
} else {
lastSyncDate = 0;
}
/**
@ -262,32 +254,16 @@ public class GtasksSyncV2Provider extends SyncV2Provider {
includeDeletedAndHidden, lastSyncDate);
List<com.google.api.services.tasks.model.Task> tasks = taskList.getItems();
if (tasks != null) {
HashSet<Long> localIds = new HashSet<>(tasks.size());
for (com.google.api.services.tasks.model.Task t : tasks) {
GtasksTaskContainer container = parseRemoteTask(t, listId);
gtasksMetadataService.findLocalMatch(container);
container.gtaskMetadata.setValue(GtasksMetadata.GTASKS_ORDER,
Long.parseLong(t.getPosition()));
container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK,
gtasksMetadataService.localIdForGtasksId(t.getParent()));
container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC,
DateUtilities.now() + 1000L);
container.gtaskMetadata.setValue(GtasksMetadata.GTASKS_ORDER, Long.parseLong(t.getPosition()));
container.gtaskMetadata.setValue(GtasksMetadata.PARENT_TASK, gtasksMetadataService.localIdForGtasksId(t.getParent()));
container.gtaskMetadata.setValue(GtasksMetadata.LAST_SYNC, DateUtilities.now() + 1000L);
write(container);
localIds.add(container.task.getId());
}
list.setValue(GtasksList.LAST_SYNC, DateUtilities.now());
storeObjectDao.persist(list);
if(lastSyncDate == 0 && !isImport) {
Criterion delete = Criterion.and(Metadata.KEY.eq(GtasksMetadata.METADATA_KEY),
GtasksMetadata.LIST_ID.eq(listId),
Criterion.not(Metadata.TASK.in(localIds)));
taskDeleter.deleteWhere(
Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
where(delete)));
metadataService.deleteWhere(delete);
}
gtasksTaskListUpdater.correctOrderAndIndentForList(listId);
}
} catch (IOException e) {

@ -137,7 +137,7 @@ public class SyncActionHelper {
// --- sync logic
protected void performSyncServiceV2Sync() {
boolean syncOccurred = syncService.synchronizeActiveTasks(false, syncResultCallback);
boolean syncOccurred = syncService.synchronizeActiveTasks(syncResultCallback);
if (syncOccurred) {
preferences.setLong(PREF_LAST_AUTO_SYNC, DateUtilities.now());
}
@ -215,7 +215,7 @@ public class SyncActionHelper {
}
} else {
syncService.synchronizeActiveTasks(true, syncResultCallback);
syncService.synchronizeActiveTasks(syncResultCallback);
}
}

@ -70,13 +70,6 @@ public class MetadataService {
return metadataDao.query(query);
}
/**
* Delete from metadata table where rows match a certain condition
*/
public void deleteWhere(Criterion where) {
metadataDao.deleteWhere(where);
}
/**
* Delete from metadata table where rows match a certain condition
* @param where predicate for which rows to update

@ -62,11 +62,10 @@ public class SyncV2Service {
/**
* Initiate synchronization of active tasks
*
* @param manual if manual sync
* @param callback result callback
* @return true if any servide was logged in and initiated a sync
*/
public boolean synchronizeActiveTasks(final boolean manual, SyncResultCallback callback) {
public boolean synchronizeActiveTasks(SyncResultCallback callback) {
final List<SyncV2Provider> active = activeProviders();
if (active.size() == 0) {
@ -74,9 +73,9 @@ public class SyncV2Service {
}
if (active.size() > 1) { // This should never happen anymore--they can't be active at the same time, but if for some reason they both are, just use ActFm
active.get(1).synchronizeActiveTasks(manual, new WidgetUpdatingCallbackWrapper(context, callback));
active.get(1).synchronizeActiveTasks(new WidgetUpdatingCallbackWrapper(context, callback));
} else if (active.size() == 1) {
active.get(0).synchronizeActiveTasks(manual, new WidgetUpdatingCallbackWrapper(context, callback));
active.get(0).synchronizeActiveTasks(new WidgetUpdatingCallbackWrapper(context, callback));
}
return true;
@ -86,13 +85,12 @@ public class SyncV2Service {
* Initiate synchronization of task list
*
* @param list list object
* @param manual if manual sync
* @param callback result callback
*/
public void synchronizeList(Object list, boolean manual, SyncResultCallback callback) {
public void synchronizeList(Object list, SyncResultCallback callback) {
for(SyncV2Provider provider : providers) {
if(provider.isActive()) {
provider.synchronizeList(list, manual, new WidgetUpdatingCallbackWrapper(context, callback));
provider.synchronizeList(list, new WidgetUpdatingCallbackWrapper(context, callback));
}
}
}

@ -1,7 +1,6 @@
package com.todoroo.astrid.service;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.sql.Criterion;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.dao.TaskDao;
@ -44,14 +43,7 @@ public class TaskDeleter {
}
public int purgeDeletedTasks() {
return deleteWhere(Task.DELETION_DATE.gt(0));
}
/**
* Delete all tasks matching a given criterion
*/
public int deleteWhere(Criterion criteria) {
return taskDao.deleteWhere(criteria);
return taskDao.deleteWhere(Task.DELETION_DATE.gt(0));
}
/**

@ -37,15 +37,14 @@ abstract public class SyncV2Provider {
* @param manual whether manually triggered
* @param callback callback object
*/
abstract public void synchronizeActiveTasks(boolean manual, SyncResultCallback callback);
abstract public void synchronizeActiveTasks(SyncResultCallback callback);
/**
* Synchronize a single list
* @param list object representing list (TaskListActivity-dependent)
* @param manual whether was manually triggered
* @param callback callback object
*/
abstract public void synchronizeList(Object list, boolean manual, SyncResultCallback callback);
abstract public void synchronizeList(Object list, SyncResultCallback callback);
/**
* @return sync utility instance

Loading…
Cancel
Save