示例#1
0
        private Tuple <PendingWriteAction, T> CacheSave(T entity)
        {
            PendingWriteAction pendingAction = null;
            T savedEntity = default(T);

            var idToken = JObject.FromObject(entity)["_id"];

            if (idToken != null && !String.IsNullOrEmpty(idToken.ToString()))
            {
                var networkRequest = Client.NetworkFactory.buildUpdateRequest(Collection, entity, idToken.ToString());

                savedEntity = Cache.Update(entity);

                pendingAction = PendingWriteAction.buildFromRequest(networkRequest);
            }
            else
            {
                var networkRequest = Client.NetworkFactory.buildCreateRequest(Collection, entity);

                var tempIdLocal = PrepareCacheSave(ref entity);
                savedEntity = Cache.Save(entity);

                pendingAction          = PendingWriteAction.buildFromRequest(networkRequest);
                pendingAction.entityId = tempIdLocal;
            }

            return(new Tuple <PendingWriteAction, T>(pendingAction, savedEntity));
        }
示例#2
0
 /// <summary>
 /// Removes pending write action item.
 /// </summary>
 /// <param name="pending"> Pending write action item. </param>
 /// <returns>The count of removed pending write action items.</returns>
 public int Remove(PendingWriteAction pending)
 {
     lock (dbConnection)
     {
         return(dbConnection.Delete(pending));
     }
 }
示例#3
0
        private async Task <Tuple <T, KinveyException, int> > HandlePushDELETE(PendingWriteAction pwa)
        {
            var             offset          = 0;
            KinveyException kinveyException = null;

            try
            {
                int result = 0;

                NetworkRequest <KinveyDeleteResponse> request = Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(pwa.collection, pwa.entityId);
                KinveyDeleteResponse kdr = await request.ExecuteAsync().ConfigureAwait(false);

                if (kdr.count == 1)
                {
                    result = SyncQueue.Remove(pwa);

                    if (result == 0)
                    {
                        offset++;
                    }
                }
            }
            catch (KinveyException ke)
            {
                kinveyException = ke;
                offset++;
            }

            return(new Tuple <T, KinveyException, int>(default(T), kinveyException, offset));
        }
示例#4
0
        private async Task <Tuple <T, KinveyException, int> > HandlePushPUT(PendingWriteAction pwa)
        {
            T               entity          = default(T);
            var             offset          = 0;
            KinveyException kinveyException = null;

            try
            {
                int result = 0;

                var localEntity = Cache.FindByID(pwa.entityId);

                NetworkRequest <T> request = Client.NetworkFactory.buildUpdateRequest <T>(pwa.collection, localEntity, pwa.entityId);
                entity = await request.ExecuteAsync().ConfigureAwait(false);

                Cache.UpdateCacheSave(entity, pwa.entityId);

                result = SyncQueue.Remove(pwa);

                if (result == 0)
                {
                    offset++;
                }
            }
            catch (KinveyException ke)
            {
                kinveyException = ke;
                offset++;
            }

            return(new Tuple <T, KinveyException, int>(entity, kinveyException, offset));
        }
示例#5
0
 /// <summary>
 /// Fetches and deletes the first pending write action item.
 /// </summary>
 /// <returns> Received pending write action item from the cache. </returns>
 public PendingWriteAction Pop()
 {
     lock (dbConnection)
     {
         try
         {
             PendingWriteAction item = Peek();
             dbConnection.Delete <PendingWriteAction>(item.key);
             return(item);
         }
         catch (Exception)
         {
             return(null);
         }
     }
 }
        public static PendingWriteAction buildFromRequest <T> (NetworkRequest <T> request)
        {
            PendingWriteAction newAction = new PendingWriteAction();

            newAction.action = request.RequestMethod;

            if (request.uriResourceParameters.ContainsKey("entityID"))
            {
                newAction.entityId = request.uriResourceParameters["entityID"];
            }

            if (request.uriResourceParameters.ContainsKey("collectionName"))
            {
                newAction.collection = request.uriResourceParameters["collectionName"];
            }

            newAction.state = JsonConvert.SerializeObject(request.customRequestHeaders);

            return(newAction);
        }
示例#7
0
        private async Task <Tuple <T, KinveyException, int> > HandlePushPOST(PendingWriteAction pwa)
        {
            T               entity          = default(T);
            var             offset          = 0;
            KinveyException kinveyException = null;

            try
            {
                int result = 0;

                string tempID = pwa.entityId;

                var localEntity = Cache.FindByID(pwa.entityId);

                JObject obj = JObject.FromObject(localEntity);
                obj["_id"]  = null;
                localEntity = Newtonsoft.Json.JsonConvert.DeserializeObject <T>(obj.ToString());

                NetworkRequest <T> request = Client.NetworkFactory.buildCreateRequest <T>(pwa.collection, localEntity);
                entity = await request.ExecuteAsync().ConfigureAwait(false);

                Cache.UpdateCacheSave(entity, tempID);

                result = SyncQueue.Remove(pwa);

                if (result == 0)
                {
                    offset++;
                }
            }
            catch (KinveyException ke)
            {
                kinveyException = ke;
                offset++;
            }

            return(new Tuple <T, KinveyException, int>(entity, kinveyException, offset));
        }
示例#8
0
        public override async Task <T> ExecuteAsync()
        {
            T savedEntity = default(T);
            NetworkRequest <T> request  = null;
            string             entityID = null;;

            JToken idToken = JObject.FromObject(entity) ["_id"];

            if (idToken != null &&
                !String.IsNullOrEmpty(idToken.ToString()))
            {
                entityID = idToken.ToString();
                request  = Client.NetworkFactory.buildUpdateRequest(Collection, entity, entityID);
            }
            else
            {
                request = Client.NetworkFactory.buildCreateRequest(Collection, entity);
            }

            switch (Policy)
            {
            case WritePolicy.FORCE_LOCAL:
                // sync
                PendingWriteAction pendingAction = PendingWriteAction.buildFromRequest(request);

                string saveModeLocal = request.RequestMethod;
                string tempIdLocal   = null;

                if (String.Equals("POST", saveModeLocal))
                {
                    tempIdLocal            = PrepareCacheSave(ref entity);
                    savedEntity            = Cache.Save(entity);
                    pendingAction.entityId = tempIdLocal;
                }
                else
                {
                    savedEntity = Cache.Update(entity);
                }

                SyncQueue.Enqueue(pendingAction);

                break;

            case WritePolicy.FORCE_NETWORK:
                // network
                savedEntity = await request.ExecuteAsync();

                break;

            case WritePolicy.NETWORK_THEN_LOCAL:
                // cache
                string saveModeNetworkThenLocal = request.RequestMethod;
                string tempIdNetworkThenLocal   = null;

                if (String.Equals("POST", saveModeNetworkThenLocal))
                {
                    tempIdNetworkThenLocal = PrepareCacheSave(ref entity);
                    Cache.Save(entity);
                }
                else
                {
                    Cache.Update(entity);
                }

                // network save
                savedEntity = await request.ExecuteAsync();

                if (tempIdNetworkThenLocal != null)
                {
                    Cache.UpdateCacheSave(savedEntity, tempIdNetworkThenLocal);
                }

                break;

            case WritePolicy.LOCAL_THEN_NETWORK:
                string saveModeLocalThenNetwork = request.RequestMethod;

                // cache
                if (String.Equals("POST", saveModeLocalThenNetwork))
                {
                    entityID    = PrepareCacheSave(ref entity);
                    savedEntity = Cache.Save(entity);
                }
                else
                {
                    savedEntity = Cache.Update(entity);
                }

                KinveyException kinveyException = null;
                Exception       exception       = null;
                try
                {
                    // network save
                    savedEntity = await request.ExecuteAsync();
                }
                catch (KinveyException kinveyEx)
                {
                    kinveyException = kinveyEx;
                }
                catch (Exception ex)
                {
                    exception = ex;
                }

                if (kinveyException != null || exception != null)
                {
                    // if the network request fails, save data to sync queue
                    var localPendingAction = PendingWriteAction.buildFromRequest(request);
                    localPendingAction.entityId = entityID;

                    SyncQueue.Enqueue(localPendingAction);

                    if (kinveyException != null)
                    {
                        throw kinveyException;
                    }
                }
                else
                {
                    Cache.UpdateCacheSave(savedEntity, entityID);
                }

                break;

            default:
                throw new KinveyException(EnumErrorCategory.ERROR_GENERAL, EnumErrorCode.ERROR_GENERAL, "Invalid write policy");
            }

            return(savedEntity);
        }
示例#9
0
        /// <summary>
        /// Enqueues a pending write action item.
        /// </summary>
        /// <returns>The count of enqueued pending write action items.</returns>
        /// <param name="pending">Pending write action item.</param>
        public int Enqueue(PendingWriteAction pending)
        {
            lock (dbConnection)
            {
                // Check if a sync queue entry for this entity already exists
                PendingWriteAction existingSyncItem = GetByID(pending.entityId);
                if (existingSyncItem != null)
                {
                    if (existingSyncItem.action == Constants.STR_REST_METHOD_PUT &&
                        pending.action == Constants.STR_REST_METHOD_PUT)
                    {
                        // If both the existing and pending actions are PUT, this means either this is an already created
                        // item, or the item has been created with a custom ID on the client.  In either case, the existing
                        // entry will capture the state of the entity.
                        return(0);
                    }
                    else if (existingSyncItem.action == Constants.STR_REST_METHOD_POST &&
                             pending.action == Constants.STR_REST_METHOD_PUT)
                    {
                        // Do not enqueue in the case of an existing POST, since the POST
                        // entry will already capture the current state of the entity.
                        return(0);
                    }
                    else if (existingSyncItem.action == Constants.STR_REST_METHOD_PUT &&
                             pending.action == Constants.STR_REST_METHOD_POST)
                    {
                        // highly unlikely, but favor the POST
                        this.Remove(existingSyncItem);
                    }
                    else if (existingSyncItem.action == Constants.STR_REST_METHOD_POST &&
                             pending.action == Constants.STR_REST_METHOD_POST)
                    {
                        // Should be imposssible to have this situation, favor the
                        // existing POST by not enqueueing
                        return(0);
                    }
                    else if (existingSyncItem.action == Constants.STR_REST_METHOD_DELETE &&
                             (pending.action == Constants.STR_REST_METHOD_PUT || pending.action == Constants.STR_REST_METHOD_POST))
                    {
                        // odd case where an object has somehow been created/updated
                        // after a delete call, but favor the create/update
                        this.Remove(existingSyncItem);
                    }
                    else if (pending.action == Constants.STR_REST_METHOD_DELETE)
                    {
                        // no matter what, favor the current deletion
                        this.Remove(existingSyncItem);

                        // If the existing item that is being deleted is something that only existed locally,
                        // do not insert the DELETE action into the queue, since it is local-only.
                        // Note that this cannot be optimized for the case when a custom ID has been set on
                        // the entity.
                        if (existingSyncItem.entityId.StartsWith("temp_", StringComparison.OrdinalIgnoreCase))
                        {
                            return(0);
                        }
                    }
                }

                return(dbConnection.Insert(pending));
            }
        }
示例#10
0
        public override async Task <KinveyDeleteResponse> ExecuteAsync()
        {
            var kdr = default(KinveyDeleteResponse);

            switch (Policy)
            {
            case WritePolicy.FORCE_LOCAL:
                // sync
                if (_query == null)
                {
                    // cache
                    kdr = Cache.DeleteByID(entityID);

                    var request = Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, entityID);

                    var pendingAction = PendingWriteAction.buildFromRequest(request);
                    SyncQueue.Enqueue(pendingAction);
                }
                else
                {
                    // cache
                    kdr = Cache.DeleteByQuery(_query);

                    foreach (var id in kdr.IDs)
                    {
                        var request       = Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, id);
                        var pendingAction = PendingWriteAction.buildFromRequest(request);
                        SyncQueue.Enqueue(pendingAction);
                    }
                }
                break;

            case WritePolicy.FORCE_NETWORK:
                // network
                if (_query == null)
                {
                    kdr = await Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, entityID).ExecuteAsync();
                }
                else
                {
                    var mongoQuery = KinveyMongoQueryBuilder.GetQueryForRemoveOperation <T>(_query);
                    kdr = await Client.NetworkFactory.buildDeleteRequestWithQuery <KinveyDeleteResponse>(Collection, mongoQuery).ExecuteAsync();
                }
                break;

            case WritePolicy.NETWORK_THEN_LOCAL:
                if (_query == null)
                {
                    // cache
                    kdr = Cache.DeleteByID(entityID);

                    // network
                    kdr = await Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, entityID).ExecuteAsync();
                }
                else
                {
                    // cache
                    kdr = Cache.DeleteByQuery(_query);

                    // network
                    var mongoQuery = KinveyMongoQueryBuilder.GetQueryForRemoveOperation <T>(_query);
                    kdr = await Client.NetworkFactory.buildDeleteRequestWithQuery <KinveyDeleteResponse>(Collection, mongoQuery).ExecuteAsync();
                }
                break;

            case WritePolicy.LOCAL_THEN_NETWORK:
                if (_query == null)
                {
                    // cache
                    kdr = Cache.DeleteByID(entityID);

                    var deleteRequest = Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, entityID);

                    KinveyException kinveyException = null;
                    Exception       exception       = null;
                    try
                    {
                        // network
                        kdr = await deleteRequest.ExecuteAsync();
                    }
                    catch (KinveyException kinveyEx)
                    {
                        kinveyException = kinveyEx;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }

                    if (kinveyException != null || exception != null)
                    {
                        var pendingAction = PendingWriteAction.buildFromRequest(deleteRequest);
                        SyncQueue.Enqueue(pendingAction);

                        if (kinveyException != null)
                        {
                            throw kinveyException;
                        }
                    }
                }
                else
                {
                    // cache
                    kdr = Cache.DeleteByQuery(_query);

                    // network
                    KinveyException kinveyException = null;
                    Exception       exception       = null;
                    try
                    {
                        var mongoQuery = KinveyMongoQueryBuilder.GetQueryForRemoveOperation <T>(_query);
                        kdr = await Client.NetworkFactory.buildDeleteRequestWithQuery <KinveyDeleteResponse>(Collection, mongoQuery).ExecuteAsync();
                    }
                    catch (KinveyException kinveyEx)
                    {
                        kinveyException = kinveyEx;
                    }
                    catch (Exception ex)
                    {
                        exception = ex;
                    }

                    if (kinveyException != null || exception != null)
                    {
                        foreach (var id in kdr.IDs)
                        {
                            var request       = Client.NetworkFactory.buildDeleteRequest <KinveyDeleteResponse>(Collection, id);
                            var pendingAction = PendingWriteAction.buildFromRequest(request);
                            SyncQueue.Enqueue(pendingAction);
                        }

                        if (kinveyException != null)
                        {
                            throw kinveyException;
                        }
                    }
                }
                break;

            default:
                throw new KinveyException(EnumErrorCategory.ERROR_GENERAL, EnumErrorCode.ERROR_GENERAL, "Invalid write policy");
            }

            return(kdr);
        }