private void ThrowExceptionIfOnlyErrors(KinveyMultiInsertResponse <T> kinveyDataStoreResponse, EnumErrorCategory errorCategory, EnumErrorCode errorCode) { if (kinveyDataStoreResponse.Entities.All(e => e == null) && kinveyDataStoreResponse.Errors.Count > 0) { throw new KinveyException(errorCategory, errorCode, kinveyDataStoreResponse.Errors[0].Errmsg); } }
private async Task <KinveyMultiInsertResponse <T> > HandleMultiInsertRequestAsync(IList <T> entities) { var response = new KinveyMultiInsertResponse <T>(); try { var multiInsertRequest = Client.NetworkFactory.BuildMultiInsertRequest <T, KinveyMultiInsertResponse <T> >(Collection, entities.ToList()); response = await multiInsertRequest.ExecuteAsync().ConfigureAwait(false); } catch (KinveyException exception) { if (exception.StatusCode == 401) { throw; } response.Entities = new List <T>(); response.Errors = new List <Error>(); for (var index = 0; index < entities.Count(); index++) { response.Entities.Add(default(T)); response.Errors.Add(new Error { Code = 0, Errmsg = exception.Message, Index = index }); } } return(response); }
/// <summary> /// Executes a multi insert request. /// </summary> /// <returns>An async task with the request result.</returns> public override async Task <KinveyMultiInsertResponse <T> > ExecuteAsync() { var kinveyDataStoreResponse = new KinveyMultiInsertResponse <T> { Entities = new List <T>(), Errors = new List <Error>() }; switch (Policy) { case WritePolicy.FORCE_LOCAL: //local cache for (var index = 0; index < entities.Count; index++) { try { var cacheSaveResult = CacheSave(entities[index]); SyncQueue.Enqueue(cacheSaveResult.Item1); kinveyDataStoreResponse.Entities.Add(cacheSaveResult.Item2); } catch (Exception ex) { kinveyDataStoreResponse.Entities.Add(default(T)); var error = new Error { Index = index, Code = 0, Errmsg = ex.Message }; kinveyDataStoreResponse.Errors.Add(error); } } ThrowExceptionIfOnlyErrors(kinveyDataStoreResponse, EnumErrorCategory.ERROR_DATASTORE_CACHE, EnumErrorCode.ERROR_DATASTORE_CACHE_MULTIPLE_SAVE); break; case WritePolicy.FORCE_NETWORK: // network kinveyDataStoreResponse = await HandleNetworkRequestAsync(entities).ConfigureAwait(false); ThrowExceptionIfOnlyErrors(kinveyDataStoreResponse, EnumErrorCategory.ERROR_BACKEND, EnumErrorCode.ERROR_JSON_RESPONSE); break; case WritePolicy.LOCAL_THEN_NETWORK: //local cache KinveyMultiInsertResponse <T> kinveyDataStoreNetworkResponse = null; var pendingWriteActions = new List <PendingWriteAction>(); for (var index = 0; index < entities.Count; index++) { try { var cacheSaveResult = CacheSave(entities[index]); pendingWriteActions.Add(cacheSaveResult.Item1); kinveyDataStoreResponse.Entities.Add(cacheSaveResult.Item2); } catch (Exception ex) { kinveyDataStoreResponse.Entities.Add(default(T)); var error = new Error { Index = index, Code = 0, Errmsg = ex.Message }; kinveyDataStoreResponse.Errors.Add(error); } } ThrowExceptionIfOnlyErrors(kinveyDataStoreResponse, EnumErrorCategory.ERROR_DATASTORE_CACHE, EnumErrorCode.ERROR_DATASTORE_CACHE_MULTIPLE_SAVE); KinveyException kinveyException = null; Exception exception = null; try { // network kinveyDataStoreNetworkResponse = await HandleNetworkRequestAsync(entities).ConfigureAwait(false); } catch (KinveyException kinveyEx) { kinveyException = kinveyEx; } catch (Exception ex) { exception = ex; } if (kinveyException != null || exception != null) { foreach (var pendingAction in pendingWriteActions) { SyncQueue.Enqueue(pendingAction); } if (kinveyException != null) { throw kinveyException; } } else { for (var index = 0; index < kinveyDataStoreResponse.Entities.Count; index++) { if (kinveyDataStoreNetworkResponse.Entities[index] != null) { if (kinveyDataStoreResponse.Entities[index] != null) { var obj = JObject.FromObject(kinveyDataStoreResponse.Entities[index]); var id = obj["_id"].ToString(); Cache.UpdateCacheSave(kinveyDataStoreNetworkResponse.Entities[index], id); } else { CacheSave(kinveyDataStoreNetworkResponse.Entities[index]); } } else { if (kinveyDataStoreResponse.Entities[index] != null) { var obj = JObject.FromObject(kinveyDataStoreResponse.Entities[index]); var id = obj["_id"].ToString(); var existingPendingWriteAction = pendingWriteActions.Find(e => e.entityId.Equals(id)); if (existingPendingWriteAction != null) { SyncQueue.Enqueue(existingPendingWriteAction); } } } } kinveyDataStoreResponse = kinveyDataStoreNetworkResponse; } ThrowExceptionIfOnlyErrors(kinveyDataStoreResponse, EnumErrorCategory.ERROR_BACKEND, EnumErrorCode.ERROR_JSON_RESPONSE); break; default: throw new KinveyException(EnumErrorCategory.ERROR_GENERAL, EnumErrorCode.ERROR_GENERAL, "Invalid write policy"); } return(kinveyDataStoreResponse); }
private async Task <KinveyMultiInsertResponse <T> > HandleNetworkRequestAsync(IList <T> entities) { var kinveyDataStoreResponse = new KinveyMultiInsertResponse <T> { Entities = HelperMethods.Initialize <T>(default(T), entities.Count), Errors = new List <Error>() }; var updateRequests = new Dictionary <int, NetworkRequest <T> >(); var entitiesToMultiInsert = new List <T>(); var initialIndexes = new List <int>(); for (var index = 0; index < entities.Count; index++) { var idToken = JObject.FromObject(entities[index])["_id"]; if (idToken != null && !string.IsNullOrEmpty(idToken.ToString())) { var updateRequest = Client.NetworkFactory.buildUpdateRequest(Collection, entities[index], idToken.ToString()); updateRequests.Add(index, updateRequest); } else { entitiesToMultiInsert.Add(entities[index]); initialIndexes.Add(index); } } var multiInsertNetworkResponse = new KinveyMultiInsertResponse <T> { Entities = new List <T>(), Errors = new List <Error>() }; if (entitiesToMultiInsert.Count > 0) { var countOfMultiInsertOperations = Math.Ceiling(entitiesToMultiInsert.Count / (double)Constants.NUMBER_LIMIT_OF_ENTITIES); var currentIndex = 0; var currentCountOfMultiInsertOperations = 0; while (currentCountOfMultiInsertOperations < countOfMultiInsertOperations) { var tasks = new List <Task <KinveyMultiInsertResponse <T> > >(); for (var index = currentCountOfMultiInsertOperations; index < currentCountOfMultiInsertOperations + 10; index++) { if (index < countOfMultiInsertOperations) { tasks.Add(HandleMultiInsertRequestAsync(entitiesToMultiInsert.Skip(index * Constants.NUMBER_LIMIT_OF_ENTITIES).Take(Constants.NUMBER_LIMIT_OF_ENTITIES).ToList())); } } await Task.WhenAll(tasks.ToArray()).ConfigureAwait(false); foreach (var task in tasks) { for (var index = 0; index < task.Result.Entities.Count; index++) { multiInsertNetworkResponse.Entities.Add(task.Result.Entities[index]); if (task.Result.Entities[index] == null) { var error = task.Result.Errors?.Find(er => er.Index == index); if (error != null) { var newError = new Error { Index = currentIndex, Code = error.Code, Errmsg = error.Errmsg }; multiInsertNetworkResponse.Errors.Add(newError); } } currentIndex++; } } currentCountOfMultiInsertOperations += 10; } } for (var index = 0; index < multiInsertNetworkResponse.Entities.Count; index++) { kinveyDataStoreResponse.Entities[initialIndexes[index]] = multiInsertNetworkResponse.Entities[index]; var error = multiInsertNetworkResponse.Errors?.Find(er => er.Index == index); if (error != null) { var newError = new Error { Index = initialIndexes[index], Code = error.Code, Errmsg = error.Errmsg }; kinveyDataStoreResponse.Errors.Add(newError); } } foreach (var updateRequest in updateRequests) { T updatedEntity = default(T); try { updatedEntity = await updateRequest.Value.ExecuteAsync().ConfigureAwait(false); } catch (Exception ex) { var error = new Error { Index = updateRequest.Key, Code = 0, Errmsg = ex.Message }; kinveyDataStoreResponse.Errors.Add(error); } kinveyDataStoreResponse.Entities[updateRequest.Key] = updatedEntity; } kinveyDataStoreResponse.Errors.Sort((x, y) => x.Index.CompareTo(y.Index)); return(kinveyDataStoreResponse); }
private async Task <Tuple <PushDataStoreResponse <T>, int> > HandlePushMultiPOST(ICollection <PendingWriteAction> pendingWriteActions) { var offset = 0; var response = new PushDataStoreResponse <T>(); var multiInsertNetworkResponse = new KinveyMultiInsertResponse <T> { Entities = new List <T>(), Errors = new List <Error>() }; var localData = new List <Tuple <string, T, PendingWriteAction> >(); var isException = false; try { foreach (var pendingWriteAction in pendingWriteActions) { var entity = Cache.FindByID(pendingWriteAction.entityId); var obj = JObject.FromObject(entity); obj["_id"] = null; entity = Newtonsoft.Json.JsonConvert.DeserializeObject <T>(obj.ToString()); localData.Add(new Tuple <string, T, PendingWriteAction>(pendingWriteAction.entityId, entity, pendingWriteAction)); } var multiInsertNetworkRequest = Client.NetworkFactory.BuildMultiInsertRequest <T, KinveyMultiInsertResponse <T> >(Collection, localData.Select(e => e.Item2).ToList()); multiInsertNetworkResponse = await multiInsertNetworkRequest.ExecuteAsync().ConfigureAwait(false); } catch (KinveyException ke) { response.AddKinveyException(ke); offset += pendingWriteActions.Count; isException = true; } catch (Exception ex) { response.AddKinveyException(new KinveyException(EnumErrorCategory.ERROR_GENERAL, EnumErrorCode.ERROR_GENERAL, ex.Message, ex)); offset += pendingWriteActions.Count; isException = true; } if (!isException) { for (var index = 0; index < localData.Count; index++) { try { if (multiInsertNetworkResponse.Entities[index] != null) { Cache.UpdateCacheSave(multiInsertNetworkResponse.Entities[index], localData[index].Item1); var removeResult = SyncQueue.Remove(localData[index].Item3); if (removeResult == 0) { offset++; } } } catch (KinveyException ke) { response.AddKinveyException(ke); offset++; } catch (Exception ex) { response.AddKinveyException(new KinveyException(EnumErrorCategory.ERROR_GENERAL, EnumErrorCode.ERROR_GENERAL, ex.Message, ex)); offset++; } } } var entities = multiInsertNetworkResponse.Entities.Where(e => e != null).ToList(); response.AddEntities(entities); foreach (var error in multiInsertNetworkResponse.Errors) { response.AddKinveyException(new KinveyException(EnumErrorCategory.ERROR_BACKEND, EnumErrorCode.ERROR_GENERAL, error.Errmsg)); offset++; } var result = new Tuple <PushDataStoreResponse <T>, int>(response, offset); return(result); }