Beispiel #1
0
        public override async Task <PageReadResult> MovePreviousAsync(CancellationToken cancellationToken)
        {
            int page;

            lock (_pageLock)
            {
                page = CurrentPage - 1;
                if (page < 1)
                {
                    return(new PageReadResult(PagedFeed.GetUriForPage(page), new List <ScrapedSong>(), null, null, 0, new IndexOutOfRangeException($"Page {page} is below the minimum of 1."), PageErrorType.PageOutOfRange));
                }
                CurrentPage--;
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
            }
            Task <PageReadResult> pageTask;
            PageReadResult?       result = null;

            if (TryGetCachedPage(page, out Task <PageReadResult>?cachedTask) && cachedTask != null)
            {
                if (cachedTask.IsCompleted)
                {
                    return(await cachedTask.ConfigureAwait(false));
                }
                else
                {
                    using (CancellationTokenSource? tcs = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
                    {
                        bool completed = await Utilities.WaitUntil(() => cachedTask.IsCompleted, tcs.Token).ConfigureAwait(false);

                        if (completed)
                        {
                            result = await cachedTask.ConfigureAwait(false);
                        }
                        else
                        {
                            return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
                        }
                    }
                }
            }
            else
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
                }
                Uri uri = PagedFeed.GetUriForPage(page);
                pageTask = PagedFeed.GetSongsAsync(uri, cancellationToken);
                if (EnablePageCache && CachedPages != null)
                {
                    CachedPages.TryAdd(page, pageTask);
                }
                result = await pageTask.ConfigureAwait(false);
            }
            return(result);
        }
        public override async Task <PageReadResult> MoveNextAsync(CancellationToken cancellationToken)
        {
            PageReadResult?result          = null;
            Uri?           pageUri         = null;
            FeedDate       feedDate        = default;
            bool           criticalFailure = false;

            try
            {
                await _semaphore.WaitAsync(cancellationToken);

                feedDate = new FeedDate(CurrentEarliest, DateDirection.Before);
                pageUri  = DatedFeed.GetUriForDate(feedDate);
                if (pageUri == LastFetchedUri)
                {
                    criticalFailure = true;
                    throw new FeedReaderException($"URL '{pageUri}' was previously read, aborting to avoid possible infinite loop.");
                }
                result = await DatedFeed.GetSongsAsync(pageUri, cancellationToken).ConfigureAwait(false);

                LastFetchedUri = pageUri;
            }
            catch (OperationCanceledException ex)
            {
                result = PageReadResult.CancelledResult(pageUri, ex);
            }
            catch (Exception ex)
            {
                if (criticalFailure)
                {
                    throw;
                }
                result = new PageReadResult(pageUri, null, null, null, 0, ex, PageErrorType.Unknown);
            }
            finally
            {
                ProcessResult(result, feedDate.Direction);
                _semaphore.Release();
            }

            return(result);
        }
Beispiel #3
0
        public override async Task <PageReadResult> MoveNextAsync(CancellationToken cancellationToken)
        {
            int page;

            lock (_pageLock)
            {
                CurrentPage++;
                page = CurrentPage;
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
            }

            Task <PageReadResult> pageTask;
            PageReadResult?       result = null;

            if (TryGetCachedPage(page, out Task <PageReadResult>?cachedTask) && cachedTask != null)
            {
                if (cachedTask.IsCompleted)
                {
                    return(await cachedTask.ConfigureAwait(false));
                }
                else
                {
                    using (CancellationTokenSource? tcs = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
                    {
                        bool completed = await Utilities.WaitUntil(() => cachedTask.IsCompleted, tcs.Token).ConfigureAwait(false);

                        if (completed)
                        {
                            result = await cachedTask.ConfigureAwait(false);
                        }
                        else
                        {
                            return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
                        }
                    }
                }
            }
            else
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return(PageReadResult.CancelledResult(PagedFeed.GetUriForPage(page)));
                }
                Uri uri = PagedFeed.GetUriForPage(page);
                pageTask = PagedFeed.GetSongsAsync(uri, cancellationToken);
                if (EnablePageCache && CachedPages != null)
                {
                    CachedPages.TryAdd(page, pageTask);
                }
                result = await pageTask.ConfigureAwait(false);
            }
            if (result.IsLastPage)
            {
                CanMoveNext = false;
                LastPage    = Math.Min(LastPage, page);
            }

            return(result);
        }