{"action":"created","comment":{"url":"https://api.github.com/repos/ravendb/ravendb/pulls/comments/195479097","pull_request_review_id":128857346,"id":195479097,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5NTQ3OTA5Nw==","diff_hunk":"@@ -0,0 +1,170 @@\n+﻿//-----------------------------------------------------------------------\n+// <copyright file=\"AsyncSessionDocumentCounters.cs\" company=\"Hibernating Rhinos LTD\">\n+//     Copyright (c) Hibernating Rhinos LTD. All rights reserved.\n+// </copyright>\n+//-----------------------------------------------------------------------\n+\n+using System;\n+using System.Collections.Generic;\n+using System.Linq;\n+using System.Threading;\n+using System.Threading.Tasks;\n+using Raven.Client.Documents.Operations.Counters;\n+using Sparrow.Json;\n+\n+namespace Raven.Client.Documents.Session\n+{\n+    public class AsyncSessionDocumentCounters : SessionCountersBase, IAsyncSessionDocumentCounters\n+    {\n+        public AsyncSessionDocumentCounters(InMemoryDocumentSessionOperations session, string documentId) : base(session, documentId)\n+        {\n+        }\n+\n+        public AsyncSessionDocumentCounters(InMemoryDocumentSessionOperations session, object entity) : base(session, entity)\n+        {\n+        }\n+\n+        public async Task<long?> GetAsync(string counter, CancellationToken token = default)\n+        {\n+            long? value = null;\n+            if (Session.CountersByDocId.TryGetValue(DocId, out var cache))\n+            {\n+                if (cache.Values.TryGetValue(counter, out value))\n+                    return value;\n+            }\n+            else\n+            {\n+                cache.Values = new Dictionary<string, long?>(StringComparer.OrdinalIgnoreCase);\n+            }\n+\n+            if ((Session.DocumentsById.TryGetValue(DocId, out var document) == false && cache.GotAll == false) ||\n+                (document != null && document.Metadata.TryGet(Constants.Documents.Metadata.Counters, \n+                    out BlittableJsonReaderArray metadataCounters) &&\n+                metadataCounters.BinarySearch(counter, StringComparison.OrdinalIgnoreCase) >= 0))\n+                \n+            {\n+                // we either don't have the document in session and GotAll = false,\n+                // or we do and it's metadata contains the counter name\n+\n+                Session.IncrementRequestCount();\n+\n+                var details = await Session.DocumentStore.Operations.ForDatabase(Session.DatabaseName)\n+                    .SendAsync(new GetCountersOperation(DocId, new[] { counter }), token: token).ConfigureAwait(false);\n+\n+                if (details.Counters?.Count > 0)\n+                {\n+                    value = details.Counters[0].TotalValue;\n+                }\n+\n+            }\n+\n+            cache.Values[counter] = value;\n+            Session.CountersByDocId[DocId] = cache;\n+\n+            return value;\n+        }\n+\n+        public async Task<Dictionary<string, long?>> GetAsync(IEnumerable<string> counters, CancellationToken token = default)\n+        {\n+            if (Session.CountersByDocId.TryGetValue(DocId, out var cache) == false)\n+            {\n+                cache.Values = new Dictionary<string, long?>(StringComparer.OrdinalIgnoreCase);\n+            }\n+\n+            BlittableJsonReaderArray metadataCounters = null;\n+\n+            Session.DocumentsById.TryGetValue(DocId, out var document);\n+            document?.Metadata.TryGet(Constants.Documents.Metadata.Counters, out metadataCounters);\n+\n+            var result = new Dictionary<string, long?>();\n+            var countersArray = counters.ToArray();\n+\n+            foreach (var counter in countersArray)\n+            {\n+                if (cache.Values.TryGetValue(counter, out var val) ||\n+                    (document != null &&\n+                     metadataCounters?.BinarySearch(counter, StringComparison.OrdinalIgnoreCase) < 0) ||\n+                    cache.GotAll)\n+                {\n+                    // we either have value in cache,\n+                    // or we have the metadata and the counter is not there,\n+                    // or GotAll\n+\n+                    result[counter] = val;\n+                    continue;\n+                }\n+\n+                result.Clear();\n+                Session.IncrementRequestCount();\n+\n+                var details = await Session.DocumentStore.Operations.ForDatabase(Session.DatabaseName)\n+                    .SendAsync(new GetCountersOperation(DocId, countersArray), token: token).ConfigureAwait(false);\n+\n+                foreach (var counterDetail in details.Counters)\n+                {\n+                    cache.Values[counterDetail.CounterName] = counterDetail.TotalValue;\n+                    result[counterDetail.CounterName] = counterDetail.TotalValue;\n+                }\n+\n+                break;\n+            }\n+\n+            Session.CountersByDocId[DocId] = cache;\n+            return result;\n+        }\n+\n+        public async Task<Dictionary<string, long?>> GetAllAsync(CancellationToken token = default)\n+        {\n+            if (Session.CountersByDocId.TryGetValue(DocId, out var cache) == false)\n+            {\n+                cache.Values = new Dictionary<string, long?>(StringComparer.OrdinalIgnoreCase);\n+            }\n+\n+            var missingCounters = cache.GotAll == false;\n+\n+            if (Session.DocumentsById.TryGetValue(DocId, out var document))\n+            {\n+                if (document.Metadata.TryGet(Constants.Documents.Metadata.Counters, \n+                    out BlittableJsonReaderArray metadataCounters) == false)\n+                {\n+                    missingCounters = false;\n+                }\n+\n+                else if (cache.Values.Count >= metadataCounters.Length)\n+                {\n+                    missingCounters = false;\n+                    foreach (var c in metadataCounters)\n+                    {\n+                        if (cache.Values.ContainsKey(c.ToString()))\n+                            continue;\n+                        missingCounters = true;\n+                        break;\n+                    }\n+                }\n+\n+            }\n+\n+            if (missingCounters)\n+            {\n+                // we either don't have the document in session and GotAll = false,\n+                // or we do and cache doesn't contain all metadata counters\n+\n+                Session.IncrementRequestCount();\n+\n+                var details = await Session.DocumentStore.Operations.ForDatabase(Session.DatabaseName)\n+                    .SendAsync(new GetCountersOperation(DocId, new string[0]), token: token).ConfigureAwait(false);","path":"src/Raven.Client/Documents/Session/AsyncSessionDocumentCounters.cs","position":155,"original_position":155,"commit_id":"eb70dbc316183eedbb3903307b3fa6c9d5659c48","original_commit_id":"eb70dbc316183eedbb3903307b3fa6c9d5659c48","user":{"login":"ayende","id":116915,"node_id":"MDQ6VXNlcjExNjkxNQ==","avatar_url":"https://avatars3.githubusercontent.com/u/116915?v=4","gravatar_id":"","url":"https://api.github.com/users/ayende","html_url":"https://github.com/ayende","followers_url":"https://api.github.com/users/ayende/followers","following_url":"https://api.github.com/users/ayende/following{/other_user}","gists_url":"https://api.github.com/users/ayende/gists{/gist_id}","starred_url":"https://api.github.com/users/ayende/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ayende/subscriptions","organizations_url":"https://api.github.com/users/ayende/orgs","repos_url":"https://api.github.com/users/ayende/repos","events_url":"https://api.github.com/users/ayende/events{/privacy}","received_events_url":"https://api.github.com/users/ayende/received_events","type":"User","site_admin":false},"body":"done","created_at":"2018-06-14T15:58:04Z","updated_at":"2018-06-14T15:58:04Z","html_url":"https://github.com/ravendb/ravendb/pull/6549#discussion_r195479097","pull_request_url":"https://api.github.com/repos/ravendb/ravendb/pulls/6549","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/comments/195479097"},"html":{"href":"https://github.com/ravendb/ravendb/pull/6549#discussion_r195479097"},"pull_request":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/6549"}},"in_reply_to_id":195471362},"pull_request":{"url":"https://api.github.com/repos/ravendb/ravendb/pulls/6549","id":193828954,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkzODI4OTU0","html_url":"https://github.com/ravendb/ravendb/pull/6549","diff_url":"https://github.com/ravendb/ravendb/pull/6549.diff","patch_url":"https://github.com/ravendb/ravendb/pull/6549.patch","issue_url":"https://api.github.com/repos/ravendb/ravendb/issues/6549","number":6549,"state":"closed","locked":false,"title":"[4.1] RavenDB-11296 Track Counters in session API","user":{"login":"aviv86","id":23610777,"node_id":"MDQ6VXNlcjIzNjEwNzc3","avatar_url":"https://avatars0.githubusercontent.com/u/23610777?v=4","gravatar_id":"","url":"https://api.github.com/users/aviv86","html_url":"https://github.com/aviv86","followers_url":"https://api.github.com/users/aviv86/followers","following_url":"https://api.github.com/users/aviv86/following{/other_user}","gists_url":"https://api.github.com/users/aviv86/gists{/gist_id}","starred_url":"https://api.github.com/users/aviv86/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aviv86/subscriptions","organizations_url":"https://api.github.com/users/aviv86/orgs","repos_url":"https://api.github.com/users/aviv86/repos","events_url":"https://api.github.com/users/aviv86/events{/privacy}","received_events_url":"https://api.github.com/users/aviv86/received_events","type":"User","site_admin":false},"body":"CancellationTokens will be handled as a part of RavenDB-11326\r\nhttp://issues.hibernatingrhinos.com/issue/RavenDB-11326\r\n\r\nStill need to support includes with counters.","created_at":"2018-06-10T14:26:50Z","updated_at":"2018-06-14T15:58:04Z","closed_at":"2018-06-14T15:44:30Z","merged_at":"2018-06-14T15:44:30Z","merge_commit_sha":"5d4acda3e18d7bf0b9250f7366e4b410d2d70fae","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/ravendb/ravendb/pulls/6549/commits","review_comments_url":"https://api.github.com/repos/ravendb/ravendb/pulls/6549/comments","review_comment_url":"https://api.github.com/repos/ravendb/ravendb/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ravendb/ravendb/issues/6549/comments","statuses_url":"https://api.github.com/repos/ravendb/ravendb/statuses/eb70dbc316183eedbb3903307b3fa6c9d5659c48","head":{"label":"aviv86:RavenDB-11296","ref":"RavenDB-11296","sha":"eb70dbc316183eedbb3903307b3fa6c9d5659c48","user":{"login":"aviv86","id":23610777,"node_id":"MDQ6VXNlcjIzNjEwNzc3","avatar_url":"https://avatars0.githubusercontent.com/u/23610777?v=4","gravatar_id":"","url":"https://api.github.com/users/aviv86","html_url":"https://github.com/aviv86","followers_url":"https://api.github.com/users/aviv86/followers","following_url":"https://api.github.com/users/aviv86/following{/other_user}","gists_url":"https://api.github.com/users/aviv86/gists{/gist_id}","starred_url":"https://api.github.com/users/aviv86/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aviv86/subscriptions","organizations_url":"https://api.github.com/users/aviv86/orgs","repos_url":"https://api.github.com/users/aviv86/repos","events_url":"https://api.github.com/users/aviv86/events{/privacy}","received_events_url":"https://api.github.com/users/aviv86/received_events","type":"User","site_admin":false},"repo":{"id":74271618,"node_id":"MDEwOlJlcG9zaXRvcnk3NDI3MTYxOA==","name":"ravendb","full_name":"aviv86/ravendb","owner":{"login":"aviv86","id":23610777,"node_id":"MDQ6VXNlcjIzNjEwNzc3","avatar_url":"https://avatars0.githubusercontent.com/u/23610777?v=4","gravatar_id":"","url":"https://api.github.com/users/aviv86","html_url":"https://github.com/aviv86","followers_url":"https://api.github.com/users/aviv86/followers","following_url":"https://api.github.com/users/aviv86/following{/other_user}","gists_url":"https://api.github.com/users/aviv86/gists{/gist_id}","starred_url":"https://api.github.com/users/aviv86/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aviv86/subscriptions","organizations_url":"https://api.github.com/users/aviv86/orgs","repos_url":"https://api.github.com/users/aviv86/repos","events_url":"https://api.github.com/users/aviv86/events{/privacy}","received_events_url":"https://api.github.com/users/aviv86/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/aviv86/ravendb","description":"A linq enabled document database for .NET","fork":true,"url":"https://api.github.com/repos/aviv86/ravendb","forks_url":"https://api.github.com/repos/aviv86/ravendb/forks","keys_url":"https://api.github.com/repos/aviv86/ravendb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/aviv86/ravendb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/aviv86/ravendb/teams","hooks_url":"https://api.github.com/repos/aviv86/ravendb/hooks","issue_events_url":"https://api.github.com/repos/aviv86/ravendb/issues/events{/number}","events_url":"https://api.github.com/repos/aviv86/ravendb/events","assignees_url":"https://api.github.com/repos/aviv86/ravendb/assignees{/user}","branches_url":"https://api.github.com/repos/aviv86/ravendb/branches{/branch}","tags_url":"https://api.github.com/repos/aviv86/ravendb/tags","blobs_url":"https://api.github.com/repos/aviv86/ravendb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/aviv86/ravendb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/aviv86/ravendb/git/refs{/sha}","trees_url":"https://api.github.com/repos/aviv86/ravendb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/aviv86/ravendb/statuses/{sha}","languages_url":"https://api.github.com/repos/aviv86/ravendb/languages","stargazers_url":"https://api.github.com/repos/aviv86/ravendb/stargazers","contributors_url":"https://api.github.com/repos/aviv86/ravendb/contributors","subscribers_url":"https://api.github.com/repos/aviv86/ravendb/subscribers","subscription_url":"https://api.github.com/repos/aviv86/ravendb/subscription","commits_url":"https://api.github.com/repos/aviv86/ravendb/commits{/sha}","git_commits_url":"https://api.github.com/repos/aviv86/ravendb/git/commits{/sha}","comments_url":"https://api.github.com/repos/aviv86/ravendb/comments{/number}","issue_comment_url":"https://api.github.com/repos/aviv86/ravendb/issues/comments{/number}","contents_url":"https://api.github.com/repos/aviv86/ravendb/contents/{+path}","compare_url":"https://api.github.com/repos/aviv86/ravendb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/aviv86/ravendb/merges","archive_url":"https://api.github.com/repos/aviv86/ravendb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/aviv86/ravendb/downloads","issues_url":"https://api.github.com/repos/aviv86/ravendb/issues{/number}","pulls_url":"https://api.github.com/repos/aviv86/ravendb/pulls{/number}","milestones_url":"https://api.github.com/repos/aviv86/ravendb/milestones{/number}","notifications_url":"https://api.github.com/repos/aviv86/ravendb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/aviv86/ravendb/labels{/name}","releases_url":"https://api.github.com/repos/aviv86/ravendb/releases{/id}","deployments_url":"https://api.github.com/repos/aviv86/ravendb/deployments","created_at":"2016-11-20T12:10:32Z","updated_at":"2018-04-25T08:33:05Z","pushed_at":"2018-06-14T14:49:11Z","git_url":"git://github.com/aviv86/ravendb.git","ssh_url":"git@github.com:aviv86/ravendb.git","clone_url":"https://github.com/aviv86/ravendb.git","svn_url":"https://github.com/aviv86/ravendb","homepage":"http://ravendb.net","size":434010,"stargazers_count":0,"watchers_count":0,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"v4.0"}},"base":{"label":"ravendb:v4.1","ref":"v4.1","sha":"3a3026c43702e3bc83f04f06a8e38b31430d0316","user":{"login":"ravendb","id":213792,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxMzc5Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/213792?v=4","gravatar_id":"","url":"https://api.github.com/users/ravendb","html_url":"https://github.com/ravendb","followers_url":"https://api.github.com/users/ravendb/followers","following_url":"https://api.github.com/users/ravendb/following{/other_user}","gists_url":"https://api.github.com/users/ravendb/gists{/gist_id}","starred_url":"https://api.github.com/users/ravendb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ravendb/subscriptions","organizations_url":"https://api.github.com/users/ravendb/orgs","repos_url":"https://api.github.com/users/ravendb/repos","events_url":"https://api.github.com/users/ravendb/events{/privacy}","received_events_url":"https://api.github.com/users/ravendb/received_events","type":"Organization","site_admin":false},"repo":{"id":542714,"node_id":"MDEwOlJlcG9zaXRvcnk1NDI3MTQ=","name":"ravendb","full_name":"ravendb/ravendb","owner":{"login":"ravendb","id":213792,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxMzc5Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/213792?v=4","gravatar_id":"","url":"https://api.github.com/users/ravendb","html_url":"https://github.com/ravendb","followers_url":"https://api.github.com/users/ravendb/followers","following_url":"https://api.github.com/users/ravendb/following{/other_user}","gists_url":"https://api.github.com/users/ravendb/gists{/gist_id}","starred_url":"https://api.github.com/users/ravendb/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ravendb/subscriptions","organizations_url":"https://api.github.com/users/ravendb/orgs","repos_url":"https://api.github.com/users/ravendb/repos","events_url":"https://api.github.com/users/ravendb/events{/privacy}","received_events_url":"https://api.github.com/users/ravendb/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ravendb/ravendb","description":"ACID Document Database","fork":false,"url":"https://api.github.com/repos/ravendb/ravendb","forks_url":"https://api.github.com/repos/ravendb/ravendb/forks","keys_url":"https://api.github.com/repos/ravendb/ravendb/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ravendb/ravendb/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ravendb/ravendb/teams","hooks_url":"https://api.github.com/repos/ravendb/ravendb/hooks","issue_events_url":"https://api.github.com/repos/ravendb/ravendb/issues/events{/number}","events_url":"https://api.github.com/repos/ravendb/ravendb/events","assignees_url":"https://api.github.com/repos/ravendb/ravendb/assignees{/user}","branches_url":"https://api.github.com/repos/ravendb/ravendb/branches{/branch}","tags_url":"https://api.github.com/repos/ravendb/ravendb/tags","blobs_url":"https://api.github.com/repos/ravendb/ravendb/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ravendb/ravendb/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ravendb/ravendb/git/refs{/sha}","trees_url":"https://api.github.com/repos/ravendb/ravendb/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ravendb/ravendb/statuses/{sha}","languages_url":"https://api.github.com/repos/ravendb/ravendb/languages","stargazers_url":"https://api.github.com/repos/ravendb/ravendb/stargazers","contributors_url":"https://api.github.com/repos/ravendb/ravendb/contributors","subscribers_url":"https://api.github.com/repos/ravendb/ravendb/subscribers","subscription_url":"https://api.github.com/repos/ravendb/ravendb/subscription","commits_url":"https://api.github.com/repos/ravendb/ravendb/commits{/sha}","git_commits_url":"https://api.github.com/repos/ravendb/ravendb/git/commits{/sha}","comments_url":"https://api.github.com/repos/ravendb/ravendb/comments{/number}","issue_comment_url":"https://api.github.com/repos/ravendb/ravendb/issues/comments{/number}","contents_url":"https://api.github.com/repos/ravendb/ravendb/contents/{+path}","compare_url":"https://api.github.com/repos/ravendb/ravendb/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ravendb/ravendb/merges","archive_url":"https://api.github.com/repos/ravendb/ravendb/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ravendb/ravendb/downloads","issues_url":"https://api.github.com/repos/ravendb/ravendb/issues{/number}","pulls_url":"https://api.github.com/repos/ravendb/ravendb/pulls{/number}","milestones_url":"https://api.github.com/repos/ravendb/ravendb/milestones{/number}","notifications_url":"https://api.github.com/repos/ravendb/ravendb/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ravendb/ravendb/labels{/name}","releases_url":"https://api.github.com/repos/ravendb/ravendb/releases{/id}","deployments_url":"https://api.github.com/repos/ravendb/ravendb/deployments","created_at":"2010-03-02T11:05:30Z","updated_at":"2018-06-14T13:38:42Z","pushed_at":"2018-06-14T15:44:30Z","git_url":"git://github.com/ravendb/ravendb.git","ssh_url":"git@github.com:ravendb/ravendb.git","clone_url":"https://github.com/ravendb/ravendb.git","svn_url":"https://github.com/ravendb/ravendb","homepage":"https://ravendb.net","size":440697,"stargazers_count":1950,"watchers_count":1950,"language":"C#","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":684,"mirror_url":null,"archived":false,"open_issues_count":2,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":684,"open_issues":2,"watchers":1950,"default_branch":"v4.0"}},"_links":{"self":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/6549"},"html":{"href":"https://github.com/ravendb/ravendb/pull/6549"},"issue":{"href":"https://api.github.com/repos/ravendb/ravendb/issues/6549"},"comments":{"href":"https://api.github.com/repos/ravendb/ravendb/issues/6549/comments"},"review_comments":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/6549/comments"},"review_comment":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ravendb/ravendb/pulls/6549/commits"},"statuses":{"href":"https://api.github.com/repos/ravendb/ravendb/statuses/eb70dbc316183eedbb3903307b3fa6c9d5659c48"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"ayende"}}