Esempio n. 1
0
        /// <summary>
        ///     SetItem T By Key
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="litter">Item T To Be Cached</param>
        /// <returns>Success True|False (For Each Cache)</returns>
        public async Task <StorageResult[]> SetItem <T>(string key, LitterBoxItem <T> litter)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return(null);
            }

            if (litter == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(litter)} Cannot Be Null"));
                return(null);
            }

            var results = new StorageResult[this._caches.Length];

            for (var i = 0; i < this._caches.Length; i++)
            {
                var cache   = this._caches[i];
                var success = await cache.SetItem(key, litter).ConfigureAwait(false);

                results[i] = new StorageResult {
                    CacheType    = cache.GetType(),
                    IsSuccessful = success
                };
            }

            return(results);
        }
Esempio n. 2
0
 /// <summary>
 ///     Initializes a new instance of the <see cref="CacheItem{T}" /> class.
 /// </summary>
 /// <param name="key">Key/ID Of Document</param>
 /// <param name="litter">Existing T LitterBoxItem</param>
 /// <param name="partitionKey">The default partition Key</param>
 public CacheItem(string key, LitterBoxItem <T> litter, string partitionKey = "none")
 {
     this.ID            = key;
     this.Value         = litter.Value;
     this.Created       = litter.Created;
     this.TimeToLive    = litter.TimeToLive;
     this.TimeToRefresh = litter.TimeToRefresh;
     this.PartitionKey  = partitionKey;
 }
Esempio n. 3
0
        /// <summary>
        ///     SetItem T (Fire Forget) By Key, Generator, TimeToRefresh, TimeToLive
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="generator">Generator Action</param>
        /// <param name="timeToRefresh">How Long After Creation To Be Considered "Good"</param>
        /// <param name="timeToLive">How Long After Creation To Auto-Delete</param>
        public void SetItemFireAndForget <T>(string key, Func <Task <T> > generator, TimeSpan?timeToRefresh = null, TimeSpan?timeToLive = null)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return;
            }

            if (generator == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(generator)} Cannot Be Null"));
                return;
            }

            if (!this._inProcess.TryAdd(key, true))
            {
                return;
            }

            Task.Run(
                async() => {
                int?toLive    = null;
                int?toRefresh = null;
                if (timeToLive != null)
                {
                    toLive = (int)((TimeSpan)timeToLive).TotalSeconds;
                }

                if (timeToRefresh != null)
                {
                    toRefresh = (int)((TimeSpan)timeToRefresh).TotalSeconds;
                }

                try {
                    var item = await generator().ConfigureAwait(false);
                    if (item != null)
                    {
                        var litter = new LitterBoxItem <T> {
                            Value         = item,
                            TimeToLive    = toLive,
                            TimeToRefresh = toRefresh
                        };
                        await this.SetItem(key, litter).ConfigureAwait(false);
                    }
                }
                catch (Exception ex) {
                    this.RaiseException(ex);
                }
            }).ConfigureAwait(false);
        }
Esempio n. 4
0
        /// <summary>
        ///     SetItem T By Key
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="original">Item T To Be Cached</param>
        /// <returns>Success True|False</returns>
        public async Task <bool> SetItem <T>(string key, LitterBoxItem <T> original)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return(false);
            }

            if (original == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(original)} Cannot Be Null"));
                return(false);
            }

            var success = false;

            // when using multi-caching; modifying the TTR and TTL on the object collides with other caches
            var litter = original.Clone();

            litter.TimeToRefresh = litter.TimeToRefresh ?? (int)this._configuration.DefaultTimeToRefresh.TotalSeconds;
            litter.TimeToLive    = litter.TimeToLive ?? (int)this._configuration.DefaultTimeToLive.TotalSeconds;

            try {
                var uri            = UriFactory.CreateDocumentCollectionUri(this._configuration.Database, this._configuration.Collection);
                var document       = new CacheItem <T>(key, litter, this._configuration.PartitionKey);
                var requestOptions = new RequestOptions {
                    ConsistencyLevel        = ConsistencyLevel.Eventual,
                    DisableRUPerMinuteUsage = true,
                    PartitionKey            = new PartitionKey(this._configuration.PartitionKey)
                };
                var result = await this.GetPooledConnection <DocumentDBConnection>().Cache.UpsertDocumentAsync(uri, document, requestOptions).ConfigureAwait(false);

                if (result != null)
                {
                    success = true;
                }
            }
            catch (Exception ex) {
                this.RaiseException(ex);
            }

            this._inProcess.TryRemove(key, out var itemSet);

            return(success);
        }
Esempio n. 5
0
        /// <summary>
        ///     SetItem T By Key
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="original">Item T To Be Cached</param>
        /// <returns>Success True|False</returns>
        public async Task <bool> SetItem <T>(string key, LitterBoxItem <T> original)
        {
            var success = false;

            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return(success);
            }

            if (original == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItem)}=>{nameof(original)} Cannot Be Null"));
                return(success);
            }

            // when using multi-caching; modifying the TTR and TTL on the object collides with other caches
            var litter = original.Clone();

            litter.TimeToRefresh = litter.TimeToRefresh ?? (int)this._configuration.DefaultTimeToRefresh.TotalSeconds;
            litter.TimeToLive    = litter.TimeToLive ?? (int)this._configuration.DefaultTimeToLive.TotalSeconds;

            try {
                var json = Utilities.Serialize(litter);
                if (!string.IsNullOrWhiteSpace(json))
                {
                    var connection = this.GetPooledConnection <RedisConnection>();

                    var hashSetSuccess = await connection.Cache.HashSetAsync(key, "litter", Compression.Zip(json)).ConfigureAwait(false);

                    var keyExpireSuccess = await connection.Cache.KeyExpireAsync(key, TimeSpan.FromSeconds((double)litter.TimeToLive)).ConfigureAwait(false);

                    success = hashSetSuccess & keyExpireSuccess;
                }
            }
            catch (Exception ex) {
                this.RaiseException(ex);
            }

            this._inProcess.TryRemove(key, out var removed);

            return(success);
        }
Esempio n. 6
0
        /// <summary>
        ///     SetItem T (Fire Forget) By Key, LitterBoxItem T
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="litter">Item T To Be Cached</param>
        public void SetItemFireAndForget <T>(string key, LitterBoxItem <T> litter)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return;
            }

            if (litter == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(litter)} Cannot Be Null"));
                return;
            }

            if (!this._inProcess.TryAdd(key, true))
            {
                return;
            }

            Task.Run(() => this.SetItem(key, litter)).ConfigureAwait(false);
        }
Esempio n. 7
0
        /// <summary>
        ///     SetItem T (Fire Forget) By Key, LitterBoxItem T
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="litter">Item T To Be Cached</param>
        public void SetItemFireAndForget <T>(string key, LitterBoxItem <T> litter)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return;
            }

            if (litter == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.SetItemFireAndForget)}=>{nameof(litter)} Cannot Be Null"));
                return;
            }

            Task.Run(
                () => {
                foreach (var cache in this._caches)
                {
                    cache.SetItemFireAndForget(key, litter);
                }
            }).ConfigureAwait(false);
        }
Esempio n. 8
0
        /// <summary>
        ///     GetItem T By Key, Generator, TimeToRefresh, TimeToLive
        /// </summary>
        /// <typeparam name="T">Type Of Cached Value</typeparam>
        /// <param name="key">Key Lookup</param>
        /// <param name="generator">Generator Action If Not Found</param>
        /// <param name="timeToRefresh">How Long After Creation To Be Considered "Good"</param>
        /// <param name="timeToLive">How Long After Creation To Auto-Delete</param>
        /// <returns>TenancyItem => LitterBoxItem T</returns>
        public async Task <LitterBoxItem <T> > GetItem <T>(string key, Func <Task <T> > generator, TimeSpan?timeToRefresh = null, TimeSpan?timeToLive = null)
        {
            if (string.IsNullOrWhiteSpace(key))
            {
                this.RaiseException(new ArgumentException($"{nameof(this.GetItem)}=>{nameof(key)} Cannot Be NullOrWhiteSpace"));
                return(null);
            }

            if (generator == null)
            {
                this.RaiseException(new ArgumentException($"{nameof(this.GetItem)}=>{nameof(generator)} Cannot Be Null"));
                return(null);
            }

            var foundIndex           = 0;
            LitterBoxItem <T> result = null;

            for (var i = 0; i < this._caches.Length; i++)
            {
                var cache = this._caches[i];
                result = await cache.GetItem <T>(key).ConfigureAwait(false);

                if (result != null)
                {
                    foundIndex       = i;
                    result.Key       = key;
                    result.CacheType = cache.GetType();

                    // if the item is stale; refresh this cache only at this time
                    if (result.IsStale())
                    {
                        cache.SetItemFireAndForget(key, generator, timeToRefresh, timeToLive);
                    }

                    break;
                }
            }

            int?toLive    = null;
            int?toRefresh = null;

            if (timeToLive != null)
            {
                toLive = (int)((TimeSpan)timeToLive).TotalSeconds;
            }

            if (timeToRefresh != null)
            {
                toRefresh = (int)((TimeSpan)timeToRefresh).TotalSeconds;
            }

            if (result == null)
            {
                foundIndex = this._caches.Length;
                try {
                    result = new LitterBoxItem <T> {
                        Value         = await generator().ConfigureAwait(false),
                        TimeToLive    = toLive,
                        TimeToRefresh = toRefresh
                    };
                }
                catch (Exception ex) {
                    this.RaiseException(ex);
                }
            }

            if (result != null)
            {
                for (var i = 0; i < foundIndex; i++)
                {
                    var cache = this._caches[i];

                    // if the result was stale and was also found in a cache
                    // refresh all caches from until the cache it was found in
                    if (result.IsStale() && result.CacheType != null)
                    {
                        cache.SetItemFireAndForget(key, generator, timeToRefresh, timeToLive);
                    }
                    else
                    {
                        // else we can just save the item into the cache and not regenerate
                        cache.SetItemFireAndForget(key, result);
                    }
                }
            }

            return(result);
        }