More producteev bug fixes. Now abule to synchronize sucessfully, except sometimes for 'wrong api-key' flakiness

pull/14/head
Tim Su 14 years ago
parent aa6f01e730
commit ea71ca001b

@ -15,8 +15,8 @@ import android.content.Context;
import android.widget.Toast;
import com.timsu.astrid.R;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.LongProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
@ -260,6 +260,7 @@ public abstract class SyncProvider<TYPE extends TaskContainer> {
} else {
push(local, null);
}
write(local);
} catch (Exception e) {
handleException("sync-local-updated", e, false); //$NON-NLS-1$
}

@ -88,11 +88,11 @@ public class ProducteevInvoker {
* @param status (optional) (1 = UNDONE, 2 = DONE)
* @param star (optional) (0 to 5 stars)
*
* @return array tasks/view
* @return task
*/
public JSONArray tasksCreate(String title, Long idResponsible, Long idDashboard,
public JSONObject tasksCreate(String title, Long idResponsible, Long idDashboard,
String deadline, Integer reminder, Integer status, Integer star) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/create.json",
return invokeGet("tasks/create.json",
"token", token,
"title", title,
"id_responsible", idResponsible,
@ -100,7 +100,7 @@ public class ProducteevInvoker {
"deadline", deadline,
"reminder", reminder,
"status", status,
"star", star), "tasks");
"star", star);
}
/**
@ -125,10 +125,10 @@ public class ProducteevInvoker {
*
* @return array tasks/view
*/
public JSONArray tasksView(Long idTask) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/view.json",
public JSONObject tasksView(Long idTask) throws ApiServiceException, IOException {
return invokeGet("tasks/view.json",
"token", token,
"id_task", idTask), "tasks");
"id_task", idTask);
}
/**
@ -139,11 +139,11 @@ public class ProducteevInvoker {
*
* @return array tasks/view
*/
public JSONArray tasksSetTitle(long idTask, String title) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/set_title.json",
public JSONObject tasksSetTitle(long idTask, String title) throws ApiServiceException, IOException {
return invokeGet("tasks/set_title.json",
"token", token,
"id_task", idTask,
"title", title), "tasks");
"title", title);
}
/**
@ -154,11 +154,11 @@ public class ProducteevInvoker {
*
* @return array tasks/view
*/
public JSONArray tasksSetStatus(long idTask, int status) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/set_star.json",
public JSONObject tasksSetStatus(long idTask, int status) throws ApiServiceException, IOException {
return invokeGet("tasks/set_star.json",
"token", token,
"id_task", idTask,
"status", status), "tasks");
"status", status);
}
/**
@ -169,11 +169,11 @@ public class ProducteevInvoker {
*
* @return array tasks/view
*/
public JSONArray tasksSetStar(long idTask, int star) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/set_star.json",
public JSONObject tasksSetStar(long idTask, int star) throws ApiServiceException, IOException {
return invokeGet("tasks/set_star.json",
"token", token,
"id_task", idTask,
"star", star), "tasks");
"star", star);
}
/**
@ -184,11 +184,11 @@ public class ProducteevInvoker {
*
* @return array tasks/view
*/
public JSONArray tasksSetDeadline(long idTask, String deadline) throws ApiServiceException, IOException {
return getResponse(invokeGet("tasks/set_deadline.json",
public JSONObject tasksSetDeadline(long idTask, String deadline) throws ApiServiceException, IOException {
return invokeGet("tasks/set_deadline.json",
"token", token,
"id_task", idTask,
"deadline", deadline), "tasks");
"deadline", deadline);
}
/**
@ -225,7 +225,7 @@ public class ProducteevInvoker {
*
* @return array: tasks/view
*/
public JSONArray tasksSetLabels(long idTask, long... idLabels) throws ApiServiceException, IOException {
public JSONObject tasksSetLabels(long idTask, long... idLabels) throws ApiServiceException, IOException {
Object[] params = new Object[idLabels.length * 2 + 2];
params[0] = "token";
params[1] = token;
@ -234,7 +234,7 @@ public class ProducteevInvoker {
params[i*2 + 3] = idLabels[i];
}
return getResponse(invokeGet("tasks/set_label.json", params), "tasks");
return invokeGet("tasks/set_label.json", params);
}
/**
@ -245,7 +245,7 @@ public class ProducteevInvoker {
*
* @return array: tasks/view
*/
public JSONArray tasksUnsetLabels(long idTask, long... idLabels) throws ApiServiceException, IOException {
public JSONObject tasksUnsetLabels(long idTask, long... idLabels) throws ApiServiceException, IOException {
Object[] params = new Object[idLabels.length * 2 + 2];
params[0] = "token";
params[1] = token;
@ -254,7 +254,7 @@ public class ProducteevInvoker {
params[i*2 + 3] = idLabels[i];
}
return getResponse(invokeGet("tasks/unset_label.json", params), "tasks");
return invokeGet("tasks/unset_label.json", params);
}
/**
@ -337,6 +337,8 @@ public class ProducteevInvoker {
try {
String request = createFetchUrl(method, getParameters);
String response = restClient.get(request);
if(response.startsWith("DEBUG MESSAGE"))
throw new ApiServiceException(response);
return new JSONObject(response);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
@ -374,6 +376,7 @@ public class ProducteevInvoker {
}
sigBuilder.append(apiSecret);
System.err.println("sigbuilder " + sigBuilder);
byte[] digest = MessageDigest.getInstance("MD5").digest(sigBuilder.toString().getBytes("UTF-8"));
String signature = new BigInteger(1, digest).toString(16);
requestBuilder.append("api_sig").append('=').append(signature);

@ -88,14 +88,16 @@ public class ProducteevRestClient implements RestClient {
int statusCode = response.getStatusLine().getStatusCode();
if(statusCode != HTTP_OK) {
ApiServiceException error;
try {
JSONObject error = new JSONObject(body);
String errorMessage = error.getJSONObject("error").getString("message"); //$NON-NLS-1$ //$NON-NLS-2$
throw new ApiServiceException(errorMessage);
JSONObject errorObject = new JSONObject(body).getJSONObject("error"); //$NON-NLS-1$
String errorMessage = errorObject.getString("message"); //$NON-NLS-1$
error= new ApiServiceException(errorMessage);
} catch (Exception e) {
throw new ApiServiceException(response.getStatusLine() +
error = new ApiServiceException(response.getStatusLine() +
"\n" + body); //$NON-NLS-1$
}
throw error;
}

@ -80,7 +80,7 @@ public final class ProducteevDataService {
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).where(Criterion.and(
Criterion.not(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY), ProducteevTask.ID.gt(0))))),
TaskCriteria.isActive())));
TaskCriteria.isActive())).groupBy(Task.ID));
}
/**
@ -95,7 +95,7 @@ public final class ProducteevDataService {
return
taskDao.query(Query.select(properties).join(ProducteevDataService.METADATA_JOIN).
where(Criterion.and(MetadataCriteria.withKey(ProducteevTask.METADATA_KEY),
Task.MODIFICATION_DATE.gt(lastSyncDate))));
Task.MODIFICATION_DATE.gt(lastSyncDate))).groupBy(Task.ID));
}
/**
@ -123,7 +123,6 @@ public final class ProducteevDataService {
* @param task
*/
public void saveTaskAndMetadata(ProducteevTaskContainer task) {
findLocalMatch(task);
taskDao.save(task.task, true);
metadataDao.deleteWhere(Criterion.and(MetadataCriteria.byTask(task.task.getId()),
@ -131,6 +130,7 @@ public final class ProducteevDataService {
MetadataCriteria.withKey(ProducteevNote.METADATA_KEY),
MetadataCriteria.withKey(TagService.KEY))));
task.metadata.add(task.pdvTask);
task.pdvTask.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
for(Metadata metadata : task.metadata) {
metadata.setValue(Metadata.TASK, task.task.getId());
metadataDao.createNew(metadata);

@ -80,6 +80,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
preferences.setToken(null);
preferences.clearLastSyncDate();
dataService = ProducteevDataService.getInstance();
dataService.clearMetadata();
}
@ -186,8 +187,10 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
readLabels(labels);
// read all tasks
JSONArray tasks = invoker.tasksShowList(defaultDashboard,
preferences.getLastServerSync());
String lastServerSync = preferences.getLastServerSync();
if(lastServerSync != null)
lastServerSync = lastServerSync.substring(0, lastServerSync.lastIndexOf(' '));
JSONArray tasks = invoker.tasksShowList(defaultDashboard, lastServerSync);
SyncData<ProducteevTaskContainer> syncData = populateSyncData(tasks);
try {
@ -238,8 +241,11 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
// read json response
ArrayList<ProducteevTaskContainer> remoteTasks = new ArrayList<ProducteevTaskContainer>(tasks.length());
for(int i = 0; i < tasks.length(); i++)
remoteTasks.add(parseRemoteTask(tasks.getJSONObject(i)));
for(int i = 0; i < tasks.length(); i++) {
ProducteevTaskContainer remote = parseRemoteTask(tasks.getJSONObject(i));
dataService.findLocalMatch(remote);
remoteTasks.add(remote);
}
return new SyncData<ProducteevTaskContainer>(remoteTasks, localCreated, localUpdated);
}
@ -251,17 +257,15 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
@Override
protected void create(ProducteevTaskContainer task) throws IOException {
Task local = task.task;
Long dashboard = null;
long dashboard = defaultDashboard;
if(task.pdvTask.containsNonNullValue(ProducteevTask.DASHBOARD_ID))
dashboard = task.pdvTask.getValue(ProducteevTask.DASHBOARD_ID);
JSONArray response = invoker.tasksCreate(local.getValue(Task.TITLE),
JSONObject response = invoker.tasksCreate(local.getValue(Task.TITLE),
null, dashboard, createDeadline(local), createReminder(local),
local.isCompleted() ? 2 : 1, createStars(local));
if(response.length() != 1)
throw new ApiServiceException("Unexpected # of tasks created: " + response.length());
ProducteevTaskContainer newRemoteTask;
try {
newRemoteTask = parseRemoteTask(response.getJSONObject(0));
newRemoteTask = parseRemoteTask(response);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
@ -275,6 +279,9 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
Task task = new Task();
ArrayList<Metadata> metadata = new ArrayList<Metadata>();
if(remoteTask.has("task"))
remoteTask = remoteTask.getJSONObject("task");
task.setValue(Task.TITLE, remoteTask.getString("title"));
task.setValue(Task.CREATION_DATE, ApiUtilities.producteevToUnixTime(remoteTask.getString("time_created"), 0));
task.setValue(Task.COMPLETION_DATE, remoteTask.getInt("status") == 2 ? DateUtilities.now() : 0);
@ -312,11 +319,9 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
if(!task.pdvTask.containsNonNullValue(ProducteevTask.ID))
throw new ApiServiceException("Tried to read an invalid task"); //$NON-NLS-1$
JSONArray tasks = invoker.tasksView(task.pdvTask.getValue(ProducteevTask.ID));
if(tasks.length() == 0)
return null;
JSONObject remote = invoker.tasksView(task.pdvTask.getValue(ProducteevTask.ID));
try {
return parseRemoteTask(tasks.getJSONObject(0));
return parseRemoteTask(remote);
} catch (JSONException e) {
throw new ApiResponseParseException(e);
}
@ -401,7 +406,7 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
}
// notes
if(shouldTransmit(local, Task.NOTES, remote)) {
if(!TextUtils.isEmpty(local.task.getValue(Task.NOTES))) {
String note = local.task.getValue(Task.NOTES);
JSONObject result = invoker.tasksNoteCreate(idTask, note);
local.metadata.add(ProducteevNote.create(result.getJSONObject("note")));
@ -478,7 +483,8 @@ public class ProducteevSyncProvider extends SyncProvider<ProducteevTaskContainer
return null;
if(!task.hasDueTime())
return ApiUtilities.unixDateToProducteev(task.getValue(Task.DUE_DATE));
return ApiUtilities.unixTimeToProducteev(task.getValue(Task.DUE_DATE));
String time = ApiUtilities.unixTimeToProducteev(task.getValue(Task.DUE_DATE));
return time.substring(0, time.lastIndexOf(' '));
}
/**

@ -19,17 +19,20 @@ public class ProducteevTaskContainer extends TaskContainer {
public Metadata pdvTask;
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata, Metadata remote) {
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata, Metadata pdvTask) {
this.task = task;
this.metadata = metadata;
this.pdvTask = remote;
if(this.pdvTask == null)
this.pdvTask = pdvTask;
if(this.pdvTask == null) {
this.pdvTask = new Metadata();
this.pdvTask.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
}
}
@SuppressWarnings("nls")
public ProducteevTaskContainer(Task task, ArrayList<Metadata> metadata, JSONObject remoteTask) {
this(task, metadata, new Metadata());
pdvTask.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
pdvTask.setValue(ProducteevTask.ID, remoteTask.optLong("id_task"));
pdvTask.setValue(ProducteevTask.DASHBOARD_ID, remoteTask.optLong("id_dashboard"));
}
@ -46,8 +49,10 @@ public class ProducteevTaskContainer extends TaskContainer {
break;
}
}
if(this.pdvTask == null)
if(this.pdvTask == null) {
this.pdvTask = new Metadata();
this.pdvTask.setValue(Metadata.KEY, ProducteevTask.METADATA_KEY);
}
}

@ -13,8 +13,8 @@ import android.content.Context;
import com.todoroo.andlib.data.GenericDao;
import com.todoroo.andlib.data.Property;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.data.Property.CountProperty;
import com.todoroo.andlib.data.TodorooCursor;
import com.todoroo.andlib.service.Autowired;
import com.todoroo.andlib.service.ContextManager;
import com.todoroo.andlib.service.DependencyInjectionService;
@ -24,8 +24,8 @@ import com.todoroo.andlib.sql.Order;
import com.todoroo.andlib.sql.Query;
import com.todoroo.andlib.utility.SoftHashMap;
import com.todoroo.astrid.dao.MetadataDao;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.MetadataDao.MetadataCriteria;
import com.todoroo.astrid.dao.TaskDao;
import com.todoroo.astrid.dao.TaskDao.TaskCriteria;
import com.todoroo.astrid.model.Metadata;
import com.todoroo.astrid.model.Task;
@ -95,7 +95,7 @@ public final class MilkDataService {
taskDao.query(Query.select(properties).join(MilkDataService.METADATA_JOIN).where(Criterion.and(
Criterion.not(Task.ID.in(Query.select(Metadata.TASK).from(Metadata.TABLE).
where(Criterion.and(MetadataCriteria.withKey(MilkTask.METADATA_KEY), MilkTask.TASK_SERIES_ID.gt(0))))),
TaskCriteria.isActive())));
TaskCriteria.isActive())).groupBy(Task.ID));
}
/**
@ -110,7 +110,7 @@ public final class MilkDataService {
return
taskDao.query(Query.select(properties).join(MilkDataService.METADATA_JOIN).
where(Criterion.and(MetadataCriteria.withKey(MilkTask.METADATA_KEY),
Task.MODIFICATION_DATE.gt(lastSyncDate))));
Task.MODIFICATION_DATE.gt(lastSyncDate))).groupBy(Task.ID));
}
/**

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -22,5 +22,7 @@
<color name="importance_2">#fffea400</color>
<color name="importance_3">#ff33a5e8</color>
<color name="importance_4">#ff808080</color>
<color name="importance_5">#ff505050</color>
<color name="importance_6">#ff202020</color>
</resources>

@ -146,6 +146,10 @@ public final class Task extends AbstractModel {
r.getColor(R.color.importance_2),
r.getColor(R.color.importance_3),
r.getColor(R.color.importance_4),
// for external services with importances > 4
r.getColor(R.color.importance_5),
r.getColor(R.color.importance_6),
};
}

@ -8,8 +8,8 @@ import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Log;
@ -21,6 +21,7 @@ import com.todoroo.andlib.service.DependencyInjectionService;
import com.todoroo.andlib.service.ExceptionService;
import com.todoroo.andlib.service.ExceptionService.TodorooUncaughtExceptionHandler;
import com.todoroo.astrid.dao.Database;
import com.todoroo.astrid.producteev.ProducteevUtilities;
import com.todoroo.astrid.rmilk.MilkUtilities;
import com.todoroo.astrid.utility.Constants;
import com.todoroo.astrid.utility.Preferences;
@ -114,6 +115,7 @@ public class StartupService {
// if sync ongoing flag was set, clear it
MilkUtilities.stopOngoing();
new ProducteevUtilities().stopOngoing();
// check for task killers
if(!Constants.OEM)

Loading…
Cancel
Save