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);
        }
Exemple #5
0
        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);
        }