protected AbstractSongFinder(IBlobCache requestCache) { if (requestCache == null) throw new ArgumentNullException("requestCache"); this._requestCache = requestCache; }
/// <summary> /// Creates a new instance of the <see cref="YoutubeSongFinder" /> class. /// </summary> /// <param name="requestCache"> /// A <see cref="IBlobCache" /> to cache the search requests. Requests with the same search /// term are considered the same. /// </param> public YoutubeSongFinder(IBlobCache requestCache) { if (requestCache == null) throw new ArgumentNullException("requestCache"); this.requestCache = requestCache; }
public BlogViewModel(string title, Uri feedAddress, IFeedService feedService = null, IBlobCache cache = null) { Title = title; FeedAddress = feedAddress; FeedService = feedService ?? Locator.Current.GetService<IFeedService>(); Cache = cache ?? Locator.Current.GetService<IBlobCache>(); Articles = new ReactiveList<ArticleViewModel>(); Refresh = ReactiveCommand.CreateAsyncObservable(x => GetAndFetchLatestArticles()); Refresh.Subscribe(articles => { // this could be done cleaner, send a PR. // Refresh.ToPropertyEx(this, x => x.Articles); Articles.Clear(); Articles.AddRange(articles); }); Refresh.ThrownExceptions.Subscribe(thrownException => { this.Log().Error(thrownException); }); _isLoading = Refresh.IsExecuting.ToProperty(this, x => x.IsLoading); // post-condition checks Condition.Ensures(FeedAddress).IsNotNull(); Condition.Ensures(FeedService).IsNotNull(); Condition.Ensures(Cache).IsNotNull(); }
public HDPApp(DeviceType deviceType, IBlobCache cache) { RxApp.DefaultExceptionHandler = Observer.Create ((Exception e) => { System.Diagnostics.Debug.WriteLine(e.Message); System.Diagnostics.Debug.WriteLine(e.StackTrace); }); BlobCache.ApplicationName = "HDP"; _cache = BlobCache.LocalMachine; JsonConvert.DefaultSettings = () => new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver(), Converters = {new MediaTypeConverter(), new StringEnumConverter()} }; _apiService = new ApiService (deviceType: deviceType); _newsService = new NewsService (_apiService); _eventsService = new EventsService (_apiService); _electionArticlesService = new ElectionArticlesService (_apiService); Locator.CurrentMutable.RegisterConstant (this, typeof(HDPApp)); State = new AppState (); UserCity.Subscribe (city => { System.Diagnostics.Debug.WriteLine("Current city is: {0}", city); }); _repository = new ContentRepository (_newsService, _electionArticlesService, _eventsService, cache); ImplementCommands (); }
public AvatarProvider(ISharedCache sharedCache, IImageCache imageCache) { cache = sharedCache.LocalMachine; this.imageCache = imageCache; DefaultUserBitmapImage = CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_user_avatar.png"); DefaultOrgBitmapImage = CreateBitmapImage("pack://application:,,,/GitHub.App;component/Images/default_org_avatar.png"); }
public ArtworkCache(IBlobCache cache = null, IArtworkFetcher artworkFetcher = null) { this.cache = cache ?? BlobCache.LocalMachine; this.artworkFetcher = artworkFetcher ?? new MusicBrainzArtworkFetcher(); this.queue = new OperationQueue(1); // Disk operations should be serialized this.storageSemaphore = new KeyedMemoizingSemaphore(); this.keyedMemoizingSemaphore = new KeyedMemoizingSemaphore(); }
static BlobCache() { if (RxApp.InUnitTestRunner()) { localMachine = new TestBlobCache(RxApp.TaskpoolScheduler); userAccount = new TestBlobCache(RxApp.TaskpoolScheduler); secure = new TestBlobCache(RxApp.TaskpoolScheduler); } }
public ServiceControl(IBlobCache cache, string url = null) { this.cache = cache; subject = new BehaviorSubject<Unit>(Unit.Default); isValid = new BehaviorSubject<bool>(false); IsValid = isValid.AsObservable(); UpdateUrl(url ?? "http://localhost:33333/api").Wait(); }
public IObservable<CacheIndex> Clear(IBlobCache cache, string indexKey, DateTimeOffset? absoluteExpiration = null) { OldKeys = Keys.ToList(); Keys.Clear(); UpdatedAt = DateTimeOffset.UtcNow; return cache .InvalidateObject<CacheIndex>(indexKey) .SelectMany(_ => cache.InsertObject(indexKey, this, absoluteExpiration)) .Select(_ => this); }
public IObservable<CacheIndex> AddAndSave(IBlobCache cache, string indexKey, CacheItem item, DateTimeOffset? absoluteExpiration = null) { var k = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", IndexKey, item.Key); if (!Keys.Contains(k)) Keys.Add(k); UpdatedAt = DateTimeOffset.UtcNow; return cache.InsertObject(IndexKey, this, absoluteExpiration) .Select(x => this); }
public AkavacheToSqlite3Migration(IBlobCache oldBlobCache, IBlobCache newBlobCache) { if (oldBlobCache == null) throw new ArgumentNullException("oldBlobCache"); if (newBlobCache == null) throw new ArgumentNullException("newBlobCache"); this.oldBlobCache = oldBlobCache; this.newBlobCache = newBlobCache; }
/// <summary> /// This method attempts to returned a cached value, while /// simultaneously calling a Func to return the latest value. When the /// latest data comes back, it replaces what was previously in the /// cache. /// /// This method is best suited for loading dynamic data from the /// Internet, while still showing the user earlier data. /// /// This method returns an IObservable that may return *two* results /// (first the cached data, then the latest data). Therefore, it's /// important for UI applications that in your Subscribe method, you /// write the code to merge the second result when it comes in. /// /// This also means that awaiting this method is a Bad Idea(tm), always /// use Subscribe. /// </summary> /// <typeparam name="T">The type of item to get.</typeparam> /// <param name="blobCache">The cache to get the item.</param> /// <param name="key">The key to store the returned result under.</param> /// <param name="fetchFunc">A method that will fetch the task.</param> /// <param name="fetchPredicate">An optional Func to determine whether /// the updated item should be fetched. If the cached version isn't found, /// this parameter is ignored and the item is always fetched.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <param name="shouldInvalidateOnError">If this is true, the cache will /// be cleared when an exception occurs in fetchFunc.</param> /// <param name="cacheValidationPredicate">An optional Func to determine /// if the fetched value should be cached.</param> /// <returns>An Observable stream containing either one or two /// results (possibly a cached version, then the latest version).</returns> public static IObservable <T> GetAndFetchLatest <T>( this IBlobCache blobCache, string key, Func <Task <T> > fetchFunc, Func <DateTimeOffset, bool> fetchPredicate = null, DateTimeOffset?absoluteExpiration = null, bool shouldInvalidateOnError = false, Func <T, bool> cacheValidationPredicate = null) { return(blobCache.GetAndFetchLatest(key, () => fetchFunc().ToObservable(), fetchPredicate, absoluteExpiration, shouldInvalidateOnError, cacheValidationPredicate)); }
/// <summary> /// Insert an object into the cache, via the JSON serializer. /// </summary> /// <typeparam name="T">The type of item.</typeparam> /// <param name="blobCache">The cache to insert the item.</param> /// <param name="key">The key to associate with the object.</param> /// <param name="value">The object to serialize.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>An observable which signals when the insertion has completed.</returns> public static IObservable <Unit> InsertObject <T>(this IBlobCache blobCache, string key, T value, DateTimeOffset?absoluteExpiration = null) { if (blobCache is IObjectBlobCache objCache) { return(objCache.InsertObject(key, value, absoluteExpiration)); } var bytes = SerializeObject(value); return(blobCache.Insert(GetTypePrefixedKey(key, typeof(T)), bytes, absoluteExpiration)); }
/// <summary> /// Attempt to return an object from the cache. If the item doesn't /// exist or returns an error, call a Func to return the latest /// version of an object and insert the result in the cache. /// /// For most Internet applications, this method is the best method to /// call to fetch static data (i.e. images) from the network. /// </summary> /// <param name="key">The key to associate with the object.</param> /// <param name="fetchFunc">A Func which will asynchronously return /// the latest value for the object should the cache not contain the /// key. /// /// Observable.Start is the most straightforward way (though not the /// most efficient!) to implement this Func.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>A Future result representing the deserialized object from /// the cache.</returns> public static IObservable <T> GetOrFetchObject <T>(this IBlobCache This, string key, Func <IObservable <T> > fetchFunc, DateTimeOffset?absoluteExpiration = null) { return(This.GetObjectAsync <T>(key).Catch <T, Exception>(_ => { object dontcare; return ((IObservable <T>)inflightFetchRequests.GetOrAdd(key, __ => (object)fetchFunc())) .Do(x => This.InsertObject(key, x, absoluteExpiration)) .Finally(() => inflightFetchRequests.TryRemove(key, out dontcare)) .Multicast(new AsyncSubject <T>()).RefCount(); })); }
/// <summary> /// Returns the time that the key was added to the cache, or returns /// null if the key isn't in the cache. /// </summary> /// <param name="key">The key to return the date for.</param> /// <returns>The date the key was created on.</returns> public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache This, string key) { var objCache = This as IObjectBlobCache; if (objCache != null) { return(objCache.GetObjectCreatedAt <T>(key)); } return(This.GetCreatedAt(GetTypePrefixedKey(key, typeof(T)))); }
static BlobCache() { if (RxApp.InUnitTestRunner()) { localMachine = new TestBlobCache(RxApp.TaskpoolScheduler); userAccount = new TestBlobCache(RxApp.TaskpoolScheduler); #if !SILVERLIGHT secure = new TestBlobCache(RxApp.TaskpoolScheduler); #endif } }
/// <summary> /// A combination of DownloadUrl and LoadImage, this method fetches an /// image from a remote URL (using the cached value if possible) and /// returns the image. /// </summary> /// <param name="blobCache">The blob cache to load the image from if available.</param> /// <param name="key">The key to store with.</param> /// <param name="url">The URL to download.</param> /// <param name="fetchAlways">If we should always fetch the image from the URL even if we have one in the blob.</param> /// <param name="desiredWidth">Optional desired width, if not specified will be the default size.</param> /// <param name="desiredHeight">Optional desired height, if not specified will be the default size.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>A Future result representing the bitmap image. blobCache /// Observable is guaranteed to be returned on the UI thread.</returns> public static IObservable <IBitmap> LoadImageFromUrl(this IBlobCache blobCache, string key, string url, bool fetchAlways = false, float?desiredWidth = null, float?desiredHeight = null, DateTimeOffset?absoluteExpiration = null) { if (blobCache is null) { throw new ArgumentNullException(nameof(blobCache)); } return(blobCache.DownloadUrl(key, url, null, fetchAlways, absoluteExpiration) .SelectMany(ThrowOnBadImageBuffer) .SelectMany(x => BytesToImage(x, desiredWidth, desiredHeight))); }
static ModelService CreateTarget( IApiClient apiClient = null, Octokit.IConnection graphql = null, IBlobCache hostCache = null, IAvatarProvider avatarProvider = null) { return(new ModelService( apiClient ?? Substitute.For <IApiClient>(), hostCache ?? new InMemoryBlobCache(), Substitute.For <IAvatarProvider>())); }
/// <summary> /// Get an object from the cache and deserialize it via the JSON /// serializer. /// </summary> /// <param name="key">The key to look up in the cache.</param> /// <param name="noTypePrefix">Use the exact key name instead of a /// modified key name. If this is true, GetAllObjects will not find this object.</param> /// <returns>A Future result representing the object in the cache.</returns> public static IObservable <T> GetObject <T>(this IBlobCache This, string key) { var objCache = This as IObjectBlobCache; if (objCache != null) { return(objCache.GetObject <T>(key)); } return(This.Get(GetTypePrefixedKey(key, typeof(T))).SelectMany(DeserializeObject <T>)); }
/// <summary> /// Invalidates a single object from the cache. It is important that the Type /// Parameter for this method be correct, and you cannot use /// IBlobCache.Invalidate to perform the same task. /// </summary> /// <param name="key">The key to invalidate.</param> public static IObservable <Unit> InvalidateObject <T>(this IBlobCache This, string key) { var objCache = This as IObjectBlobCache; if (objCache != null) { return(objCache.InvalidateObject <T>(key)); } return(This.Invalidate(GetTypePrefixedKey(key, typeof(T)))); }
//These methods are the ones we call from courseViewModel and ChapterViewModel public async Task <List <ChapterLevel> > FetchChapterLevels(string id) { Cache = BlobCache.LocalMachine; List <Chapter> getChaptersTask = await GetChaptersAsync(id); List <ChapterLevel> chapterLevels = FetchSortedLevels(getChaptersTask); await Cache.InsertObject("chapters", chapterLevels, DateTimeOffset.Now.AddHours(2)); List <ChapterLevel> chapters = await Cache.GetObject <List <ChapterLevel> >("chapters"); return(chapters); }
public async Task <List <Course> > FetchCourses() { //Using the Akavache nuget we can store data from GetCoursesAsync() in our localMachine using a keyword "courses" //The offset method tells the cache how long we want the data to remain inside the cache //This method is different from FetchChapters and FetchPages because we run it when the app is loading in the start //Making the loading of courses much faster Cache = BlobCache.LocalMachine; IOnlineStepApi __onlineStepApi = RestService.For <IOnlineStepApi>("https://online-step.herokuapp.com"); List <Course> Courses = await __onlineStepApi.GetCourses(); return(Courses); }
public MainViewModel(INavService navService, IBlobCache cache, IAnalyticsService analyticsService) : base(navService, analyticsService) { _cache = cache; PinsCommand = new Command <ObservableRangeCollection <PlugEVMeEntry> >(async(entries) => await ExecutePinsCommand(entries)); ViewCommand = new Command <PlugEVMeEntry>(async(entry) => await ExecuteViewCommand(entry)); NewCommand = new Command(async() => await ExecuteNewCommand()); RefreshCommand = new AsyncCommand(async() => await LoadEntries()); }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. The URL itself is used as the key. /// </summary> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public IObservable<byte[]> DownloadUrl(IBlobCache This, string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null) { var doFetch = new Func<KeyNotFoundException, IObservable<byte[]>>(_ => inflightWebRequests.GetOrAdd(url, __ => Observable.Defer(() => { return MakeWebRequest(new Uri(url), headers) .SelectMany(x => ProcessAndCacheWebResponse(x, url, This, absoluteExpiration)); }).Multicast(new AsyncSubject<byte[]>()).RefCount())); IObservable<byte[]> dontcare; var ret = fetchAlways ? doFetch(null) : This.GetAsync(url).Catch(doFetch); return ret.Finally(() => inflightWebRequests.TryRemove(url, out dontcare)); }
static IObservable <T> GetAndFetchLatestFromIndex <T>(this IBlobCache This, string key, Func <IObservable <T> > fetchFunc, Action <T> removedItemsCallback, Func <DateTimeOffset, bool> fetchPredicate = null, DateTimeOffset?absoluteExpiration = null, bool shouldInvalidateOnError = false) where T : CacheItem { var idx = Observable.Defer(() => This.GetOrCreateObject(key, () => CacheIndex.Create(key))).Replay().RefCount(); var fetch = idx .Select(x => Tuple.Create(x, fetchPredicate == null || !x.Keys.Any() || fetchPredicate(x.UpdatedAt))) .Where(predicateIsTrue => predicateIsTrue.Item2) .Select(x => x.Item1) .Select(index => index.Clear()) .SelectMany(index => fetchFunc() .Catch <T, Exception>(ex => { var shouldInvalidate = shouldInvalidateOnError ? This.InvalidateObject <CacheIndex>(key) : Observable.Return(Unit.Default); return(shouldInvalidate.SelectMany(__ => Observable.Throw <T>(ex))); }) .SelectMany(x => x.Save <T>(This, key, absoluteExpiration)) .Do(x => index.Add(key, x)) ); var cache = idx .SelectMany(index => This.GetObjects <T>(index.Keys.ToList())) .SelectMany(dict => dict.Values); return(cache.Merge(fetch) .Finally(async() => { var index = await idx; await index.Save(This); var list = index.OldKeys.Except(index.Keys); if (!list.Any()) { return; } var removed = await This.GetObjects <T>(list); foreach (var d in removed.Values) { removedItemsCallback(d); } await This.InvalidateObjects <T>(list); }) .Replay().RefCount()); }
public ContentRepository ( NewsService newsService, ElectionArticlesService electionArticlesService, EventsService eventsService, IBlobCache cache) { _news = newsService; _electionArticles = electionArticlesService; _events = eventsService; _cache = cache; }
/// <summary> /// Get an object from the cache and deserialize it via the JSON /// serializer. /// </summary> /// <param name="key">The key to look up in the cache.</param> /// <param name="noTypePrefix">Use the exact key name instead of a /// modified key name. If this is true, GetAllObjects will not find this object.</param> /// <returns>A Future result representing the object in the cache.</returns> public static IObservable <T> GetObjectAsync <T>(this IBlobCache This, string key, bool noTypePrefix = false) { var objCache = This as IObjectBlobCache; if (objCache != null) { return(objCache.GetObjectAsync <T>(key, noTypePrefix)); } var theKey = noTypePrefix ? key : GetTypePrefixedKey(key, typeof(T)); return(This.GetAsync(theKey).SelectMany(DeserializeObject <T>)); }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. The URL itself is used as the key. /// </summary> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public IObservable <byte[]> DownloadUrl(IBlobCache This, string url, IDictionary <string, string> headers = null, bool fetchAlways = false, DateTimeOffset?absoluteExpiration = null) { var doFetch = new Func <IObservable <byte[]> >(() => MakeWebRequest(new Uri(url), headers).ToObservable()); if (fetchAlways) { return(This.GetAndFetchLatest(url, doFetch, absoluteExpiration: absoluteExpiration).TakeLast(1)); } else { return(This.GetOrFetchObject(url, doFetch, absoluteExpiration)); } }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. The URL itself is used as the key. /// </summary> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public static IObservable <byte[]> DownloadUrl(this IBlobCache This, string url, Dictionary <string, string> headers = null, bool fetchAlways = false, DateTimeOffset?absoluteExpiration = null) { var doFetch = new Func <KeyNotFoundException, IObservable <byte[]> >(_ => inflightWebRequests.GetOrAdd(url, __ => Observable.Defer(() => { return(MakeWebRequest(new Uri(url), headers) .SelectMany(x => ProcessAndCacheWebResponse(x, url, This, absoluteExpiration))); }).Multicast(new AsyncSubject <byte[]>()).RefCount())); IObservable <byte[]> dontcare; var ret = fetchAlways ? doFetch(null) : This.GetAsync(url).Catch(doFetch); return(ret.Finally(() => inflightWebRequests.TryRemove(url, out dontcare))); }
public IObservable <T> Save <T>(IBlobCache cache, string key, DateTimeOffset?absoluteExpiration = null) where T : CacheItem { Guard.ArgumentNotNull(cache, nameof(cache)); Guard.ArgumentNotEmptyString(key, nameof(key)); var k = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", key, Key); return(cache .InvalidateObject <T>(k) .Select(_ => cache.InsertObject(k, this, absoluteExpiration)) .Select(_ => this as T)); }
/// <summary> /// Initializes a new instance of the <see cref="SettingsStorage"/> class. /// </summary> /// <param name="keyPrefix"> /// This value will be used as prefix for all settings keys. It should be reasonably unique, /// so that it doesn't collide with other keys in the same <see cref="IBlobCache"/>. /// </param> /// <param name="cache"> /// An <see cref="IBlobCache"/> implementation where you want your settings to be stored. /// </param> protected SettingsStorage(string keyPrefix, IBlobCache cache) { if (string.IsNullOrWhiteSpace(keyPrefix)) { throw new ArgumentException("Invalid key prefix", nameof(keyPrefix)); } this.keyPrefix = keyPrefix; this.blobCache = cache ?? throw new ArgumentNullException(nameof(cache)); this.cache = new Dictionary <string, object>(); this.cacheLock = new ReaderWriterLockSlim(); }
public Task Initialize(string dbLocation) { var t = Task.Run(() => { cache = new SqlRawPersistentBlobCache(dbLocation) { ForcedDateTimeKind = DateTimeKind.Utc }; }); t.ConfigureAwait(false); return(t); }
public static IObservable <Unit> InsertObjects <T>(this IBlobCache This, IDictionary <string, T> keyValuePairs, DateTimeOffset?absoluteExpiration = null) { var bulkCache = This as IObjectBulkBlobCache; if (bulkCache != null) { return(bulkCache.InsertObjects(keyValuePairs, absoluteExpiration)); } return(keyValuePairs.ToObservable() .SelectMany(x => This.InsertObject(x.Key, x.Value)) .TakeLast(1)); }
public static IObservable <Unit> Invalidate(this IBlobCache This, IEnumerable <string> keys) { var bulkCache = This as IBulkBlobCache; if (bulkCache != null) { return(bulkCache.Invalidate(keys)); } return(keys.ToObservable() .SelectMany(x => This.Invalidate(x)) .TakeLast(1)); }
public IObservable <CacheIndex> AddAndSave(IBlobCache cache, string indexKey, CacheItem item, DateTimeOffset?absoluteExpiration = null) { var k = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", IndexKey, item.Key); if (!Keys.Contains(k)) { Keys.Add(k); } UpdatedAt = DateTimeOffset.UtcNow; return(cache.InsertObject(IndexKey, this, absoluteExpiration) .Select(x => this)); }
/// <summary> /// Insert an object into the cache, via the JSON serializer. /// </summary> /// <param name="key">The key to associate with the object.</param> /// <param name="value">The object to serialize.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> public static IObservable <Unit> InsertObject <T>(this IBlobCache This, string key, T value, DateTimeOffset?absoluteExpiration = null) { var objCache = This as IObjectBlobCache; if (objCache != null) { return(objCache.InsertObject(key, value, absoluteExpiration)); } var bytes = SerializeObject(value); return(This.Insert(key, bytes, absoluteExpiration)); }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. The URL itself is used as the key. /// </summary> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public IObservable<byte[]> DownloadUrl(IBlobCache This, string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null) { var doFetch = new Func<IObservable<byte[]>>(() => MakeWebRequest(new Uri(url), headers).ToObservable()); if (fetchAlways) { return This.GetAndFetchLatest(url, doFetch, absoluteExpiration: absoluteExpiration).TakeLast(1); } else { return This.GetOrFetchObject(url, doFetch, absoluteExpiration); } }
/// <summary> /// Returns the time that the key was added to the cache, or returns /// null if the key isn't in the cache. /// </summary> /// <typeparam name="T">The type of item to get.</typeparam> /// <param name="blobCache">The cache to get the item.</param> /// <param name="key">The key to return the date for.</param> /// <returns>The date the key was created on.</returns> public static IObservable <DateTimeOffset?> GetObjectCreatedAt <T>(this IBlobCache blobCache, string key) { if (blobCache is null) { throw new ArgumentNullException(nameof(blobCache)); } if (blobCache is IObjectBlobCache objCache) { return(objCache.GetObjectCreatedAt <T>(key)); } return(blobCache.GetCreatedAt(GetTypePrefixedKey(key, typeof(T)))); }
/// <summary> /// Gets a dictionary filled with the specified keys with their corresponding values. /// </summary> /// <typeparam name="T">The type of item to get.</typeparam> /// <param name="blobCache">The blob cache to extract the values from.</param> /// <param name="keys">The keys to get the values for.</param> /// <returns>A observable with the specified values.</returns> public static IObservable <IDictionary <string, T> > GetObjects <T>(this IBlobCache blobCache, IEnumerable <string> keys) { if (blobCache is IObjectBulkBlobCache bulkCache) { return(bulkCache.GetObjects <T>(keys)); } return(keys.ToObservable() .SelectMany(x => blobCache.GetObject <T>(x) .Where(y => y is not null) .Select(y => new KeyValuePair <string, T>(x, y !)) .Catch <KeyValuePair <string, T>, KeyNotFoundException>(_ => Observable.Empty <KeyValuePair <string, T> >())) .ToDictionary(k => k.Key, v => v.Value)); }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. The URL itself is used as the key. /// </summary> /// <param name="blobCache">The blob cache associated with the action.</param> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public IObservable <byte[]> DownloadUrl(IBlobCache blobCache, Uri url, IDictionary <string, string> headers = null, bool fetchAlways = false, DateTimeOffset?absoluteExpiration = null) { if (blobCache is null) { throw new ArgumentNullException(nameof(blobCache)); } if (url is null) { throw new ArgumentNullException(nameof(url)); } return(blobCache.DownloadUrl(url.ToString(), url, headers, fetchAlways, absoluteExpiration)); }
/// <summary> /// Return all objects of a specific Type in the cache. /// </summary> /// <returns>A Future result representing all objects in the cache /// with the specified Type.</returns> public static IObservable <IEnumerable <T> > GetAllObjects <T>(this IBlobCache This) { // NB: This isn't exactly thread-safe, but it's Close Enough(tm) // We make up for the fact that the keys could get kicked out // from under us via the Catch below var matchingKeys = This.GetAllKeys() .Where(x => x.StartsWith(GetTypePrefixedKey("", typeof(T)))) .ToArray(); return(matchingKeys.ToObservable() .SelectMany(x => This.GetObjectAsync <T>(x, true).Catch(Observable.Empty <T>())) .ToList() .Select(x => (IEnumerable <T>)x)); }
/// <summary> /// Invalidates a single object from the cache. It is important that the Type /// Parameter for this method be correct, and you cannot use /// IBlobCache.Invalidate to perform the same task. /// </summary> /// <typeparam name="T">The type of item to invalidate.</typeparam> /// <param name="blobCache">The cache to invalidate.</param> /// <param name="key">The key to invalidate.</param> /// <returns>An observable that signals when the operation has completed.</returns> public static IObservable <Unit> InvalidateObject <T>(this IBlobCache blobCache, string key) { if (blobCache is null) { throw new ArgumentNullException(nameof(blobCache)); } if (blobCache is IObjectBlobCache objCache) { return(objCache.InvalidateObject <T>(key)); } return(blobCache.Invalidate(GetTypePrefixedKey(key, typeof(T)))); }
/// <summary> /// Get an object from the cache and deserialize it via the JSON /// serializer. /// </summary> /// <typeparam name="T">The type of item.</typeparam> /// <param name="blobCache">The cache to get the item.</param> /// <param name="key">The key to look up in the cache /// modified key name. If this is true, GetAllObjects will not find this object.</param> /// <returns>A Future result representing the object in the cache.</returns> public static IObservable <T?> GetObject <T>(this IBlobCache blobCache, string key) { if (blobCache is null) { throw new ArgumentNullException(nameof(blobCache)); } if (blobCache is IObjectBlobCache objCache) { return(objCache.GetObject <T>(key)); } return(blobCache.Get(GetTypePrefixedKey(key, typeof(T))).SelectMany(DeserializeObject <T>)); }
public CachedRestClient() { _headers = new Dictionary <string, string>(); _cancelTokenSource = new CancellationTokenSource(); _cancelToken = CancellationToken.None; _parentToken = CancellationToken.None; Locator.CurrentMutable.Register(() => Scheduler.Default, typeof(IScheduler), "Taskpool"); Locator.CurrentMutable.Register(() => new FilesystemProvider(), typeof(IFilesystemProvider), null); Locator.CurrentMutable.Register(() => new HttpMixin(), typeof(IAkavacheHttpMixin), null); //new Akavache.Sqlite3.Registrations().Register(Locator.CurrentMutable); _blobCache = new SQLitePersistentBlobCache("cache.db"); }
public static IObservable<CacheIndex> AddAndSaveToIndex(IBlobCache cache, string indexKey, CacheItem item, DateTimeOffset? absoluteExpiration = null) { return cache.GetOrCreateObject(indexKey, () => Create(indexKey)) .Do(index => { var k = string.Format(CultureInfo.InvariantCulture, "{0}|{1}", index.IndexKey, item.Key); if (!index.Keys.Contains(k)) index.Keys.Add(k); index.UpdatedAt = DateTimeOffset.UtcNow; }) .SelectMany(index => cache.InsertObject(index.IndexKey, index, absoluteExpiration) .Select(x => index)); }
public AkavacheStorageService( Lazy <IFilesystemProvider> fileSystemProvider, IScheduler scheduler, string dbFileName = "blobs.db", IBlobCache blobCache = null) { _dbFileName = dbFileName; _fileSystemProvider = _fileSystemProvider ?? Locator.Current.GetLazyLocator <IFilesystemProvider>(); _previousCache = new SerialDisposable(); _scheduler = scheduler; _blobCache = blobCache; SetupNewCache(); }
public FeedsViewModel(IBlobCache cache = null) { Cache = cache ?? Locator.Current.GetService<IBlobCache>(); Cache.GetOrCreateObject(BlobCacheKeys.Blogs, () => new ReactiveList<BlogViewModel>()) .Subscribe(blogs => { Blogs = blogs; }); RefreshAll = ReactiveCommand.CreateAsyncTask(x => { foreach (var blog in Blogs) { blog.Refresh.InvokeCommand(null); } return Task.FromResult(Unit.Default); }); RefreshAll.ThrownExceptions.Subscribe(thrownException => { this.Log().Error(thrownException); }); _isLoading = RefreshAll.IsExecuting.ToProperty(this, x => x.IsLoading); PersistData = ReactiveCommand.CreateAsyncTask(async x => { await Cache.InsertObject(BlobCacheKeys.Blogs, Blogs); }); PersistData.ThrownExceptions.Subscribe(thrownException => { this.Log().Error(thrownException); }); // behaviours // when a blog is added or removed, wait for 5 seconds of inactivity before persisting the data as the user may be doing bulk [add|remove] operations. this.WhenAnyValue(viewModel => viewModel.Blogs) .Throttle(TimeSpan.FromSeconds(5), RxApp.MainThreadScheduler) .InvokeCommand(this, viewModel => viewModel.PersistData); // When an user adds a new blog to the feed, automatically fetch/cache the contents of the blog. // When a blog becomes the selected blog, fetch/cache the contents of the blog. this.WhenAnyObservable(viewModel => viewModel.Blogs.ItemsAdded) .Merge(this.WhenAnyValue(viewModel => viewModel.SelectedBlog).Where(blogVm => blogVm != null)) .Subscribe(x => x.Refresh.InvokeCommand(null)); // post-condition checks Condition.Ensures(Cache).IsNotNull(); Condition.Ensures(RefreshAll).IsNotNull(); Condition.Ensures(PersistData).IsNotNull(); }
protected SharedCache(IBlobCache userAccountCache, IBlobCache localMachineCache, ISecureBlobCache secureCache) { if (secureCache == null) { try { BlobCache.Secure = new CredentialCache(); secureCache = BlobCache.Secure; } catch (Exception e) { log.Error("Failed to set up secure cache.", e); secureCache = new InMemoryBlobCache(); } } UserAccount = userAccountCache ?? GetBlobCacheWithFallback(() => BlobCache.UserAccount, "UserAccount"); LocalMachine = localMachineCache ?? GetBlobCacheWithFallback(() => BlobCache.LocalMachine, "LocalMachine"); Secure = secureCache; }
/// <summary> /// Download data from an HTTP URL and insert the result into the /// cache. If the data is already in the cache, this returns /// a cached value. An explicit key is provided rather than the URL itself. /// </summary> /// <param name="key">The key to store with.</param> /// <param name="url">The URL to download.</param> /// <param name="headers">An optional Dictionary containing the HTTP /// request headers.</param> /// <param name="fetchAlways">Force a web request to always be issued, skipping the cache.</param> /// <param name="absoluteExpiration">An optional expiration date.</param> /// <returns>The data downloaded from the URL.</returns> public IObservable<byte[]> DownloadUrl(IBlobCache This, string key, string url, IDictionary<string, string> headers = null, bool fetchAlways = false, DateTimeOffset? absoluteExpiration = null) { var doFetch = MakeWebRequest(new Uri(url), headers).SelectMany(x => ProcessWebResponse(x, url, absoluteExpiration)); var fetchAndCache = doFetch.SelectMany(x => This.Insert(key, x, absoluteExpiration).Select(_ => x)); var ret = default(IObservable<byte[]>); if (!fetchAlways) { ret = This.Get(key).Catch(fetchAndCache); } else { ret = fetchAndCache; } var conn = ret.PublishLast(); conn.Connect(); return conn; }
public static async Task<List<string>> GenerateDatabase(IBlobCache targetCache, int size) { var ret = new List<string>(); // Write out in groups of 4096 while (size > 0) { var toWriteSize = Math.Min(4096, size); var toWrite = GenerateRandomDatabaseContents(toWriteSize); await targetCache.Insert(toWrite); foreach (var k in toWrite.Keys) ret.Add(k); size -= toWrite.Count; Console.WriteLine(size); } return ret; }
public PlayApi(IRestClient authedClient, [Named("LocalMachine")] IBlobCache blobCache) { client = authedClient; cache = blobCache; }
public MainViewModel (INavService navService, ITripLogDataService tripLogDataService, IBlobCache cache) : base(navService) { this.tripLogDataService = tripLogDataService; this.cache = cache; LogEntries = new ObservableCollection<TripLogEntry> (); }
public async Task ReadFromStorage(IBlobCache storage) { ApiKey = await storage.GetOrCreateObject("ApiKey", () => ""); AuthUser = await storage.GetOrCreateObject("AuthUser", () => ""); AuthPass = await storage.GetOrCreateObject("AuthPass", () => ""); Endpoint = await storage.GetOrCreateObject("Endpoint", () => "https://staging.vpdb.io/api"); PbxFolder = await storage.GetOrCreateObject("PbxFolder", () => ""); SyncStarred = await storage.GetOrCreateObject("SyncStarred", () => true); MinimizeToTray = await storage.GetOrCreateObject("MinimizeToTray", () => false); StartWithWindows = await storage.GetOrCreateObject("StartWithWindows", () => false); ReformatXml = await storage.GetOrCreateObject("ReformatXml", () => false); XmlFile = await storage.GetOrCreateObject("XmlFile", () => new Dictionary<Platform.PlatformType, string> {{ Platform.PlatformType.VP, "Visual Pinball" }}); DownloadOnStartup = await storage.GetOrCreateObject("DownloadOnStartup", () => false); PatchTableScripts = await storage.GetOrCreateObject("PatchTableScripts", () => true); DownloadOrientation = await storage.GetOrCreateObject("DownloadOrientation", () => SettingsManager.Orientation.Portrait); DownloadOrientationFallback = await storage.GetOrCreateObject("DownloadOrientationFallback", () => SettingsManager.Orientation.Same); DownloadLighting = await storage.GetOrCreateObject("DownloadLighting", () => SettingsManager.Lighting.Day); DownloadLightingFallback = await storage.GetOrCreateObject("DownloadLightingFallback", () => SettingsManager.Lighting.Any); WindowPosition = await storage.GetOrCreateObject("WindowPosition", () => new Position()); IsFirstRun = await storage.GetOrCreateObject("IsFirstRun", () => true); }
public TestSettings(IBlobCache blobCache) : base("#Settings#", blobCache) { }
public async Task WriteToStorage(IBlobCache storage) { await storage.InsertObject("ApiKey", ApiKey); await storage.InsertObject("AuthUser", AuthUser); await storage.InsertObject("AuthPass", AuthPass); await storage.InsertObject("Endpoint", Endpoint); await storage.InsertObject("PbxFolder", PbxFolder); await storage.InsertObject("SyncStarred", SyncStarred); await storage.InsertObject("MinimizeToTray", MinimizeToTray); await storage.InsertObject("StartWithWindows", StartWithWindows); await storage.InsertObject("ReformatXml", ReformatXml); await storage.InsertObject("XmlFile", XmlFile); await storage.InsertObject("DownloadOnStartup", DownloadOnStartup); await storage.InsertObject("PatchTableScripts", PatchTableScripts); await storage.InsertObject("DownloadOrientation", DownloadOrientation); await storage.InsertObject("DownloadOrientationFallback", DownloadOrientationFallback); await storage.InsertObject("DownloadLighting", DownloadLighting); await storage.InsertObject("DownloadLightingFallback", DownloadLightingFallback); await storage.InsertObject("IsFirstRun", false); IsFirstRun = false; }
public IObservable<CacheIndex> Save(IBlobCache cache, DateTimeOffset? absoluteExpiration = null) { return cache.InsertObject(IndexKey, this, absoluteExpiration) .Select(x => this); }
public async Task WriteInternalToStorage(IBlobCache storage) { await storage.InsertObject("WindowPosition", WindowPosition); }
private async Task VacuumIfNeeded(IBlobCache x, TimeSpan timeAgo) { var lastVacuum = await x.GetOrCreateObject(vacuumKey, () => new DateTime()); if (lastVacuum > DateTime.UtcNow.Subtract(timeAgo)) return; await Vacuum(x); }
private static async Task Vacuum(IBlobCache x) { await x.Vacuum(); await x.InsertObject(vacuumKey, DateTime.UtcNow); }
public void RegisterCache(IBlobCache cache) { lock (_caches) _caches.Add(cache); }