Created
April 10, 2017 00:49
-
-
Save jakkaj/71192cbbf4fc05a7fe1e21e3a5df7119 to your computer and use it in GitHub Desktop.
CachingService which will check a local cache before making a call to original data service
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Text; | |
using System.Threading.Tasks; | |
using System.Xml; | |
using Arlo.SDK.Contract; | |
using Arlo.SDK.Entities.Base; | |
using Arlo.SDK.Entities.Product; | |
using Arlo.SDK.Entities.System; | |
using Arlo.SDK.Util; | |
using Autofac; | |
using Xamling.Azure.Portable.Contract.Cache; | |
using XamlingCore.Portable.Contract.Entities; | |
using XamlingCore.Portable.Contract.Helpers; | |
using XamlingCore.Portable.Util.TaskUtils; | |
namespace Arlo.SDK.Services.System | |
{ | |
public class CachingService : ICachingService | |
{ | |
private readonly IRedisEntityCache _entityCache; | |
public ILifetimeScope Scope { get; set; } | |
public IHashHelper HashHelper { get; set; } | |
public CachingService(IRedisEntityCache entityCache) | |
{ | |
_entityCache = entityCache; | |
} | |
public async Task SetEntity<T>(string key, T entity, TimeSpan? ts = null) | |
where T:class, new() | |
{ | |
await _entityCache.SetEntity(key, entity, ts ?? Constants.Cache.DefaultTimespan); | |
} | |
public async Task<T> GetEntity<T>(string key) | |
where T : class, new() | |
{ | |
return await _entityCache.GetEntity<T>(key); | |
} | |
public async Task<T> GetEntity<T>(string key, Func<Task<T>> sourceTask, TimeSpan? ts = null, bool forceRefresh = false) | |
where T : class, new() | |
{ | |
if (forceRefresh) | |
{ | |
var result = await sourceTask(); | |
await SetEntity(key, result, ts ?? Constants.Cache.DefaultTimespan); | |
return result; | |
} | |
return await _entityCache.GetEntity<T>(key, sourceTask, ts ?? Constants.Cache.DefaultTimespan); | |
} | |
/// <summary> | |
/// Tries the cache before loading | |
/// </summary> | |
/// <typeparam name="T"></typeparam> | |
/// <param name="key"></param> | |
/// <param name="url"></param> | |
/// <returns></returns> | |
public async Task<T> LoadEntity<T>(string key, string url, bool forceRefresh = false, TimeSpan? ts = null) | |
where T: class, new() | |
{ | |
var eRepo = Scope.Resolve<IGenericWebRepo<T>>(); | |
if (forceRefresh) | |
{ | |
return await eRepo.Get(url); | |
} | |
return await GetEntity(key, () => eRepo.Get(url), ts); | |
} | |
public async Task<List<T>> LoadLinkEntitiesFromList<T, TLinks>(List<TLinks> links, string key, string rel, bool forceRefresh) | |
where T : class, new() | |
where TLinks : ListOfLinks | |
{ | |
if (links == null) | |
{ | |
return null; | |
} | |
key += _getHashLinksLinks(links); | |
var cacheResult = await GetEntity<List<T>>(key); | |
if (cacheResult != null && !forceRefresh) | |
{ | |
return cacheResult; | |
} | |
var resultTasks = new List<Task<List<T>>>(); | |
foreach (var lol in links) | |
{ | |
if (lol == null) | |
{ | |
continue; | |
} | |
resultTasks.Add(TaskThrottler.Get("LoadLinkEntitiesFromList", 15).Throttle(() => LoadLinkEntities<T>(lol, Guid.NewGuid().ToString(), rel, forceRefresh))); | |
} | |
var resultFromTasks = await Task.WhenAll(resultTasks); | |
var listResult = resultFromTasks.ToList(); | |
var result = new List<T>(); | |
foreach (var l in listResult) | |
{ | |
result.AddRange(l); | |
} | |
await SetEntity(key, result); | |
return result; | |
} | |
public async Task<List<T>> LoadLinkEntities<T>(ListOfLinks links, string key, string rel, bool forceRefresh) | |
where T : class, new() | |
{ | |
if (links == null) | |
{ | |
return null; | |
} | |
key += _getHashLinks(links); | |
var cacheResult = await GetEntity<List<T>>(key); | |
if (cacheResult != null && !forceRefresh) | |
{ | |
return cacheResult; | |
} | |
var repo = Scope.Resolve<IGenericWebRepo<T>>(); | |
var resultTasks = new List<Task<T>>(); | |
if (links.Link == null) | |
{ | |
return null; | |
} | |
foreach (var l in links.Link) | |
{ | |
if (l.Rel != rel) | |
{ | |
continue; | |
} | |
var lClosure = l; | |
lClosure.Href = lClosure.Href.Replace("sessionregistrations.", "sessionregistrations");//hardcode fix a bug in the arlo api | |
resultTasks.Add(TaskThrottler.Get("GetLinkEntities", 15).Throttle(() => repo.Get(lClosure.Href))); | |
} | |
var resultFromTasks = await Task.WhenAll(resultTasks); | |
var listResult = resultFromTasks.ToList(); | |
await SetEntity(key, listResult); | |
return listResult; | |
} | |
public async Task<T> RecurseGetLinks<T>(ListOfLinks links, string key, string rel, bool doNext, bool forceRefresh) | |
where T : ListOfLinks, new() | |
{ | |
key += _getHashLinks(links); | |
var cacheResult = await GetEntity<T>(key); | |
if (cacheResult != null && !forceRefresh) | |
{ | |
return cacheResult; | |
} | |
var sessionUrl = links.FindLink(rel); | |
if (sessionUrl == null) | |
{ | |
return null; | |
} | |
var sessionsFromServer = await _recurseLinks<T>(sessionUrl, doNext); | |
await SetEntity(key, sessionsFromServer); | |
return sessionsFromServer; | |
} | |
async Task<T> _recurseLinks<T>(string sessionUrl, bool doNext) | |
where T:ListOfLinks, new() | |
{ | |
var repo = Scope.Resolve<IGenericWebRepo<T>>(); | |
var sessions = await repo.Get(sessionUrl); | |
if (sessions == null) | |
{ | |
return null; | |
} | |
if (!doNext) | |
{ | |
return sessions; | |
} | |
var nextUrl = sessions.FindLink(Constants.Rel.Next); | |
if (nextUrl == null) | |
{ | |
return sessions; | |
} | |
var sessionsRecursed = await _recurseLinks<T>(nextUrl, true); | |
if (sessionsRecursed?.Link == null) | |
{ | |
return sessions; | |
} | |
sessions.Link.AddRange(sessionsRecursed.Link); | |
return sessions; | |
} | |
string _getHashLinksLinks<TLinks>(List<TLinks> links) | |
where TLinks:ListOfLinks | |
{ | |
var list = new List<string>(); | |
foreach (var l in links) | |
{ | |
var linksSelected = l?.Link?.Select(_ => _.Href).ToList(); | |
if (linksSelected == null || linksSelected.Count == 0) | |
{ | |
continue; | |
} | |
var s = string.Join("", linksSelected); | |
var hash = HashHelper.Hash(Encoding.UTF8.GetBytes(s)); | |
list.Add(hash); | |
} | |
var sAll = string.Join("", list); | |
return HashHelper.Hash(Encoding.UTF8.GetBytes(sAll)); | |
} | |
string _getHashLinks(ListOfLinks links) | |
{ | |
if(links == null) | |
{ | |
return null; | |
} | |
var s = string.Join("", links.Link.Select(_ => _.Href)); | |
var hash = HashHelper.Hash(Encoding.UTF8.GetBytes(s)); | |
return hash; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment