/// <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));
        }
Пример #2
0
        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;
        }
        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);
        }