private void UpdateAgentInfoOnCacheRemove(object key, object value, EvictionReason reason, object state) { Guid webAgentID = (Guid)key; var poolEnt = poolEntries.SingleOrDefault(a => a.WebAgentID == webAgentID); RefreshTokenWebAgent agent = value as RefreshTokenWebAgent; if (agent == null || poolEnt == null) { return; } poolEnt.TokenExpires = agent.TokenValidTo; poolEnt.AccessToken = agent.AccessToken; poolEnt.UserAgentString = agent.UserAgent; poolEnt.RefreshToken = agent.RefreshToken; poolEnt.RateLimiterMode = agent.RateLimiter.Mode; }
/// <summary> /// Gets the <see cref="IWebAgent"/> corresponding to the current user, or creates one if it doesn't exist. /// </summary> /// <param name="username">Username of Reddit user of <see cref="IWebAgent"/></param> /// <param name="createAsync">Async function to return a new <see cref="RefreshTokenPoolEntry"/>. Parameters (<see cref="string"/> username, <see cref="string"/> default useragent, <see cref="RateLimitMode"/> default rate limit mode)</param> /// <returns></returns> public async Task <IWebAgent> GetOrCreateWebAgentAsync(string username, Func <string, string, RateLimitMode, Task <RefreshTokenPoolEntry> > createAsync, int requestsPerMinuteWithOAuth = 60, int requestsPerMinuteWithoutOAuth = 30) { if (string.IsNullOrWhiteSpace(username)) { throw new ArgumentException("username cannot be null or empty"); } var poolEnt = poolEntries.SingleOrDefault(a => a.Username.ToLower() == username.ToLower()); if (poolEnt == null) { await cacheLock.WaitAsync(); RefreshTokenWebAgent agent = null; try { //check if someone else wrote it while waiting for lock. poolEnt = poolEntries.SingleOrDefault(a => a.Username.ToLower() == username.ToLower()); if (poolEnt != null) { return(await GetWebAgentAsync(poolEnt, requestsPerMinuteWithOAuth, requestsPerMinuteWithoutOAuth)); } poolEnt = await createAsync(username, DefaultUserAgent, DefaultRateLimitMode); poolEntries.Add(poolEnt); var opts = new MemoryCacheEntryOptions() { AbsoluteExpiration = null, SlidingExpiration = new TimeSpan(0, SlidingExpirationMinutes, 0) }; opts.RegisterPostEvictionCallback(UpdateAgentInfoOnCacheRemove); agent = new RefreshTokenWebAgent(poolEnt.RefreshToken, ClientID, ClientSecret, RedirectURI, poolEnt.UserAgentString, poolEnt.AccessToken, poolEnt.TokenExpires, new RateLimitManager(poolEnt.RateLimiterMode)); activeAgentsCache.Set(poolEnt.WebAgentID, agent, opts); return(agent); } finally { cacheLock.Release(); } } return(await GetWebAgentAsync(poolEnt, requestsPerMinuteWithOAuth, requestsPerMinuteWithoutOAuth)); }
private async Task <IWebAgent> GetWebAgentAsync(RefreshTokenPoolEntry poolEnt, int requestsPerMinuteWithOAuth, int requestsPerMinuteWithoutOAuth) { IWebAgent toReturn = null; if (poolEnt != null) { toReturn = activeAgentsCache.Get <IWebAgent>(poolEnt.WebAgentID); if (toReturn == null) { await cacheLock.WaitAsync(); RefreshTokenWebAgent agent = null; try { //check if someone else wrote it while waiting for lock. agent = activeAgentsCache.Get <RefreshTokenWebAgent>(poolEnt.WebAgentID); if (agent != null) { return(agent); } var opts = new MemoryCacheEntryOptions() { AbsoluteExpiration = null, SlidingExpiration = new TimeSpan(0, SlidingExpirationMinutes, 0) }; opts.RegisterPostEvictionCallback(UpdateAgentInfoOnCacheRemove); agent = new RefreshTokenWebAgent(poolEnt.RefreshToken, ClientID, ClientSecret, RedirectURI, poolEnt.UserAgentString, poolEnt.AccessToken, poolEnt.TokenExpires, new RateLimitManager(poolEnt.RateLimiterMode, requestsPerMinuteWithOAuth, requestsPerMinuteWithoutOAuth)); activeAgentsCache.Set(poolEnt.WebAgentID, agent, opts); return(agent); } finally { cacheLock.Release(); } } } return(toReturn); }