Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MLIBZ - 2882 Make network requests async #219

Merged
merged 5 commits into from Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -51,18 +51,22 @@ public AsyncClientRequest(KinveyClientCallback<Result> callback) {
}

public void execute() {
Logger.INFO("Calling AsyncClientRequest#execute");
Client.sharedInstance().getKinveyHandlerThread().postTask(this);
}

@Override
public void run() {
Logger.INFO("Calling AsyncClientRequest#run");
Result result = null;
if(callback == null){
return;
}
try{
if (!hasCancelled()){
Logger.INFO("Start executeAsync");
result = executeAsync();
Logger.INFO("Finish executeAsync");
}
}catch(Throwable e){
// e.printStackTrace();
Expand All @@ -76,10 +80,13 @@ public void run() {
}
// KinveyCallbackHandler kinveyCallbackHandler = new KinveyCallbackHandler();
if (hasCancelled()){
Logger.INFO("Calling kinveyCallbackHandler.onCancel");
kinveyCallbackHandler.onCancel(((KinveyCancellableCallback) callback));
}else if(error != null){
Logger.INFO("Calling kinveyCallbackHandler.onFailure");
kinveyCallbackHandler.onFailure(error, callback);
}else{
Logger.INFO("Calling kinveyCallbackHandler.onResult");
kinveyCallbackHandler.onResult(result, callback);
}
}
Expand Down
Expand Up @@ -514,6 +514,7 @@ public void save(@NonNull T entity, @NonNull KinveyClientCallback<T> callback)
Preconditions.checkNotNull(client, "client must not be null");
Preconditions.checkArgument(client.isInitialize(), "client must be initialized.");
Preconditions.checkNotNull(entity, "Entity cannot be null.");
Logger.INFO("Calling DataStore#save(object)");
new SaveRequest(entity, callback).execute();
}

Expand Down Expand Up @@ -544,6 +545,7 @@ public void save(@NonNull List<T> entities, @NonNull KinveyClientCallback<List<T
Preconditions.checkNotNull(client, "client must not be null");
Preconditions.checkArgument(client.isInitialize(), "client must be initialized.");
Preconditions.checkNotNull(entities, "Entity cannot be null.");
Logger.INFO("Calling DataStore#save(listObjects)");
new SaveListRequest(entities, callback).execute();
}

Expand Down Expand Up @@ -1166,6 +1168,7 @@ public SaveRequest(T entity, KinveyClientCallback<T> callback) {

@Override
protected T executeAsync() throws IOException {
Logger.INFO("Calling SaveRequest#executeAsync()");
return (DataStore.super.save(entity));
}
}
Expand All @@ -1180,6 +1183,7 @@ private class SaveListRequest extends AsyncClientRequest<List<T>> {

@Override
protected List<T> executeAsync() throws IOException {
Logger.INFO("Calling SaveListRequest#executeAsync()");
return (DataStore.super.save(entities));
}
}
Expand Down
13 changes: 12 additions & 1 deletion java-api-core/src/com/kinvey/java/AbstractClient.java
Expand Up @@ -74,6 +74,8 @@ public abstract class AbstractClient<T extends BaseUser> extends AbstractKinveyJ
*/
public static final String DEFAULT_MIC_API_VERSION = "3";

public static final int DEFAULT_NUMBER_OF_THREADS_FOR_DATASTORE_SAVE_OF_LIST = 1;

private CredentialStore store;

/** used to synchronized access to the local api wrappers **/
Expand Down Expand Up @@ -105,6 +107,7 @@ public abstract class AbstractClient<T extends BaseUser> extends AbstractKinveyJ

private String MICApiVersion;
private int requestTimeout;
private int numberThreadsForDataStoreSaveList = DEFAULT_NUMBER_OF_THREADS_FOR_DATASTORE_SAVE_OF_LIST;

public void setMICApiVersion(String version){
if (!version.startsWith("v")){
Expand Down Expand Up @@ -139,7 +142,15 @@ public void setClientAppVersion(int major, int minor, int revision){
public String getClientAppVersion(){
return this.clientAppVersion;
}


public int getNumberThreadsForDataStoreSaveList() {
return numberThreadsForDataStoreSaveList;
}

public void setNumberThreadsForDataStoreSaveList(int numberThreadsForDataStoreSaveList) {
this.numberThreadsForDataStoreSaveList = numberThreadsForDataStoreSaveList;
}

public void setCustomRequestProperties(GenericJson customheaders){
this.customRequestProperties = customheaders;
}
Expand Down
Expand Up @@ -19,6 +19,7 @@
import com.google.api.client.json.GenericJson;
import com.google.api.client.util.ClassInfo;
import com.google.api.client.util.FieldInfo;
import com.kinvey.java.Logger;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
Expand All @@ -41,7 +42,7 @@ public interface ReferenceListener{

public static <T extends GenericJson> T processReferences(T gson, final ReferenceListener listener) throws IllegalAccessException, InstantiationException {


Logger.INFO("Start ReferenceHelper.processReferences(T gson, final ReferenceListener listener)");
for (Field f : gson.getClass().getDeclaredFields()){
//find field info
if (f.isAnnotationPresent(KinveyReference.class)){
Expand Down Expand Up @@ -84,6 +85,7 @@ public static <T extends GenericJson> T processReferences(T gson, final Referenc
}
}

Logger.INFO("Finish ReferenceHelper.processReferences(T gson, final ReferenceListener listener) and return gson");
return gson;
}
}
Expand Up @@ -333,6 +333,7 @@ HttpResponse executeUnparsed(boolean upload) throws IOException {
}

response = request.execute();
Logger.INFO("Getting response for network request");

lastResponseCode = response.getStatusCode();
lastResponseMessage = response.getStatusMessage();
Expand All @@ -345,6 +346,7 @@ HttpResponse executeUnparsed(boolean upload) throws IOException {
//process refresh token needed
if (response.getStatusCode() == 401 && !hasRetryed) {
//get the refresh token
Logger.INFO("get the refresh token");
Credential cred = client.getStore().load(client.getActiveUser().getId());
String refreshToken = null;

Expand Down Expand Up @@ -386,6 +388,7 @@ HttpResponse executeUnparsed(boolean upload) throws IOException {
throw newExceptionOnError(response);
}

Logger.INFO("Return response for network request");
return response;
}

Expand All @@ -405,9 +408,11 @@ protected IOException newExceptionOnError(HttpResponse response) {
* @throws IOException
*/
public T execute() throws IOException {
Logger.INFO("Start execute for network request");
HttpResponse response = executeUnparsed();

if (overrideRedirect){
Logger.INFO("overrideRedirect == true");
return onRedirect(response.getHeaders().getLocation());
}

Expand Down
19 changes: 18 additions & 1 deletion java-api-core/src/com/kinvey/java/network/NetworkManager.java
Expand Up @@ -24,6 +24,7 @@
import com.google.gson.Gson;
import com.kinvey.java.AbstractClient;
import com.kinvey.java.Constants;
import com.kinvey.java.Logger;
import com.kinvey.java.Query;
import com.kinvey.java.annotations.ReferenceHelper;
import com.kinvey.java.cache.ICache;
Expand Down Expand Up @@ -422,6 +423,7 @@ public GetCount getCountBlocking() throws IOException {
*/
public Save saveBlocking(T entity) throws IOException {

Logger.INFO("Start saveBlocking for object");
Save save;
String sourceID;

Expand All @@ -430,21 +432,28 @@ public Save saveBlocking(T entity) throws IOException {

//prepare entity relation data saving
try {
Logger.INFO("Start prepare entity relation data saving");
ReferenceHelper.processReferences(entity, new ReferenceHelper.ReferenceListener() {
@Override
public String onUnsavedReferenceFound(String collection, GenericJson object) {
Logger.INFO("Calling onUnsavedReferenceFound(String, GenericJson)");
if (object.containsKey("_id")){
Logger.INFO("return object.get(_id).toString() for onUnsavedReferenceFound(String, GenericJson)");
return object.get("_id").toString();
}

NetworkManager<GenericJson> manager = new NetworkManager<GenericJson>(collection, GenericJson.class, client);
try {
Logger.INFO("Start recursive call for manager.saveBlocking(object).execute() inside saveBlocking");
GenericJson saved = manager.saveBlocking(object).execute();
Logger.INFO("return saved.get(ID_FIELD_NAME).toString() for onUnsavedReferenceFound(String, GenericJson)");
return saved.get(ID_FIELD_NAME).toString();
} catch (IOException e) {
Logger.ERROR("Catch exception for recursive call for manager.saveBlocking(object).execute()");
e.printStackTrace();
}

Logger.INFO("return null for onUnsavedReferenceFound(String, GenericJson)");
return null;
}
});
Expand All @@ -456,18 +465,25 @@ public String onUnsavedReferenceFound(String collection, GenericJson object) {

boolean bRealmGeneratedId = isTempId(entity);

Logger.INFO("Start choosing PUT or POST request");
if (sourceID != null && !bRealmGeneratedId) {
Logger.INFO("Start for preparing new Save(entity, myClass, sourceID, SaveMode.PUT)");
save = new Save(entity, myClass, sourceID, SaveMode.PUT);
Logger.INFO("Finish for preparing new Save(entity, myClass, sourceID, SaveMode.PUT)");
} else {
Logger.INFO("Start for preparing new Save(entity, myClass, sourceID, SaveMode.POST)");
save = new Save(entity, myClass, SaveMode.POST);
Logger.INFO("Finish for preparing new Save(entity, myClass, SaveMode.POST)");
}

client.initializeRequest(save);

Logger.INFO("Finish for initializing request with save object");
Logger.INFO("Return save object");
return save;
}

public boolean isTempId(T item) {
Logger.INFO("Start checking for isTempId(entity)");
boolean isTempId = false;
if (item.get(Constants._ID) != null) {
try {
Expand All @@ -476,6 +492,7 @@ public boolean isTempId(T item) {
// issue with the regex, so do nothing because we default to false
}
}
Logger.INFO("Finish checking for isTempId(entity)");
return isTempId;
}

Expand Down
3 changes: 3 additions & 0 deletions java-api-core/src/com/kinvey/java/store/BaseDataStore.java
Expand Up @@ -22,6 +22,7 @@
import com.kinvey.java.AbstractClient;
import com.kinvey.java.Constants;
import com.kinvey.java.KinveyException;
import com.kinvey.java.Logger;
import com.kinvey.java.Query;
import com.kinvey.java.cache.ICache;
import com.kinvey.java.cache.KinveyCachedClientCallback;
Expand Down Expand Up @@ -335,6 +336,7 @@ public List<T> save (@Nonnull Iterable<T> objects) throws IOException {
Preconditions.checkNotNull(client, "client must not be null.");
Preconditions.checkArgument(client.isInitialize(), "client must be initialized.");
Preconditions.checkNotNull(objects, "objects must not be null.");
Logger.INFO("Calling BaseDataStore#save(listObjects)");
return new SaveListRequest<T>(cache, networkManager, this.storeType.writePolicy, objects, client.getSyncManager()).execute();
}

Expand All @@ -350,6 +352,7 @@ public T save (@Nonnull T object) throws IOException {
Preconditions.checkNotNull(client, "client must not be null.");
Preconditions.checkArgument(client.isInitialize(), "client must be initialized.");
Preconditions.checkNotNull(object, "object must not be null.");
Logger.INFO("Calling BaseDataStore#save(object)");
return new SaveRequest<T>(cache, networkManager, this.storeType.writePolicy, object, client.getSyncManager()).execute();
}

Expand Down
Expand Up @@ -17,7 +17,10 @@
package com.kinvey.java.store.requests.data.save;

import com.google.api.client.json.GenericJson;
import com.kinvey.java.AbstractClient;
import com.kinvey.java.Constants;
import com.kinvey.java.KinveyException;
import com.kinvey.java.Logger;
import com.kinvey.java.cache.ICache;
import com.kinvey.java.network.NetworkManager;
import com.kinvey.java.store.WritePolicy;
Expand All @@ -27,9 +30,15 @@
import com.kinvey.java.sync.dto.SyncRequest;

import java.io.IOException;
import java.security.AccessControlException;
import java.util.List;

import java.util.ArrayList;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
* Created by Prots on 2/5/16.
Expand Down Expand Up @@ -85,16 +94,54 @@ public List<T> execute() throws IOException {
}
break;
case FORCE_NETWORK:
for (T obj : objects){
SaveRequest<T> save = new SaveRequest<>(
cache, networkManager , writePolicy, obj, syncManager);
ret.add(save.execute());
Logger.INFO("Start saving entities");
ExecutorService executor;
List<FutureTask<T>> tasks;
FutureTask<T> ft;
List<T> items = (List<T>) objects;
executor = Executors.newFixedThreadPool(networkManager.getClient().getNumberThreadsForDataStoreSaveList());
tasks = new ArrayList<>();
for (T obj : objects) {
try {
SaveRequest<T> save = new SaveRequest<>(
cache, networkManager, writePolicy, obj, syncManager);
ft = new FutureTask<T>(new CallableAsyncSaveRequestHelper(save));
tasks.add(ft);
executor.execute(ft);
} catch (AccessControlException | KinveyException e) {
e.printStackTrace();
} catch (Exception e) {
throw e;
}
}
for (FutureTask<T> task : tasks) {
try {
ret.add(task.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
executor.shutdown();
Logger.INFO("Finish saving entities");
break;
}
return ret;
}

private class CallableAsyncSaveRequestHelper implements Callable {

SaveRequest<T> save;

CallableAsyncSaveRequestHelper(SaveRequest<T> save) {
this.save = save;
}

@Override
public T call() throws Exception {
return save.execute();
}
}

@Override
public void cancel() {
//TODO: put async and track cancel
Expand Down
Expand Up @@ -18,6 +18,7 @@

import com.google.api.client.json.GenericJson;
import com.kinvey.java.Constants;
import com.kinvey.java.Logger;
import com.kinvey.java.cache.ICache;
import com.kinvey.java.network.NetworkManager;
import com.kinvey.java.store.WritePolicy;
Expand Down Expand Up @@ -94,7 +95,9 @@ public T execute() throws IOException {
cache.save(ret);
break;
case FORCE_NETWORK:
Logger.INFO("Start saving entity");
ret = networkManager.saveBlocking(object).execute();
Logger.INFO("Finish saving entity");
break;
}
return ret;
Expand Down