/// <summary> /// - this returns twice, once immediately with cached value if exists, once again with updated results if the date of the week is older than Wednesday. /// </summary> /// <param name="issueNumber"></param> /// <returns></returns> public IObservable <IssueResult> Issue(int issueNumber) { return(_stateService.GetAndFetchLatest(BlobCacheKeys.GetKeyForIssue(issueNumber), _weeklyXamarinApiService.WeeklyXamarinApi.Issues(), fetchPredicate: dateTimeOffset => true, absoluteExpiration: RxApp.MainThreadScheduler.Now.AddDays(31))); }
IObservable <List <ArticleViewModel> > GetAndFetchLatestArticles() { return(Cache.GetAndFetchLatest(BlobCacheKeys.GetCacheKeyForFeedAddress(FeedAddress), async() => await Task.Run(() => FeedService.GetFeedFor(FeedAddress)), datetimeOffset => true, // store the results in the cache for 31 days. RxApp.MainThreadScheduler.Now + TimeSpan.FromDays(31))); }
/// <summary> /// /// </summary> /// <param name="issuesPerPage"></param> /// <param name="page"></param> /// <returns></returns> public IObservable <IssuesResult> Issues(int issuesPerPage = 250, int page = 1) { return(_stateService.GetAndFetchLatest(BlobCacheKeys.GetKeyForIssues(issuesPerPage, page), _weeklyXamarinApiService.WeeklyXamarinApi.Issues(), fetchPredicate: dateTimeOffset => FetchOnlyIfCloseOrAfterUsualPublishDate(dateTimeOffset), absoluteExpiration: RxApp.MainThreadScheduler.Now.AddDays(7))); }
public void SetsArtworkKey() { string key = BlobCacheKeys.GetKeyForArtwork(new byte[] { 0, 1 }); var song = new LocalSong("C://Bla", TimeSpan.Zero, key); Assert.Equal(key, song.ArtworkKey); }
public void SmokeTest() { const string artworkKey = BlobCacheKeys.Artwork + "mycoolhash"; string keyWithSize = BlobCacheKeys.GetArtworkKeyWithSize(artworkKey, 50); Assert.Equal(artworkKey + "-50x50", keyWithSize); }
public async Task NullSearchTermDefaultsToEmptyString() { var songs = new[] { new YoutubeSong("http://blabla", TimeSpan.Zero) }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForYoutubeCache(string.Empty), songs); var finder = new YoutubeSongFinder(cache); var result = await finder.GetSongsAsync(); Assert.Equal(1, result.Count); }
public async Task StoresArtworkInBlobCache() { var blobCache = new InMemoryBlobCache(); var artworkCache = new ArtworkCache(blobCache); var data = new byte[] { 0, 1 }; string key = BlobCacheKeys.GetKeyForArtwork(data); await artworkCache.Store(key, data); Assert.Equal(data, await blobCache.Get(key)); }
public async Task UsesCachedSongsIfAvailable() { const string searchTerm = "Foo"; var songs = new[] { new YoutubeSong("http://blabla", TimeSpan.Zero) }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForYoutubeCache(searchTerm), songs); var finder = new YoutubeSongFinder(cache); var result = await finder.GetSongsAsync(searchTerm); Assert.Equal(1, result.Count); }
public async Task NullSearchTermDefaultsToEmptyString() { var songs = new[] { new SoundCloudSong { IsStreamable = true, StreamUrl = new Uri("http://blabla.com"), PermaLinkUrl = new Uri("http://blabla") } }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForSoundCloudCache(string.Empty), songs); var finder = new SoundCloudSongFinder(cache); var result = await finder.GetSongsAsync(); Assert.Equal(1, result.Count); }
public async Task NotFoundRequestIsMarked() { var fetcher = Substitute.For <IArtworkFetcher>(); fetcher.RetrieveAsync(Arg.Any <string>(), Arg.Any <string>()).Returns(Task.FromResult <Uri>(null)); var blobCache = new InMemoryBlobCache(); var fixture = new ArtworkCache(blobCache, fetcher); string artist = "A"; string album = "B"; string lookupKey = BlobCacheKeys.GetKeyForOnlineArtwork(artist, album); await fixture.FetchOnline(artist, album); Assert.Equal("FAILED", await blobCache.GetObject <string>(lookupKey)); }
public async Task DoesntStoreArtworkIfAlreadyInLocalCache() { var blobCache = Substitute.For <IBlobCache>(); var artworkCache = new ArtworkCache(blobCache); var data = new byte[] { 0, 1 }; string key = BlobCacheKeys.GetKeyForArtwork(data); await artworkCache.Store(key, data); blobCache.GetCreatedAt(Arg.Any <string>()).Returns(Observable.Return(new DateTimeOffset?(DateTimeOffset.MaxValue))); await artworkCache.Store(key, data); blobCache.Received(1).Insert(Arg.Any <string>(), Arg.Any <byte[]>()); }
public async Task UsesCachedSongsIfAvailable() { const string searchTerm = "Foo"; var songs = new[] { new SoundCloudSong { IsStreamable = true, StreamUrl = new Uri("http://blabla.com"), PermaLinkUrl = new Uri("http://blabla") } }; var cache = new InMemoryBlobCache(); cache.InsertObject(BlobCacheKeys.GetKeyForSoundCloudCache(searchTerm), songs); var finder = new SoundCloudSongFinder(cache); var result = await finder.GetSongsAsync(searchTerm); Assert.Equal(1, result.Count); }
public async Task PullsSearchesFromCache() { string artist = "A"; string album = "B"; string key = BlobCacheKeys.GetKeyForOnlineArtwork(artist, album); var fetcher = Substitute.For <IArtworkFetcher>(); var blobCache = new InMemoryBlobCache(); await blobCache.InsertObject(key, "TestArtworkKey"); var fixture = new ArtworkCache(blobCache, fetcher); string returned = await fixture.FetchOnline(artist, album); Assert.Equal("TestArtworkKey", returned); fetcher.DidNotReceiveWithAnyArgs().RetrieveAsync(null, null); }
public void CanStoreMulipleArtworksIfArtworksExistsInCache() { var blobCache = new InMemoryBlobCache(); var data = new byte[] { 0, 1 }; string key = BlobCacheKeys.GetKeyForArtwork(data); blobCache.Insert(key, data); var fixture = new ArtworkCache(blobCache); Task firstTask = fixture.Store(key, data); Task secondTask = fixture.Store(key, data); Task thrirdTask = fixture.Store(key, data); Assert.True(firstTask.IsCompleted); Assert.True(secondTask.IsCompleted); Assert.True(thrirdTask.IsCompleted); }
public void SameKeysWaitOnFirstToFinish() { var signal = new AsyncSubject <Unit>(); var blobCache = Substitute.For <IBlobCache>(); blobCache.Insert(Arg.Any <string>(), Arg.Any <byte[]>(), Arg.Any <DateTimeOffset?>()).Returns(signal); var fixture = new ArtworkCache(blobCache); var data = new byte[] { 0, 1 }; string key = BlobCacheKeys.GetKeyForArtwork(data); Task firstTask = fixture.Store(key, data); Task secondTask = fixture.Store(key, data); Assert.False(firstTask.IsCompleted); Assert.False(secondTask.IsCompleted); signal.OnNext(Unit.Default); signal.OnCompleted(); Assert.True(firstTask.IsCompleted); Assert.True(secondTask.IsCompleted); }
public void SearchQueryKeyShouldBeExpected(string query, string expected) { var sut = BlobCacheKeys.GetKeyForSearch(query); sut.Should().Be(expected); }
private async Task UpdateSongsAsync(string path) { if (this.currentSongFinderSubscription != null) { this.currentSongFinderSubscription.Dispose(); this.currentSongFinderSubscription = null; } this.IsUpdating = true; await this.RemoveMissingSongsAsync(path); ILocalSongFinder songFinder = this.localSongFinderFunc(path); this.currentSongFinderSubscription = songFinder.GetSongsAsync() .ObserveOn(RxApp.TaskpoolScheduler) .Subscribe(t => { LocalSong song = t.Item1; this.songLock.EnterWriteLock(); bool added = this.songs.Add(song); LocalSong realSong; bool needsUpdate = false; if (added) { realSong = song; needsUpdate = true; } else { LocalSong existing = this.songs.First(x => x.OriginalPath == song.OriginalPath); if (existing.UpdateMetadataFrom(song)) { needsUpdate = true; } realSong = existing; } this.songLock.ExitWriteLock(); byte[] artworkData = t.Item2; if (artworkData != null) { string key = BlobCacheKeys.GetKeyForArtwork(artworkData); if (realSong.ArtworkKey != key) { ArtworkCache.Instance.Store(key, artworkData).ToObservable() .Subscribe(x => realSong.ArtworkKey = key); } } if (needsUpdate) { this.songsUpdated.OnNext(Unit.Default); } }, () => { this.Save(); this.StartOnlineArtworkLookup(); this.songLock.EnterReadLock(); int songCount = this.songs.Count; this.songLock.ExitReadLock(); AnalyticsClient.Instance.RecordLibrarySize(songCount); this.IsUpdating = false; }); }
public IObservable <DuckDuckGoSearchResult> Search(string query) { return(_stateService.GetOrFetch(BlobCacheKeys.GetKeyForSearch(query), async() => await _duckDuckGoApiService.UserInitiated.Search(query), absoluteExpiration: DateTime.UtcNow.AddDays(7))); }