{"action":"created","comment":{"url":"https://api.github.com/repos/aspnet/Caching/pulls/comments/32687842","id":32687842,"diff_hunk":"@@ -0,0 +1,478 @@\n+// Copyright (c) .NET Foundation. All rights reserved.\n+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n+\n+using System;\n+using System.Data;\n+using System.Data.SqlClient;\n+using System.Threading;\n+using System.Threading.Tasks;\n+using Microsoft.Framework.Caching.Distributed;\n+using Microsoft.Framework.Internal;\n+using Microsoft.Framework.Logging;\n+using Microsoft.Framework.OptionsModel;\n+\n+namespace Microsoft.Framework.Caching.SqlServer\n+{\n+    /// <summary>\n+    /// Distributed cache implementation using Microsoft SQL Server database.\n+    /// </summary>\n+    public class SqlServerCache : IDistributedCache\n+    {\n+        /// <summary>\n+        /// To prevent frequent updates to a cache item's expiration time in database, especially when doing a\n+        /// Get operation, a cache item's expiration time is extended by doubling the sliding expiration.\n+        /// The 'SlidingExpiration' here should be interpreted as the minimum time to live for a cache item before\n+        /// it expires.\n+        /// Example:\n+        /// For a sliding expiration of 30 mins, a new cache item would have its 'ExpiresAtTimeUTC' 60 mins(30 * 2)\n+        /// from now. All 'Get' operations before the first 30 mins do not cause any database updates to the cache\n+        /// item's expiration time and any 'Get' operations between the 30th and 60th minute would cause a database\n+        /// update where the expiration time is again extended by 60 mins.\n+        /// </summary>\n+        internal const int ExpirationTimeMultiplier = 2;\n+\n+        // Table column names\n+        private const string CacheItemId = \"Id\";\n+        private const string CacheItemValue = \"Value\";\n+        private const string ExpiresAtTimeUTC = \"ExpiresAtTimeUTC\";\n+        private const string SlidingExpirationInTicks = \"SlidingExpirationInTicks\";\n+        private const string AbsoluteExpiration = \"AbsoluteExpiration\";\n+        private int _cacheItemIdIndex = -1;\n+        private int _cacheItemValueIndex = -1;\n+        private int _expiresAtTimeUTCIndex = -1;\n+        private int _slidingExpirationInTicksIndex = -1;\n+        private int _absoluteExpirationIndex = -1;\n+\n+        private readonly SqlServerCacheOptions _options;\n+        private readonly ILogger _logger;\n+        private readonly ISystemClock _systemClock;\n+        private readonly SqlQueries _sqlQueries;\n+        private DateTimeOffset _lastExpirationScan;\n+\n+        public SqlServerCache(IOptions<SqlServerCacheOptions> options, ILoggerFactory loggerFactory)\n+        {\n+            _options = options.Options;\n+            _systemClock = _options.SystemClock;\n+            _sqlQueries = new SqlQueries(_options.TableName);\n+            _logger = loggerFactory.CreateLogger<SqlServerCache>();\n+        }\n+\n+        public void Connect()\n+        {\n+            // Try connecting to the database to test if its available and also\n+            // get and cache the ordinal positions of the columns for better performance.\n+            using (var connection = new SqlConnection(_options.ConnectionString))\n+            {\n+                var command = new SqlCommand(_sqlQueries.GetTableSchema, connection);\n+                connection.Open();\n+\n+                var reader = command.ExecuteReader(CommandBehavior.SchemaOnly);\n+\n+                _cacheItemIdIndex = reader.GetOrdinal(CacheItemId);\n+                _cacheItemValueIndex = reader.GetOrdinal(CacheItemValue);\n+                _expiresAtTimeUTCIndex = reader.GetOrdinal(ExpiresAtTimeUTC);\n+                _slidingExpirationInTicksIndex = reader.GetOrdinal(SlidingExpirationInTicks);\n+                _absoluteExpirationIndex = reader.GetOrdinal(AbsoluteExpiration);\n+            }\n+        }\n+\n+        public async Task ConnectAsync()\n+        {\n+            // Try connecting to the database to test if its available and also\n+            // get and cache the ordinal positions of the columns for better performance.\n+            using (var connection = new SqlConnection(_options.ConnectionString))\n+            {\n+                var command = new SqlCommand(_sqlQueries.GetTableSchema, connection);\n+                await connection.OpenAsync();\n+\n+                var reader = await command.ExecuteReaderAsync(CommandBehavior.SchemaOnly);\n+\n+                _cacheItemIdIndex = reader.GetOrdinal(CacheItemId);\n+                _cacheItemValueIndex = reader.GetOrdinal(CacheItemValue);\n+                _expiresAtTimeUTCIndex = reader.GetOrdinal(ExpiresAtTimeUTC);\n+                _slidingExpirationInTicksIndex = reader.GetOrdinal(SlidingExpirationInTicks);\n+                _absoluteExpirationIndex = reader.GetOrdinal(AbsoluteExpiration);\n+            }\n+        }\n+\n+        public byte[] Get([NotNull] string key)\n+        {\n+            byte[] cacheItemvalue = null;\n+            var utcNow = _systemClock.UtcNow;\n+\n+            using (var connection = new SqlConnection(_options.ConnectionString))\n+            {\n+                var command = new SqlCommand(_sqlQueries.GetCacheItem, connection);\n+                command.Parameters.AddWithValue(CacheItemId, key);\n+                command.Parameters.AddWithValue(\"UtcNow\", utcNow);\n+\n+                connection.Open();\n+\n+                var reader = command.ExecuteReader(CommandBehavior.SingleRow);\n+\n+                DateTimeOffset oldExpirationTime;\n+                TimeSpan? slidingExpiration = null;\n+                DateTimeOffset? absoluteExpiration = null;\n+                if (reader.Read())\n+                {\n+                    oldExpirationTime = reader.GetFieldValue<DateTimeOffset>(_expiresAtTimeUTCIndex);\n+                    cacheItemvalue = reader.GetFieldValue<byte[]>(_cacheItemValueIndex);\n+\n+                    if (!reader.IsDBNull(_slidingExpirationInTicksIndex))\n+                    {\n+                        slidingExpiration = TimeSpan.FromTicks(\n+                            reader.GetFieldValue<long>(_slidingExpirationInTicksIndex));\n+                    }\n+\n+                    if (!reader.IsDBNull(_absoluteExpirationIndex))\n+                    {\n+                        absoluteExpiration = reader.GetFieldValue<DateTimeOffset>(_absoluteExpirationIndex);\n+                    }\n+                }\n+                else\n+                {\n+                    return null;\n+                }\n+\n+                // Check if the current item has a sliding expiration and is going to expire within the\n+                // next timeout period(ex:20 minutes), then extend the expiration time.\n+                if (slidingExpiration.HasValue &&\n+                    utcNow >= (oldExpirationTime - slidingExpiration.Value))\n+                {\n+                    var newExpirationTime = GetExpirationTime(slidingExpiration, absoluteExpiration, utcNow);\n+\n+                    if (oldExpirationTime != newExpirationTime)\n+                    {\n+                        reader.Dispose();\n+\n+                        command = new SqlCommand(_sqlQueries.UpdateCacheItemExpiration, connection);\n+                        command.Parameters.AddWithValue(CacheItemId, key);\n+                        command.Parameters.AddWithValue(ExpiresAtTimeUTC, newExpirationTime);\n+\n+                        command.ExecuteNonQuery();\n+                    }\n+                }\n+            }\n+\n+            StartScanForExpiredCacheItems();\n+\n+            return cacheItemvalue;\n+        }\n+\n+        public async Task<byte[]> GetAsync([NotNull] string key)\n+        {\n+            byte[] cacheItemvalue = null;\n+            var utcNow = _systemClock.UtcNow;\n+\n+            using (var connection = new SqlConnection(_options.ConnectionString))\n+            {\n+                var command = new SqlCommand(_sqlQueries.GetCacheItem, connection);\n+                command.Parameters.AddWithValue(CacheItemId, key);\n+                command.Parameters.AddWithValue(\"UtcNow\", utcNow);\n+\n+                await connection.OpenAsync();\n+\n+                var reader = await command.ExecuteReaderAsync(CommandBehavior.SingleRow);\n+\n+                DateTimeOffset oldExpirationTime;\n+                TimeSpan? slidingExpiration = null;\n+                DateTimeOffset? absoluteExpiration = null;\n+                if (await reader.ReadAsync())\n+                {\n+                    oldExpirationTime = await reader.GetFieldValueAsync<DateTimeOffset>(_expiresAtTimeUTCIndex);\n+                    cacheItemvalue = await reader.GetFieldValueAsync<byte[]>(_cacheItemValueIndex);","path":"src/Microsoft.Framework.Caching.SqlServer/SqlServerCache.cs","position":183,"original_position":183,"commit_id":"cdc6264668c06308c64be37b1512fb50f9a4fcb3","original_commit_id":"cdc6264668c06308c64be37b1512fb50f9a4fcb3","user":{"login":"divega","id":1253414,"avatar_url":"https://avatars.githubusercontent.com/u/1253414?v=3","gravatar_id":"","url":"https://api.github.com/users/divega","html_url":"https://github.com/divega","followers_url":"https://api.github.com/users/divega/followers","following_url":"https://api.github.com/users/divega/following{/other_user}","gists_url":"https://api.github.com/users/divega/gists{/gist_id}","starred_url":"https://api.github.com/users/divega/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/divega/subscriptions","organizations_url":"https://api.github.com/users/divega/orgs","repos_url":"https://api.github.com/users/divega/repos","events_url":"https://api.github.com/users/divega/events{/privacy}","received_events_url":"https://api.github.com/users/divega/received_events","type":"User","site_admin":false},"body":"Consider using `GetStream()` and `CopyToAsync()` here. This could have more of an impact for the async path.","created_at":"2015-06-17T23:47:35Z","updated_at":"2015-06-17T23:47:35Z","html_url":"https://github.com/aspnet/Caching/pull/70#discussion_r32687842","pull_request_url":"https://api.github.com/repos/aspnet/Caching/pulls/70","_links":{"self":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/comments/32687842"},"html":{"href":"https://github.com/aspnet/Caching/pull/70#discussion_r32687842"},"pull_request":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/70"}}},"pull_request":{"url":"https://api.github.com/repos/aspnet/Caching/pulls/70","id":37491892,"html_url":"https://github.com/aspnet/Caching/pull/70","diff_url":"https://github.com/aspnet/Caching/pull/70.diff","patch_url":"https://github.com/aspnet/Caching/pull/70.patch","issue_url":"https://api.github.com/repos/aspnet/Caching/issues/70","number":70,"state":"open","locked":false,"title":"[Design] Implementation of SQL Server Cache","user":{"login":"kichalla","id":6559784,"avatar_url":"https://avatars.githubusercontent.com/u/6559784?v=3","gravatar_id":"","url":"https://api.github.com/users/kichalla","html_url":"https://github.com/kichalla","followers_url":"https://api.github.com/users/kichalla/followers","following_url":"https://api.github.com/users/kichalla/following{/other_user}","gists_url":"https://api.github.com/users/kichalla/gists{/gist_id}","starred_url":"https://api.github.com/users/kichalla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/kichalla/subscriptions","organizations_url":"https://api.github.com/users/kichalla/orgs","repos_url":"https://api.github.com/users/kichalla/repos","events_url":"https://api.github.com/users/kichalla/events{/privacy}","received_events_url":"https://api.github.com/users/kichalla/received_events","type":"User","site_admin":false},"body":"@Tratcher @Eilon @muratg  @lodejard\r\n\r\nPlease note that I do not have tests yet, but I have verified that the following is working end-to-end with different samples(including the one in Session repo : https://github.com/aspnet/Session/pull/34)","created_at":"2015-06-11T18:08:52Z","updated_at":"2015-06-17T23:47:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"447b68aaeec46f3a9b2a08df402938eaffb028da","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/aspnet/Caching/pulls/70/commits","review_comments_url":"https://api.github.com/repos/aspnet/Caching/pulls/70/comments","review_comment_url":"https://api.github.com/repos/aspnet/Caching/pulls/comments{/number}","comments_url":"https://api.github.com/repos/aspnet/Caching/issues/70/comments","statuses_url":"https://api.github.com/repos/aspnet/Caching/statuses/cdc6264668c06308c64be37b1512fb50f9a4fcb3","head":{"label":"aspnet:kiran/sql-server-cache","ref":"kiran/sql-server-cache","sha":"cdc6264668c06308c64be37b1512fb50f9a4fcb3","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":22390590,"name":"Caching","full_name":"aspnet/Caching","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Caching","description":"Libraries for caching, including in-memory caching, distributed caching, and ASP.NET session caching.","fork":false,"url":"https://api.github.com/repos/aspnet/Caching","forks_url":"https://api.github.com/repos/aspnet/Caching/forks","keys_url":"https://api.github.com/repos/aspnet/Caching/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Caching/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Caching/teams","hooks_url":"https://api.github.com/repos/aspnet/Caching/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Caching/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Caching/events","assignees_url":"https://api.github.com/repos/aspnet/Caching/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Caching/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Caching/tags","blobs_url":"https://api.github.com/repos/aspnet/Caching/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Caching/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Caching/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Caching/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Caching/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Caching/languages","stargazers_url":"https://api.github.com/repos/aspnet/Caching/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Caching/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Caching/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Caching/subscription","commits_url":"https://api.github.com/repos/aspnet/Caching/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Caching/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Caching/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Caching/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Caching/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Caching/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Caching/merges","archive_url":"https://api.github.com/repos/aspnet/Caching/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Caching/downloads","issues_url":"https://api.github.com/repos/aspnet/Caching/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Caching/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Caching/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Caching/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Caching/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Caching/releases{/id}","created_at":"2014-07-29T18:25:32Z","updated_at":"2015-06-15T14:14:36Z","pushed_at":"2015-06-15T21:27:00Z","git_url":"git://github.com/aspnet/Caching.git","ssh_url":"git@github.com:aspnet/Caching.git","clone_url":"https://github.com/aspnet/Caching.git","svn_url":"https://github.com/aspnet/Caching","homepage":"","size":1648,"stargazers_count":76,"watchers_count":76,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":12,"forks":27,"open_issues":12,"watchers":76,"default_branch":"dev"}},"base":{"label":"aspnet:dev","ref":"dev","sha":"e14fe9e39a839fbc4c23ee9c861c06d60ddf04a5","user":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"repo":{"id":22390590,"name":"Caching","full_name":"aspnet/Caching","owner":{"login":"aspnet","id":6476660,"avatar_url":"https://avatars.githubusercontent.com/u/6476660?v=3","gravatar_id":"","url":"https://api.github.com/users/aspnet","html_url":"https://github.com/aspnet","followers_url":"https://api.github.com/users/aspnet/followers","following_url":"https://api.github.com/users/aspnet/following{/other_user}","gists_url":"https://api.github.com/users/aspnet/gists{/gist_id}","starred_url":"https://api.github.com/users/aspnet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aspnet/subscriptions","organizations_url":"https://api.github.com/users/aspnet/orgs","repos_url":"https://api.github.com/users/aspnet/repos","events_url":"https://api.github.com/users/aspnet/events{/privacy}","received_events_url":"https://api.github.com/users/aspnet/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/aspnet/Caching","description":"Libraries for caching, including in-memory caching, distributed caching, and ASP.NET session caching.","fork":false,"url":"https://api.github.com/repos/aspnet/Caching","forks_url":"https://api.github.com/repos/aspnet/Caching/forks","keys_url":"https://api.github.com/repos/aspnet/Caching/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aspnet/Caching/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aspnet/Caching/teams","hooks_url":"https://api.github.com/repos/aspnet/Caching/hooks","issue_events_url":"https://api.github.com/repos/aspnet/Caching/issues/events{/number}","events_url":"https://api.github.com/repos/aspnet/Caching/events","assignees_url":"https://api.github.com/repos/aspnet/Caching/assignees{/user}","branches_url":"https://api.github.com/repos/aspnet/Caching/branches{/branch}","tags_url":"https://api.github.com/repos/aspnet/Caching/tags","blobs_url":"https://api.github.com/repos/aspnet/Caching/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aspnet/Caching/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aspnet/Caching/git/refs{/sha}","trees_url":"https://api.github.com/repos/aspnet/Caching/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aspnet/Caching/statuses/{sha}","languages_url":"https://api.github.com/repos/aspnet/Caching/languages","stargazers_url":"https://api.github.com/repos/aspnet/Caching/stargazers","contributors_url":"https://api.github.com/repos/aspnet/Caching/contributors","subscribers_url":"https://api.github.com/repos/aspnet/Caching/subscribers","subscription_url":"https://api.github.com/repos/aspnet/Caching/subscription","commits_url":"https://api.github.com/repos/aspnet/Caching/commits{/sha}","git_commits_url":"https://api.github.com/repos/aspnet/Caching/git/commits{/sha}","comments_url":"https://api.github.com/repos/aspnet/Caching/comments{/number}","issue_comment_url":"https://api.github.com/repos/aspnet/Caching/issues/comments{/number}","contents_url":"https://api.github.com/repos/aspnet/Caching/contents/{+path}","compare_url":"https://api.github.com/repos/aspnet/Caching/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aspnet/Caching/merges","archive_url":"https://api.github.com/repos/aspnet/Caching/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aspnet/Caching/downloads","issues_url":"https://api.github.com/repos/aspnet/Caching/issues{/number}","pulls_url":"https://api.github.com/repos/aspnet/Caching/pulls{/number}","milestones_url":"https://api.github.com/repos/aspnet/Caching/milestones{/number}","notifications_url":"https://api.github.com/repos/aspnet/Caching/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aspnet/Caching/labels{/name}","releases_url":"https://api.github.com/repos/aspnet/Caching/releases{/id}","created_at":"2014-07-29T18:25:32Z","updated_at":"2015-06-15T14:14:36Z","pushed_at":"2015-06-15T21:27:00Z","git_url":"git://github.com/aspnet/Caching.git","ssh_url":"git@github.com:aspnet/Caching.git","clone_url":"https://github.com/aspnet/Caching.git","svn_url":"https://github.com/aspnet/Caching","homepage":"","size":1648,"stargazers_count":76,"watchers_count":76,"language":"C#","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":27,"mirror_url":null,"open_issues_count":12,"forks":27,"open_issues":12,"watchers":76,"default_branch":"dev"}},"_links":{"self":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/70"},"html":{"href":"https://github.com/aspnet/Caching/pull/70"},"issue":{"href":"https://api.github.com/repos/aspnet/Caching/issues/70"},"comments":{"href":"https://api.github.com/repos/aspnet/Caching/issues/70/comments"},"review_comments":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/70/comments"},"review_comment":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/aspnet/Caching/pulls/70/commits"},"statuses":{"href":"https://api.github.com/repos/aspnet/Caching/statuses/cdc6264668c06308c64be37b1512fb50f9a4fcb3"}}}}