Implemented delayed pushing for task list ordering

pull/14/head
Sam Bosley 12 years ago
parent 565e4adf54
commit adcf8cce74

@ -323,65 +323,6 @@ public final class ActFmSyncService {
parameters[i+2] = getParameters[i]; parameters[i+2] = getParameters[i];
return actFmInvoker.invoke(method, parameters); return actFmInvoker.invoke(method, parameters);
} }
//
// // --- helpers
// private void synchronizeAttachments(JSONObject item, Task model) {
// TodorooCursor<Metadata> attachments = metadataService.query(Query.select(Metadata.PROPERTIES)
// .where(Criterion.and(MetadataCriteria.byTaskAndwithKey(model.getId(),
// FileMetadata.METADATA_KEY), FileMetadata.REMOTE_ID.gt(0))));
// try {
// HashMap<Long, Metadata> currentFiles = new HashMap<Long, Metadata>();
// for (attachments.moveToFirst(); !attachments.isAfterLast(); attachments.moveToNext()) {
// Metadata m = new Metadata(attachments);
// currentFiles.put(m.getValue(FileMetadata.REMOTE_ID), m);
// }
//
// JSONArray remoteFiles = item.getJSONArray("attachments");
// for (int i = 0; i < remoteFiles.length(); i++) {
// JSONObject file = remoteFiles.getJSONObject(i);
//
// long id = file.optLong("id");
// if (currentFiles.containsKey(id)) {
// // Match, make sure name and url are up to date, then remove from map
// Metadata fileMetadata = currentFiles.get(id);
// fileMetadata.setValue(FileMetadata.URL, file.getString("url"));
// fileMetadata.setValue(FileMetadata.NAME, file.getString("name"));
// metadataService.save(fileMetadata);
// currentFiles.remove(id);
// } else {
// // Create new file attachment
// Metadata newAttachment = FileMetadata.createNewFileMetadata(model.getId(), "",
// file.getString("name"), file.getString("content_type"));
// String url = file.getString("url");
// newAttachment.setValue(FileMetadata.URL, url);
// newAttachment.setValue(FileMetadata.REMOTE_ID, id);
// metadataService.save(newAttachment);
// }
// }
//
// // Remove all the leftovers
// Set<Long> attachmentsToDelete = currentFiles.keySet();
// for (Long remoteId : attachmentsToDelete) {
// Metadata toDelete = currentFiles.get(remoteId);
// String path = toDelete.getValue(FileMetadata.FILE_PATH);
// if (TextUtils.isEmpty(path))
// metadataService.delete(toDelete);
// else {
// File f = new File(toDelete.getValue(FileMetadata.FILE_PATH));
// if (!f.exists() || f.delete()) {
// metadataService.delete(toDelete);
// }
//
// }
// }
//
// } catch (JSONException e) {
// e.printStackTrace();
// } finally {
// attachments.close();
// }
// }
protected void handleException(String message, Exception exception) { protected void handleException(String message, Exception exception) {
Log.w("actfm-sync", message, exception); Log.w("actfm-sync", message, exception);

@ -106,7 +106,7 @@ public class ActFmSyncThread {
private static volatile ActFmSyncThread instance; private static volatile ActFmSyncThread instance;
public static synchronized ActFmSyncThread getInstance() { public static ActFmSyncThread getInstance() {
if (instance == null) { if (instance == null) {
synchronized(ActFmSyncThread.class) { synchronized(ActFmSyncThread.class) {
if (instance == null) { if (instance == null) {
@ -124,6 +124,7 @@ public class ActFmSyncThread {
if (instance == null) { if (instance == null) {
List<ClientToServerMessage<?>> syncQueue = Collections.synchronizedList(new LinkedList<ClientToServerMessage<?>>()); List<ClientToServerMessage<?>> syncQueue = Collections.synchronizedList(new LinkedList<ClientToServerMessage<?>>());
ActFmSyncMonitor monitor = ActFmSyncMonitor.getInstance(); ActFmSyncMonitor monitor = ActFmSyncMonitor.getInstance();
ActFmSyncWaitingPool waitingPool = ActFmSyncWaitingPool.getInstance();
instance = new ActFmSyncThread(syncQueue, monitor); instance = new ActFmSyncThread(syncQueue, monitor);
@ -131,7 +132,7 @@ public class ActFmSyncThread {
tagDataDao.addListener(new SyncDatabaseListener<TagData>(instance, ModelType.TYPE_TAG)); tagDataDao.addListener(new SyncDatabaseListener<TagData>(instance, ModelType.TYPE_TAG));
userActivityDao.addListener(new SyncDatabaseListener<UserActivity>(instance, ModelType.TYPE_ACTIVITY)); userActivityDao.addListener(new SyncDatabaseListener<UserActivity>(instance, ModelType.TYPE_ACTIVITY));
taskAttachmentDao.addListener(new SyncDatabaseListener<TaskAttachment>(instance, ModelType.TYPE_ATTACHMENT)); taskAttachmentDao.addListener(new SyncDatabaseListener<TaskAttachment>(instance, ModelType.TYPE_ATTACHMENT));
taskListMetadataDao.addListener(new SyncDatabaseListener<TaskListMetadata>(instance, ModelType.TYPE_TASK_LIST_METADATA)); taskListMetadataDao.addListener(new TaskListMetadataSyncDatabaseListener(instance, waitingPool, ModelType.TYPE_TASK_LIST_METADATA));
instance.startSyncThread(); instance.startSyncThread();
} }

@ -0,0 +1,56 @@
package com.todoroo.astrid.actfm.sync;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.todoroo.andlib.utility.AndroidUtilities;
import com.todoroo.astrid.actfm.sync.messages.ClientToServerMessage;
public class ActFmSyncWaitingPool {
private static volatile ActFmSyncWaitingPool instance;
public static ActFmSyncWaitingPool getInstance() {
if (instance == null) {
synchronized(ActFmSyncWaitingPool.class) {
if (instance == null) {
instance = new ActFmSyncWaitingPool();
}
}
}
return instance;
}
private static final long WAIT_TIME = 15 * 1000L;
private final ExecutorService singleThreadPool;
private final List<ClientToServerMessage<?>> pendingMessages;
private final Runnable delayMessageRunnable = new Runnable() {
@Override
public void run() {
if (pendingMessages.isEmpty())
return;
AndroidUtilities.sleepDeep(WAIT_TIME);
while (!pendingMessages.isEmpty()) {
ActFmSyncThread.getInstance().enqueueMessage(pendingMessages.remove(0), null);
}
}
};
private ActFmSyncWaitingPool() {
super();
singleThreadPool = Executors.newSingleThreadExecutor();
pendingMessages = Collections.synchronizedList(new LinkedList<ClientToServerMessage<?>>());
}
public synchronized void enqueueMessage(ClientToServerMessage<?> message) {
if (!pendingMessages.contains(message)) {
pendingMessages.add(message);
singleThreadPool.submit(delayMessageRunnable);
}
}
}

@ -4,6 +4,7 @@ import com.todoroo.andlib.data.AbstractModel;
import com.todoroo.andlib.data.DatabaseDao.ModelUpdateListener; import com.todoroo.andlib.data.DatabaseDao.ModelUpdateListener;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.ModelType; import com.todoroo.astrid.actfm.sync.ActFmSyncThread.ModelType;
import com.todoroo.astrid.actfm.sync.messages.ChangesHappened; import com.todoroo.astrid.actfm.sync.messages.ChangesHappened;
import com.todoroo.astrid.actfm.sync.messages.ClientToServerMessage;
public class SyncDatabaseListener<MTYPE extends AbstractModel> implements ModelUpdateListener<MTYPE> { public class SyncDatabaseListener<MTYPE extends AbstractModel> implements ModelUpdateListener<MTYPE> {
@ -18,8 +19,12 @@ public class SyncDatabaseListener<MTYPE extends AbstractModel> implements ModelU
public void onModelUpdated(MTYPE model, boolean outstandingEntries) { public void onModelUpdated(MTYPE model, boolean outstandingEntries) {
if (outstandingEntries) { if (outstandingEntries) {
ChangesHappened<?, ?> ch = ChangesHappened.instantiateChangesHappened(model.getId(), modelType); ChangesHappened<?, ?> ch = ChangesHappened.instantiateChangesHappened(model.getId(), modelType);
actFmSyncThread.enqueueMessage(ch, null); enqueueMessage(model, ch);
} }
} }
protected void enqueueMessage(MTYPE model, ClientToServerMessage<?> message) {
actFmSyncThread.enqueueMessage(message, null);
}
} }

@ -0,0 +1,24 @@
package com.todoroo.astrid.actfm.sync;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.ModelType;
import com.todoroo.astrid.actfm.sync.messages.ClientToServerMessage;
import com.todoroo.astrid.data.TaskListMetadata;
public class TaskListMetadataSyncDatabaseListener extends SyncDatabaseListener<TaskListMetadata> {
private final ActFmSyncWaitingPool waitingPool;
public TaskListMetadataSyncDatabaseListener(ActFmSyncThread actFmSyncThread, ActFmSyncWaitingPool waitingPool, ModelType modelType) {
super(actFmSyncThread, modelType);
this.waitingPool = waitingPool;
}
@Override
protected void enqueueMessage(TaskListMetadata model, ClientToServerMessage<?> message) {
if (model.getSetValues().containsKey(TaskListMetadata.TASK_IDS.name))
waitingPool.enqueueMessage(message);
else
super.enqueueMessage(model, message);
}
}

@ -32,7 +32,6 @@ import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.TaskAttachment; import com.todoroo.astrid.data.TaskAttachment;
import com.todoroo.astrid.data.TaskAttachmentOutstanding; import com.todoroo.astrid.data.TaskAttachmentOutstanding;
import com.todoroo.astrid.data.TaskListMetadata; import com.todoroo.astrid.data.TaskListMetadata;
import com.todoroo.astrid.data.TaskListMetadataOutstanding;
import com.todoroo.astrid.data.TaskOutstanding; import com.todoroo.astrid.data.TaskOutstanding;
import com.todoroo.astrid.data.UserActivity; import com.todoroo.astrid.data.UserActivity;
import com.todoroo.astrid.data.UserActivityOutstanding; import com.todoroo.astrid.data.UserActivityOutstanding;
@ -42,9 +41,9 @@ public class ChangesHappened<TYPE extends RemoteModel, OE extends OutstandingEnt
private static final String ERROR_TAG = "actfm-changes-happened"; private static final String ERROR_TAG = "actfm-changes-happened";
private final Class<OE> outstandingClass; protected final Class<OE> outstandingClass;
private final List<OE> changes; protected final List<OE> changes;
private final OutstandingEntryDao<OE> outstandingDao; protected final OutstandingEntryDao<OE> outstandingDao;
public static final String CHANGES_KEY = "changes"; public static final String CHANGES_KEY = "changes";
@ -63,7 +62,7 @@ public class ChangesHappened<TYPE extends RemoteModel, OE extends OutstandingEnt
return new ChangesHappened<TaskAttachment, TaskAttachmentOutstanding>(id, TaskAttachment.class, return new ChangesHappened<TaskAttachment, TaskAttachmentOutstanding>(id, TaskAttachment.class,
PluginServices.getTaskAttachmentDao(), PluginServices.getTaskAttachmentOutstandingDao()); PluginServices.getTaskAttachmentDao(), PluginServices.getTaskAttachmentOutstandingDao());
case TYPE_TASK_LIST_METADATA: case TYPE_TASK_LIST_METADATA:
return new ChangesHappened<TaskListMetadata, TaskListMetadataOutstanding>(id, TaskListMetadata.class, return new TaskListMetadataChangesHappened(id, TaskListMetadata.class,
PluginServices.getTaskListMetadataDao(), PluginServices.getTaskListMetadataOutstandingDao()); PluginServices.getTaskListMetadataDao(), PluginServices.getTaskListMetadataOutstandingDao());
default: default:
return null; return null;
@ -157,7 +156,7 @@ public class ChangesHappened<TYPE extends RemoteModel, OE extends OutstandingEnt
return array; return array;
} }
private void populateChanges() { protected void populateChanges() {
TodorooCursor<OE> cursor = outstandingDao.query(Query.select(DaoReflectionHelpers.getModelProperties(outstandingClass)) TodorooCursor<OE> cursor = outstandingDao.query(Query.select(DaoReflectionHelpers.getModelProperties(outstandingClass))
.where(OutstandingEntry.ENTITY_ID_PROPERTY.eq(id)).orderBy(Order.asc(OutstandingEntry.CREATED_AT_PROPERTY))); .where(OutstandingEntry.ENTITY_ID_PROPERTY.eq(id)).orderBy(Order.asc(OutstandingEntry.CREATED_AT_PROPERTY)));
try { try {

@ -0,0 +1,39 @@
package com.todoroo.astrid.actfm.sync.messages;
import java.util.HashSet;
import java.util.Set;
import com.todoroo.astrid.dao.TaskListMetadataDao;
import com.todoroo.astrid.dao.TaskListMetadataOutstandingDao;
import com.todoroo.astrid.data.TaskListMetadata;
import com.todoroo.astrid.data.TaskListMetadataOutstanding;
public class TaskListMetadataChangesHappened extends ChangesHappened<TaskListMetadata, TaskListMetadataOutstanding> {
public TaskListMetadataChangesHappened(long id, Class<TaskListMetadata> modelClass, TaskListMetadataDao modelDao, TaskListMetadataOutstandingDao outstandingDao) {
super(id, modelClass, modelDao, outstandingDao);
}
@Override
protected void populateChanges() {
super.populateChanges();
// Collapses/removes redundant task list orders from the list--only send the most recent ordering
Set<Long> removedChanges = new HashSet<Long>();
boolean foundOrderChange = false;
for (int i = changes.size() - 1; i >= 0; i--) {
TaskListMetadataOutstanding oe = changes.get(i);
if (TaskListMetadata.TASK_IDS.name.equals(oe.getValue(TaskListMetadataOutstanding.COLUMN_STRING))) {
if (foundOrderChange) {
changes.remove(i);
removedChanges.add(oe.getId());
} else {
foundOrderChange = true;
}
}
}
outstandingDao.deleteWhere(TaskListMetadataOutstanding.ID.in(removedChanges.toArray(new Long[removedChanges.size()])));
}
}
Loading…
Cancel
Save