private async Task BeginRefreshAsync(int startAt, bool shouldAwait, CancellationToken cancelToken)
        {
            IList <ItemKey> keysToDownload = m_data.Keys.CollectKeysNeedingDownload(startAt, ReadAheadChunkSize);

            if (keysToDownload.IsNullOrEmpty())
            {
                return;
            }
            //
            // Refresh happens in the background
            // This will return as soon as the task is launched
            //
            PendingGetCompletionDelegate completionCallback = null;

            if (!shouldAwait)
            {
                completionCallback = PendingGetCompletion; // Callback => download items in background
            }

            PendingGetResult result = await Store.RefreshAsyncImpl(
                keysToDownload,
                m_data.TypeVersions,
                completionCallback,
                cancelToken);

            if (result == null)
            {
                return; // NO pending work
            }

            PendingGetCompletion(this, result);
        }
Exemple #2
0
        /// <summary>
        /// Triggers a FORCED refresh in the background and returns as soon as it can
        /// When the background fetch completes, invokes the callback
        /// </summary>
        public IAsyncAction DownloadAsync(
            IList <ItemKey> keys,
            IList <string> typeVersions,
            PendingGetCompletionDelegate callback)
        {
            if (callback == null)
            {
                throw new ArgumentNullException("callback");
            }

            return(AsyncInfo.Run(async cancelToken => { await DownloadAsyncImpl(keys, typeVersions, callback, cancelToken); }));
        }
        /// <summary>
        /// Returns a list of items such that:
        ///     - If an item matching the equivalent key is available locally, returns it
        ///     - ELSE returns a NULL item at the ordinal matching the key - indicating that the item is PENDING
        ///     - Issues a background get for the pending items, and notifies you (callback) when done
        /// This technique is useful for making responsive UIs. 
        ///   - User can view locally available items quickly
        ///   - Pending items are shown as 'loading' and updated as they become available
        /// </summary>
        /// <param name="keys">keys to retrieve</param>
        /// <param name="typeVersions"></param>
        /// <returns>List with COUNT == keys.Count. If an item was not found locally, the equivalent item in the list is NULL</returns>
        public IAsyncOperation<IList<IItemDataTyped>> GetAsync(
            IList<ItemKey> keys,
            IList<string> typeVersions, 
            PendingGetCompletionDelegate callback)
        {
            if (keys == null)
            {
                throw new ArgumentNullException("keys");
            }

            return AsyncInfo.Run(cancelToken => GetAsyncImpl(keys, typeVersions, callback, cancelToken));
        }
Exemple #4
0
        public IAsyncOperation <IList <RecordItem> > GetItemsAsync(
            IList <ItemKey> keys,
            IList <string> typeVersions,
            PendingGetCompletionDelegate callback)
        {
            if (keys == null)
            {
                throw new ArgumentNullException("keys");
            }

            return(AsyncInfo.Run(async cancelToken => await GetItemsAsyncImpl(keys, typeVersions, callback, cancelToken)));
        }
Exemple #5
0
 private void NotifyPendingGetComplete(PendingGetCompletionDelegate callback, PendingGetResult result)
 {
     if (callback != null)
     {
         try
         {
             callback(this, result);
         }
         catch
         {
         }
     }
 }
Exemple #6
0
        internal async Task <IList <RecordItem> > GetItemsAsyncImpl(IList <ItemKey> keys, IList <string> typeVersions,
                                                                    PendingGetCompletionDelegate callback,
                                                                    CancellationToken cancelToken)
        {
            //
            // true: include null items - i.e. items not found in the local store
            //
            IList <RecordItem> foundItems = await m_localStore.GetItemsAsyncImpl(keys, true);

            //
            // Trigger a download of items that are not available yet...
            //
            IList <ItemKey> pendingKeys = CollectKeysNeedingDownload(keys, typeVersions, foundItems);

            if (pendingKeys.IsNullOrEmpty())
            {
                return(foundItems);
            }

            PendingGetResult pendingResult = await DownloadAsyncImpl(pendingKeys, typeVersions, callback, cancelToken);

            if (pendingResult == null)
            {
                return(foundItems);
            }

            //
            // Load fresh items
            //
            if (pendingResult.HasKeysFound)
            {
                await LoadNewItems(foundItems, keys, pendingResult.KeysFound);
            }

            return(foundItems);
        }
        internal async Task<PendingGetResult> DownloadItems(IList<ItemKey> keys, IList<string> typeVersions, PendingGetCompletionDelegate callback, CancellationToken cancelToken)
        {
            var result = new PendingGetResult();
            try
            {
                result.KeysRequested = keys;

                ItemQuery query = this.CreateRefreshQueryForKeys(keys, typeVersions);

                IList<RecordItem> items = await m_remoteStore.GetAllItemsAsync(query);
                
                 await this.PersistDownloadedItemsAsync(items);

                result.KeysFound = (
                    from item in items
                    select item.Key
                    ).ToArray();
            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            NotifyPendingGetComplete(callback, result);

            return result;
        }
 private void NotifyPendingGetComplete(PendingGetCompletionDelegate callback, PendingGetResult result)
 {
     if (callback != null)
     {
         try
         {
             callback(this, result);
         }
         catch
         {
         }
     }
 }
        private async Task<PendingGetResult> DownloadItems(
            IList<ItemKey> keys, 
            IList<string> typeVersions,
            PendingGetCompletionDelegate callback, 
            CancellationToken cancelToken)
        {
            var result = new PendingGetResult();
            try
            {
                result.KeysRequested = keys;

                ItemQuery query = ItemQuery.QueryForKeys(keys);
                query.View.SetSections(SectionsToFetch);
                if (typeVersions != null && typeVersions.Count > 0)
                {
                    query.View.TypeVersions.AddRange(typeVersions);
                }

                IList<RecordItem> items = await m_record.GetAllItemsAsync(query);
                await m_itemStore.PutItemsAsyncImpl(items);

                result.KeysFound = (
                    from item in items
                    select item.Key
                    ).ToArray();
            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            NotifyPendingGetComplete(callback, result);

            return result;
        }
        internal async Task<PendingGetResult> RefreshAsyncImpl(
            IList<ItemKey> keys,
            IList<string> typeVersions,
            PendingGetCompletionDelegate callback, 
            CancellationToken cancelToken)
        {
            IList<ItemKey> pendingKeys = await CollectKeysNotInLocalStore(keys, typeVersions);
            if (pendingKeys.IsNullOrEmpty())
            {
                return null; // No pending work
            }

            return await DownloadAsyncImpl(pendingKeys, typeVersions, callback, cancelToken);
        }
        internal async Task<PendingGetResult> DownloadAsyncImpl(
            IList<ItemKey> keys,
            IList<string> typeVersions,
            PendingGetCompletionDelegate callback, 
            CancellationToken cancelToken)
        {
            if (callback != null)
            {
                //
                // Run the download in the background. 
                // Return what we have right away, and notify caller when pending items arrive
                //
                Task task = DownloadItems(keys, typeVersions, callback, cancelToken);
                return null;
            }

            //
            // Wait for download to complete...
            //
            PendingGetResult result = await DownloadItems(keys, typeVersions, callback, cancelToken);
            result.EnsureSuccess();

            return result;
        }
        private async Task<IList<RecordItem>> GetItemsAsyncImpl(
            IList<ItemKey> keys,
            IList<string> typeVersions,
            PendingGetCompletionDelegate callback, 
            CancellationToken cancelToken)
        {
            //
            // true: include null items - i.e. items not found in the local store
            //
            IList<RecordItem> foundItems = await Local.GetItemsAsyncImpl(keys, true);

            //
            // Trigger a download of items that are not available yet...
            //
            IList<ItemKey> pendingKeys = CollectKeysNeedingDownload(keys, typeVersions, foundItems);
            if (pendingKeys.IsNullOrEmpty())
            {
                return foundItems;
            }

            PendingGetResult pendingResult = await DownloadAsyncImpl(pendingKeys, typeVersions, callback, cancelToken);
            if (pendingResult == null)
            {
                return foundItems;
            }

            //
            // Load fresh items
            //
            if (pendingResult.HasKeysFound)
            {
                await LoadNewItems(foundItems, keys, pendingResult.KeysFound);
            }

            return foundItems;
        }
        internal async Task<IList<IItemDataTyped>> GetAsyncImpl(
            IList<ItemKey> keys,
            IList<string> typeVersions,
            PendingGetCompletionDelegate callback, 
            CancellationToken cancelToken)
        {
            IList<RecordItem> items = await GetItemsAsyncImpl(keys, typeVersions, callback, cancelToken);
            if (items != null)
            {
                return (
                    from item in items
                    select (item != null ? item.TypedData : null)
                    ).ToArray();
            }

            return null;
        }
        /// <summary>
        /// Triggers a FORCED refresh in the background and returns as soon as it can
        /// When the background fetch completes, invokes the callback
        /// </summary>
        public IAsyncAction DownloadAsync(
            IList<ItemKey> keys,
            IList<string> typeVersions, 
            PendingGetCompletionDelegate callback)
        {
            if (callback == null)
            {
                throw new ArgumentNullException("callback");
            }

            return AsyncInfo.Run(async cancelToken => { await DownloadAsyncImpl(keys, typeVersions, callback, cancelToken); });
        }
Exemple #15
0
        internal async Task <PendingGetResult> DownloadItems(IList <ItemKey> keys, IList <string> typeVersions, PendingGetCompletionDelegate callback, CancellationToken cancelToken)
        {
            var result = new PendingGetResult();

            try
            {
                result.KeysRequested = keys;

                ItemQuery query = this.CreateRefreshQueryForKeys(keys, typeVersions);

                IList <RecordItem> items = await m_remoteStore.GetAllItemsAsync(query);

                await this.PersistDownloadedItemsAsync(items);

                result.KeysFound = (
                    from item in items
                    select item.Key
                    ).ToArray();
            }
            catch (Exception ex)
            {
                result.Exception = ex;
            }

            NotifyPendingGetComplete(callback, result);

            return(result);
        }
Exemple #16
0
        internal async Task <PendingGetResult> RefreshAsyncImpl(IList <ItemKey> keys, IList <string> typeVersions, PendingGetCompletionDelegate callback, CancellationToken cancelToken)
        {
            IList <ItemKey> pendingKeys = await CollectKeysNotInLocalStore(keys, typeVersions);

            if (pendingKeys.IsNullOrEmpty())
            {
                return(null); // No pending work
            }

            System.Diagnostics.Debug.WriteLine("Downloading {0} items", keys.Count);

            return(await DownloadAsyncImpl(pendingKeys, typeVersions, callback, cancelToken));
        }
Exemple #17
0
        internal async Task <PendingGetResult> DownloadAsyncImpl(IList <ItemKey> keys, IList <string> typeVersions, PendingGetCompletionDelegate callback, CancellationToken cancelToken)
        {
            if (callback != null)
            {
                //
                // Run the download in the background.
                // Return what we have right away, and notify caller when pending items arrive
                //
                Task task = DownloadItems(keys, typeVersions, callback, cancelToken);
                return(null);
            }

            //
            // Wait for download to complete...
            //
            PendingGetResult result = await DownloadItems(keys, typeVersions, callback, cancelToken);

            result.EnsureSuccess();

            return(result);
        }
Exemple #18
0
        internal async Task <IList <IItemDataTyped> > GetAsyncImpl(IList <ItemKey> keys, IList <string> typeVersions, PendingGetCompletionDelegate callback, CancellationToken cancelToken)
        {
            IList <RecordItem> items = await GetItemsAsyncImpl(keys, typeVersions, callback, cancelToken);

            if (items != null)
            {
                return((
                           from item in items
                           select(item != null ? item.TypedData : null)
                           ).ToArray());
            }

            return(null);
        }