Started implementing ability to report errors to sync callbacks to customize behavior

pull/14/head
Sam Bosley 11 years ago
parent 2b70c8f755
commit c5460da0e9

@ -129,13 +129,6 @@ public class GCMIntentService extends GCMBaseIntentService {
/** Handle web task or list changed */
protected void handleWebUpdate(Intent intent) {
Runnable refreshCallback = new Runnable() {
@Override
public void run() {
Intent broadcastIntent = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH);
ContextManager.getContext().sendBroadcast(broadcastIntent, AstridApiConstants.PERMISSION_READ);
}
};
if(intent.hasExtra("tag_id")) {
String uuid = intent.getStringExtra("tag_id");
TodorooCursor<TagData> cursor = tagDataService.query(
@ -152,7 +145,7 @@ public class GCMIntentService extends GCMBaseIntentService {
} finally {
cursor.close();
}
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<TagData>(TagData.class, uuid, pushedAt), refreshCallback);
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<TagData>(TagData.class, uuid, pushedAt), ActFmSyncThread.DEFAULT_REFRESH_RUNNABLE);
} else if(intent.hasExtra("task_id")) {
String uuid = intent.getStringExtra("task_id");
TodorooCursor<Task> cursor = taskService.query(
@ -166,7 +159,7 @@ public class GCMIntentService extends GCMBaseIntentService {
task.readFromCursor(cursor);
pushedAt = task.getValue(Task.PUSHED_AT);
}
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<Task>(Task.class, uuid, pushedAt), refreshCallback);
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<Task>(Task.class, uuid, pushedAt), ActFmSyncThread.DEFAULT_REFRESH_RUNNABLE);
} finally {
cursor.close();
}

@ -5,6 +5,8 @@
*/
package com.todoroo.astrid.actfm;
import java.util.List;
import org.json.JSONObject;
import android.app.Activity;
@ -41,6 +43,7 @@ import com.todoroo.astrid.actfm.ActFmCameraModule.CameraResultCallback;
import com.todoroo.astrid.actfm.ActFmCameraModule.ClearImageCallback;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncService;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.activity.AstridActivity;
import com.todoroo.astrid.activity.TaskListActivity;
import com.todoroo.astrid.adapter.UpdateAdapter;
@ -112,7 +115,7 @@ public abstract class CommentsFragment extends SherlockListFragment {
protected abstract String commentAddStatistic();
protected abstract void performFetch(boolean manual, Runnable done);
protected abstract void performFetch(boolean manual, SyncMessageCallback done);
@Override
public void onActivityCreated(Bundle savedInstanceState) {
@ -268,9 +271,9 @@ public abstract class CommentsFragment extends SherlockListFragment {
protected void refreshActivity(boolean manual) {
if (actFmPreferenceService.isLoggedIn()) {
Runnable doneRunnable = new Runnable() {
SyncMessageCallback doneRunnable = new SyncMessageCallback() {
@Override
public void run() {
public void runOnSuccess() {
synchronized (this) {
Activity activity = getActivity();
if (activity != null)
@ -282,11 +285,16 @@ public abstract class CommentsFragment extends SherlockListFragment {
});
}
}
@Override
public void runOnErrors(List<JSONObject> errors) {
// TODO: Implement this
}
};
if (hasModel()) {
performFetch(manual, doneRunnable);
} else {
doneRunnable.run();
doneRunnable.runOnSuccess();
}
}
}

@ -20,6 +20,7 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.actfm.sync.messages.BriefMe;
import com.todoroo.astrid.actfm.sync.messages.FetchHistory;
import com.todoroo.astrid.actfm.sync.messages.NameMaps;
@ -126,7 +127,7 @@ public class TagCommentsFragment extends CommentsFragment {
}
@Override
protected void performFetch(boolean manual, Runnable done) {
protected void performFetch(boolean manual, SyncMessageCallback done) {
if (tagData != null) {
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<UserActivity>(UserActivity.class, null, tagData.getValue(TagData.USER_ACTIVITIES_PUSHED_AT), BriefMe.TAG_ID_KEY, tagData.getUuid()), done);
new FetchHistory<TagData>(tagDataDao, TagData.HISTORY_FETCH_DATE, NameMaps.TABLE_ID_TAGS, tagData.getUuid(), null, tagData.getValue(TagData.HISTORY_FETCH_DATE), true, done).execute();

@ -5,6 +5,7 @@
*/
package com.todoroo.astrid.actfm;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.json.JSONArray;
@ -46,6 +47,7 @@ import com.todoroo.andlib.utility.Preferences;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncService;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.actfm.sync.messages.BriefMe;
import com.todoroo.astrid.actfm.sync.messages.FetchHistory;
import com.todoroo.astrid.actfm.sync.messages.NameMaps;
@ -336,9 +338,9 @@ public class TagViewFragment extends TaskListFragment {
if (actFmPreferenceService.isLoggedIn() && tagData != null && !RemoteModel.isUuidEmpty(tagData.getUuid())) {
((TextView)taskListView.findViewById(android.R.id.empty)).setText(R.string.DLG_loading);
Runnable callback = new Runnable() {
SyncMessageCallback callback = new SyncMessageCallback() {
@Override
public void run() {
public void runOnSuccess() {
synchronized(this) {
Activity activity = getActivity();
if (activity != null) {
@ -357,6 +359,10 @@ public class TagViewFragment extends TaskListFragment {
}
}
}
@Override
public void runOnErrors(List<JSONObject> errors) {
// TODO: Implement this
}
};
ActFmSyncThread.getInstance().repopulateQueueFromOutstandingTables();

@ -9,6 +9,7 @@ import com.timsu.astrid.R;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.actfm.sync.messages.BriefMe;
import com.todoroo.astrid.actfm.sync.messages.FetchHistory;
import com.todoroo.astrid.actfm.sync.messages.NameMaps;
@ -79,7 +80,7 @@ public class TaskCommentsFragment extends CommentsFragment {
}
@Override
protected void performFetch(boolean manual, Runnable done) {
protected void performFetch(boolean manual, SyncMessageCallback done) {
if (task != null) {
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<UserActivity>(UserActivity.class, null, task.getValue(Task.USER_ACTIVITIES_PUSHED_AT), BriefMe.TASK_ID_KEY, task.getUuid()), done);
new FetchHistory<Task>(taskDao, Task.HISTORY_FETCH_DATE, NameMaps.TABLE_ID_TASKS, task.getUuid(), task.getValue(Task.TITLE), task.getValue(Task.HISTORY_FETCH_DATE), false, done).execute();

@ -1,6 +1,7 @@
package com.todoroo.astrid.actfm.sync;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -71,7 +72,7 @@ public class ActFmSyncThread {
private static final String ERROR_TAG = "actfm-sync-thread"; //$NON-NLS-1$
private final List<ClientToServerMessage<?>> pendingMessages;
private final Map<ClientToServerMessage<?>, Runnable> pendingCallbacks;
private final Map<ClientToServerMessage<?>, SyncMessageCallback> pendingCallbacks;
private final Object monitor;
private Thread thread;
@ -117,6 +118,11 @@ public class ActFmSyncThread {
private ProgressBar progressBar = null;
public static interface SyncMessageCallback {
public void runOnSuccess();
public void runOnErrors(List<JSONObject> errors);
}
public static enum ModelType {
TYPE_TASK,
TYPE_TAG,
@ -165,7 +171,7 @@ public class ActFmSyncThread {
private ActFmSyncThread(List<ClientToServerMessage<?>> messageQueue, Object syncMonitor) {
DependencyInjectionService.getInstance().inject(this);
this.pendingMessages = messageQueue;
this.pendingCallbacks = Collections.synchronizedMap(new HashMap<ClientToServerMessage<?>, Runnable>());
this.pendingCallbacks = Collections.synchronizedMap(new HashMap<ClientToServerMessage<?>, SyncMessageCallback>());
this.monitor = syncMonitor;
this.syncMigration = Preferences.getBoolean(AstridNewSyncMigrator.PREF_SYNC_MIGRATION, false);
}
@ -202,7 +208,7 @@ public class ActFmSyncThread {
Preferences.clear(key);
}
public synchronized void enqueueMessage(ClientToServerMessage<?> message, Runnable callback) {
public synchronized void enqueueMessage(ClientToServerMessage<?> message, SyncMessageCallback callback) {
if (!RemoteModelDao.getOutstandingEntryFlag(RemoteModelDao.OUTSTANDING_ENTRY_FLAG_ENQUEUE_MESSAGES))
return;
if (!pendingMessages.contains(message)) {
@ -268,19 +274,22 @@ public class ActFmSyncThread {
}
}
public static final Runnable DEFAULT_REFRESH_RUNNABLE = new Runnable() {
public static final SyncMessageCallback DEFAULT_REFRESH_RUNNABLE = new SyncMessageCallback() {
@Override
public void run() {
public void runOnSuccess() {
Intent refresh = new Intent(AstridApiConstants.BROADCAST_EVENT_REFRESH);
ContextManager.getContext().sendBroadcast(refresh);
}
@Override
public void runOnErrors(List<JSONObject> errors) {/**/}
};
@SuppressWarnings("nls")
private void sync() {
try {
int batchSize = 4;
List<ClientToServerMessage<?>> messageBatch = new LinkedList<ClientToServerMessage<?>>();
List<ClientToServerMessage<?>> messageBatch = new ArrayList<ClientToServerMessage<?>>();
while(true) {
synchronized(monitor) {
while ((pendingMessages.isEmpty() && !timeForBackgroundSync()) || !actFmPreferenceService.isLoggedIn() || !syncMigration) {
@ -316,14 +325,18 @@ public class ActFmSyncThread {
if (!messageBatch.isEmpty() && checkForToken()) {
JSONArray payload = new JSONArray();
MultipartEntity entity = new MultipartEntity();
for (ClientToServerMessage<?> message : messageBatch) {
for (int i = 0; i < messageBatch.size(); i++) {
ClientToServerMessage<?> message = messageBatch.get(i);
JSONObject serialized = message.serializeToJSON(entity);
if (serialized != null) {
payload.put(serialized);
syncLog("Sending: " + serialized);
} else {
messageBatch.remove(i);
i--;
incrementProgress(); // Don't let failed serialization mess up progress bar
}
}
if (payload.length() == 0) {
@ -333,6 +346,7 @@ public class ActFmSyncThread {
payload.put(getClientVersion());
JSONArray errors = null;
try {
JSONObject response = actFmInvoker.postSync(payload, entity, token);
// process responses
@ -352,7 +366,7 @@ public class ActFmSyncThread {
}
}
}
JSONArray errors = response.optJSONArray("errors");
errors = response.optJSONArray("errors");
boolean errorsExist = (errors != null && errors.length() > 0);
replayOutstandingChanges(errorsExist);
setWidgetSuppression(false);
@ -367,13 +381,15 @@ public class ActFmSyncThread {
batchSize = Math.max(batchSize / 2, 1);
}
Set<Runnable> callbacksExecutedThisLoop = new HashSet<Runnable>();
for (ClientToServerMessage<?> message : messageBatch) {
Set<SyncMessageCallback> callbacksExecutedThisLoop = new HashSet<SyncMessageCallback>();
Map<Integer, List<JSONObject>> errorMap = buildErrorMap(errors);
for (int i = 0; i < messageBatch.size(); i++) {
ClientToServerMessage<?> message = messageBatch.get(i);
incrementProgress();
try {
Runnable r = pendingCallbacks.remove(message);
SyncMessageCallback r = pendingCallbacks.remove(message);
if (r != null && !callbacksExecutedThisLoop.contains(r)) {
r.run();
r.runOnSuccess();
callbacksExecutedThisLoop.add(r);
}
} catch (Exception e) {
@ -394,6 +410,26 @@ public class ActFmSyncThread {
}
private Map<Integer, List<JSONObject>> buildErrorMap(JSONArray errors) {
Map<Integer, List<JSONObject>> result = new HashMap<Integer, List<JSONObject>>();
if (errors != null) {
for (int i = 0; i < errors.length(); i++) {
JSONObject error = errors.optJSONObject(i);
if (error != null && error.has("index")) { //$NON-NLS-1$
int index = error.optInt("index"); //$NON-NLS-1$
List<JSONObject> errorList = result.get(index);
if (errorList == null) {
errorList = new LinkedList<JSONObject>();
result.put(index, errorList);
}
error.remove("index"); //$NON-NLS-1$
errorList.add(error);
}
}
}
return result;
}
// Reapplies changes still in the outstanding tables to the local database
// Called after a batch has finished processing
private void replayOutstandingChanges(boolean afterErrors) {

@ -15,6 +15,7 @@ import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.astrid.actfm.sync.ActFmInvoker;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.dao.HistoryDao;
import com.todoroo.astrid.dao.RemoteModelDao;
import com.todoroo.astrid.dao.UserDao;
@ -33,7 +34,7 @@ public class FetchHistory<TYPE extends RemoteModel> {
private final String taskTitle;
private final long modifiedAfter;
private final boolean includeTaskHistory;
private final Runnable done;
private final SyncMessageCallback done;
@Autowired
private ActFmInvoker actFmInvoker;
@ -48,7 +49,7 @@ public class FetchHistory<TYPE extends RemoteModel> {
private ActFmPreferenceService actFmPreferenceService;
public FetchHistory(RemoteModelDao<TYPE> dao, LongProperty historyTimeProperty,
String table, String uuid, String taskTitle, long modifiedAfter, boolean includeTaskHistory, Runnable done) {
String table, String uuid, String taskTitle, long modifiedAfter, boolean includeTaskHistory, SyncMessageCallback done) {
DependencyInjectionService.getInstance().inject(this);
this.dao = dao;
this.historyTimeProperty = historyTimeProperty;
@ -167,7 +168,7 @@ public class FetchHistory<TYPE extends RemoteModel> {
}
if (done != null)
done.run();
done.runOnSuccess();
}
}).start();
}

@ -54,6 +54,7 @@ import com.todoroo.astrid.actfm.ActFmCameraModule.ClearImageCallback;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncService;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.actfm.sync.messages.BriefMe;
import com.todoroo.astrid.actfm.sync.messages.FetchHistory;
import com.todoroo.astrid.actfm.sync.messages.NameMaps;
@ -408,9 +409,9 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
return;
}
Runnable callback = new Runnable() {
SyncMessageCallback callback = new SyncMessageCallback() {
@Override
public void run() {
public void runOnSuccess() {
synchronized(this) {
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@ -429,6 +430,10 @@ public class EditNoteActivity extends LinearLayout implements TimerActionListene
}
}
}
@Override
public void runOnErrors(List<JSONObject> errors) {
// TODO: Implement this
}
};
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<UserActivity>(UserActivity.class, null, task.getValue(Task.USER_ACTIVITIES_PUSHED_AT), BriefMe.TASK_ID_KEY, task.getUuid()), callback);

@ -5,6 +5,10 @@
*/
package com.todoroo.astrid.people;
import java.util.List;
import org.json.JSONObject;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
@ -20,6 +24,7 @@ import com.todoroo.andlib.utility.DateUtilities;
import com.todoroo.astrid.actfm.sync.ActFmPreferenceService;
import com.todoroo.astrid.actfm.sync.ActFmSyncService;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread;
import com.todoroo.astrid.actfm.sync.ActFmSyncThread.SyncMessageCallback;
import com.todoroo.astrid.actfm.sync.messages.BriefMe;
import com.todoroo.astrid.activity.TaskListFragment;
import com.todoroo.astrid.dao.UserDao;
@ -202,9 +207,9 @@ public class PersonViewFragment extends TaskListFragment {
private void refreshData() {
if (user != null) {
emptyView.setText(R.string.DLG_loading);
Runnable callback = new Runnable() {
SyncMessageCallback callback = new SyncMessageCallback() {
@Override
public void run() {
public void runOnSuccess() {
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(new Runnable() {
@ -216,6 +221,10 @@ public class PersonViewFragment extends TaskListFragment {
});
}
}
@Override
public void runOnErrors(List<JSONObject> errors) {
// TODO: Implement this
}
};
ActFmSyncThread.getInstance().enqueueMessage(new BriefMe<User>(User.class, user.getValue(User.UUID), user.getValue(User.PUSHED_AT)), callback);
}

Loading…
Cancel
Save