{"action":"created","comment":{"url":"https://api.github.com/repos/ehcache/ehcache3/pulls/comments/58245664","id":58245664,"diff_hunk":"@@ -0,0 +1,174 @@\n+= Clustered Ehcache Server Side Data Store and Operation API Proposal\n+\n+This document outlines a proposal for storing, retrieving and mutating cache\n+state stored within the Voltron server.  First I will outline the basics of the\n+proposal, then I will give some examples of its usage to implement a variety of\n+single key operations on the cache.  Finally I will outline some implementation\n+decisions we may face around performance tradeoffs with the proposal.\n+\n+== The Proposal\n+\n+Ehcache supports an open type system on its keys.  This means users can use any\n+'serializable' type as a key, this in turn means the server cannot perform\n+equals comparisons on keys (or values in the case of concurrent operations).\n+Therefore to support equality comparison on clients without performing CAS loops\n+or taking exclusive locks across a network this scheme has been proposed.\n+\n+== Server Side Data Structure\n+\n+The server will store cache data as a multi-map where the key is the cache-key\n+hash (minimally just the Java hashcode, but potentially something wider than\n+that), and the value is a sequence of binary payloads:\n+\n+[\"ditaa\", \"server-data-structure\", \"png\"]\n+--------------------------------------------------------------------------------\n+             +----+    +----------------------------------------------+\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             |hash| => | |binary blob| |binary blob| |binary blob| ...|\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             +----+    +----------------------------------------------+\n+\n+             +----+    +----------------------------------------------+\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             |hash| => | |binary blob| |binary blob| |binary blob| ...|\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             +----+    +----------------------------------------------+\n+\n+             +----+    +----------------------------------------------+\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             |hash| => | |binary blob| |binary blob| |binary blob| ...|\n+             |    |    | +-----------+ +-----------+ +-----------+    |\n+             +----+    +----------------------------------------------+\n+--------------------------------------------------------------------------------\n+\n+The server supports the following operations:\n+\n+ * `List<binary-blob> get(hash)`: returns the list for the given hash\n+ * `void append(hash, binary-blob)`: adds the given binary blob to the end of\n+   the list for the given hash\n+ * `list<binary-blob> getAndAppend(hash, binary-blob)`: the same as append but\n+   also returns the list immediately prior to mutation (atomically).\n+ * `void replace(hash, list<binary-blob>, list<binary-blob>)`: replaces the\n+   first occurrence of the given subsequence with the supplied sequence\n+\n+This is the entirety of the functionality and data structure exposed to the\n+client that is of relevance to single key operations.\n+\n+== Client Side Interpretation\n+\n+The server side view of the data structure above is fairly primitive.  The\n+client however, understands the structure within the binary blobs, and so has\n+a much richer picture of what this data structure presents.\n+\n+[\"ditaa\", \"client-data-structure\", \"png\"]\n+--------------------------------------------------------------------------------\n+      +----+    +----------------------------------------------------------+\n+      |    |    | +------+ /----------\\ +------+ /----------\\ /----------\\ |\n+      |hash| => | |k1, v1| |k1, f(k,v)| |k2, v1| |k1, g(k,v)| |k2, f(k,v)| |\n+      |    |    | +------+ \\----------/ +------+ \\----------/ \\----------/ |\n+      +----+    +----------------------------------------------------------+\n+                                             |\n+                                             V\n+                +----------------------------------------------------------+\n+                |                       +------+              /----------\\ |\n+                |                       |k2, v1|              |k2, f(k,v)| |\n+                |                       +------+              \\----------/ |\n+                +----------------------------------------------------------+\n+                                             +\n+                +----------------------------------------------------------+\n+                | +------+ /----------\\          /----------\\              |\n+                | |k1, v1| |k1, f(k,v)|          |k1, g(k,v)|              |\n+                | +------+ \\----------/          \\----------/              |\n+                +----------------------------------------------------------+\n+--------------------------------------------------------------------------------\n+\n+The structure above is interpreted by the client as meaning the current value of\n+the k1 mapping is `g(f({k1, v1}))`, and that of the k2 mappings is\n+`f({k2, v1}`.  More generally the current value of a mapping is always equal\n+to a recursive application of the functions in its sequence (treating the\n+'value' as an initial generator function).\n+\n+At this point we define a critical client side operation:\n+\n+[source]\n+----\n+value resolve(chain, key) {\n+  resolved = [];\n+  transform = () -> {};\n+  for (function f : chain)) {\n+    if (f.for(key)) {\n+      transform = transform.andThen(f);\n+    } else {\n+      resolved.add(f);\n+    }\n+  }\n+  value = transform.apply();\n+  resolved.add(value)\n+\n+  asynchronously(server.replace(key.hash, chain, resolved));\n+\n+  return value;\n+}\n+----\n+\n+Invocation of this operation resolves the current value of the key, and\n+asynchronously updates the servers representation:\n+\n+[\"ditaa\", \"resolve-operation\", \"png\"]\n+--------------------------------------------------------------------------------\n+      +----+    +----------------------------------------------------------+\n+      |    |    | +------+ /----------\\ +------+ /----------\\ /----------\\ |\n+      |hash| => | |k1, v1| |k1, f(k,v)| |k2, v1| |k1, g(k,v)| |k2, f(k,v)| |\n+      |    |    | +------+ \\----------/ +------+ \\----------/ \\----------/ |\n+      +----+    +----------------------------------------------------------+\n+                                             |\n+\n+                                     resolve(chain, k1)\n+\n+                                             |\n+                                             V\n+                            +--------------------------------+\n+                            | +------+ /----------\\ +------+ |\n+                            | |k2, v1| |k2, f(k,v)| |k1, v2| |\n+                            | +------+ \\----------/ +------+ |\n+                            +--------------------------------+\n+                                             |\n+\n+                                     resolve(chain, k2)\n+\n+                                             |\n+                                             V\n+                                   +-------------------+\n+                                   | +------+ +------+ |\n+                                   | |k1, v2| |k2, v2| |\n+                                   | +------+ +------+ |\n+                                   +-------------------+\n+--------------------------------------------------------------------------------\n+\n+== Example Operations\n+\n+[source]\n+----\n+void put(key, value) {\n+  server.append(key.hash, function(put(key, value)));\n+}\n+\n+value get(key) {\n+  return resolve(server.get(key.hash), key);\n+}\n+\n+value putIfAbsent(key, value) {\n+  return resolve(server.getAndAppend(key.hash, operation(putIfAbsent(key, value))), key);\n+}\n+----","path":"docs/src/docs/asciidoc/developer/clustered.adoc","position":163,"original_position":163,"commit_id":"f10d6909f7146c0f44c6f648f14a75f5066555cf","original_commit_id":"f10d6909f7146c0f44c6f648f14a75f5066555cf","user":{"login":"jhouserizer","id":1182369,"avatar_url":"https://avatars.githubusercontent.com/u/1182369?v=3","gravatar_id":"","url":"https://api.github.com/users/jhouserizer","html_url":"https://github.com/jhouserizer","followers_url":"https://api.github.com/users/jhouserizer/followers","following_url":"https://api.github.com/users/jhouserizer/following{/other_user}","gists_url":"https://api.github.com/users/jhouserizer/gists{/gist_id}","starred_url":"https://api.github.com/users/jhouserizer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jhouserizer/subscriptions","organizations_url":"https://api.github.com/users/jhouserizer/orgs","repos_url":"https://api.github.com/users/jhouserizer/repos","events_url":"https://api.github.com/users/jhouserizer/events{/privacy}","received_events_url":"https://api.github.com/users/jhouserizer/received_events","type":"User","site_admin":false},"body":"I had the same comment/question when talking this scheme through with Chris the other day.  He had an answer to it, that was a bit hand-wavey :)  but which sounded ok.   The server could 'notice' that the list related to a hash is getting very long and send a message to a client requesting it to do some resolve()ing for the given hash, which the client would then do.  Presumably it could do this noticing just as a client is doing an append() on that hash - so the server would then know a good candidate of a client to choose for doing the resolve().","created_at":"2016-04-01T18:17:11Z","updated_at":"2016-04-01T18:17:11Z","html_url":"https://github.com/ehcache/ehcache3/pull/914#discussion_r58245664","pull_request_url":"https://api.github.com/repos/ehcache/ehcache3/pulls/914","_links":{"self":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/comments/58245664"},"html":{"href":"https://github.com/ehcache/ehcache3/pull/914#discussion_r58245664"},"pull_request":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/914"}}},"pull_request":{"url":"https://api.github.com/repos/ehcache/ehcache3/pulls/914","id":64868706,"html_url":"https://github.com/ehcache/ehcache3/pull/914","diff_url":"https://github.com/ehcache/ehcache3/pull/914.diff","patch_url":"https://github.com/ehcache/ehcache3/pull/914.patch","issue_url":"https://api.github.com/repos/ehcache/ehcache3/issues/914","number":914,"state":"open","locked":false,"title":"Initial proposal on clustered cache operations","user":{"login":"chrisdennis","id":954331,"avatar_url":"https://avatars.githubusercontent.com/u/954331?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdennis","html_url":"https://github.com/chrisdennis","followers_url":"https://api.github.com/users/chrisdennis/followers","following_url":"https://api.github.com/users/chrisdennis/following{/other_user}","gists_url":"https://api.github.com/users/chrisdennis/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdennis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdennis/subscriptions","organizations_url":"https://api.github.com/users/chrisdennis/orgs","repos_url":"https://api.github.com/users/chrisdennis/repos","events_url":"https://api.github.com/users/chrisdennis/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdennis/received_events","type":"User","site_admin":false},"body":"Please place your review requirements here.  If you'd prefer a rendered copy then feel free to fetch and render at your leisure.","created_at":"2016-03-31T22:21:04Z","updated_at":"2016-04-01T18:17:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ab23a65a94314d93bd8075cb76d34fd88b95be2f","assignee":null,"milestone":{"url":"https://api.github.com/repos/ehcache/ehcache3/milestones/14","html_url":"https://github.com/ehcache/ehcache3/milestones/BF-4577","labels_url":"https://api.github.com/repos/ehcache/ehcache3/milestones/14/labels","id":1672016,"number":14,"title":"BF-4577","description":"Put & Get data within a clustered cache in strong consistency mode.","creator":{"login":"chrisdennis","id":954331,"avatar_url":"https://avatars.githubusercontent.com/u/954331?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdennis","html_url":"https://github.com/chrisdennis","followers_url":"https://api.github.com/users/chrisdennis/followers","following_url":"https://api.github.com/users/chrisdennis/following{/other_user}","gists_url":"https://api.github.com/users/chrisdennis/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdennis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdennis/subscriptions","organizations_url":"https://api.github.com/users/chrisdennis/orgs","repos_url":"https://api.github.com/users/chrisdennis/repos","events_url":"https://api.github.com/users/chrisdennis/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdennis/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":0,"state":"open","created_at":"2016-03-29T14:47:18Z","updated_at":"2016-03-31T22:21:04Z","due_on":null,"closed_at":null},"commits_url":"https://api.github.com/repos/ehcache/ehcache3/pulls/914/commits","review_comments_url":"https://api.github.com/repos/ehcache/ehcache3/pulls/914/comments","review_comment_url":"https://api.github.com/repos/ehcache/ehcache3/pulls/comments{/number}","comments_url":"https://api.github.com/repos/ehcache/ehcache3/issues/914/comments","statuses_url":"https://api.github.com/repos/ehcache/ehcache3/statuses/f10d6909f7146c0f44c6f648f14a75f5066555cf","head":{"label":"chrisdennis:clustered_ops_proposal","ref":"clustered_ops_proposal","sha":"f10d6909f7146c0f44c6f648f14a75f5066555cf","user":{"login":"chrisdennis","id":954331,"avatar_url":"https://avatars.githubusercontent.com/u/954331?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdennis","html_url":"https://github.com/chrisdennis","followers_url":"https://api.github.com/users/chrisdennis/followers","following_url":"https://api.github.com/users/chrisdennis/following{/other_user}","gists_url":"https://api.github.com/users/chrisdennis/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdennis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdennis/subscriptions","organizations_url":"https://api.github.com/users/chrisdennis/orgs","repos_url":"https://api.github.com/users/chrisdennis/repos","events_url":"https://api.github.com/users/chrisdennis/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdennis/received_events","type":"User","site_admin":false},"repo":{"id":22694171,"name":"ehcache3","full_name":"chrisdennis/ehcache3","owner":{"login":"chrisdennis","id":954331,"avatar_url":"https://avatars.githubusercontent.com/u/954331?v=3","gravatar_id":"","url":"https://api.github.com/users/chrisdennis","html_url":"https://github.com/chrisdennis","followers_url":"https://api.github.com/users/chrisdennis/followers","following_url":"https://api.github.com/users/chrisdennis/following{/other_user}","gists_url":"https://api.github.com/users/chrisdennis/gists{/gist_id}","starred_url":"https://api.github.com/users/chrisdennis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/chrisdennis/subscriptions","organizations_url":"https://api.github.com/users/chrisdennis/orgs","repos_url":"https://api.github.com/users/chrisdennis/repos","events_url":"https://api.github.com/users/chrisdennis/events{/privacy}","received_events_url":"https://api.github.com/users/chrisdennis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/chrisdennis/ehcache3","description":"Ehcache 3.x line ","fork":true,"url":"https://api.github.com/repos/chrisdennis/ehcache3","forks_url":"https://api.github.com/repos/chrisdennis/ehcache3/forks","keys_url":"https://api.github.com/repos/chrisdennis/ehcache3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/chrisdennis/ehcache3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/chrisdennis/ehcache3/teams","hooks_url":"https://api.github.com/repos/chrisdennis/ehcache3/hooks","issue_events_url":"https://api.github.com/repos/chrisdennis/ehcache3/issues/events{/number}","events_url":"https://api.github.com/repos/chrisdennis/ehcache3/events","assignees_url":"https://api.github.com/repos/chrisdennis/ehcache3/assignees{/user}","branches_url":"https://api.github.com/repos/chrisdennis/ehcache3/branches{/branch}","tags_url":"https://api.github.com/repos/chrisdennis/ehcache3/tags","blobs_url":"https://api.github.com/repos/chrisdennis/ehcache3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/chrisdennis/ehcache3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/chrisdennis/ehcache3/git/refs{/sha}","trees_url":"https://api.github.com/repos/chrisdennis/ehcache3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/chrisdennis/ehcache3/statuses/{sha}","languages_url":"https://api.github.com/repos/chrisdennis/ehcache3/languages","stargazers_url":"https://api.github.com/repos/chrisdennis/ehcache3/stargazers","contributors_url":"https://api.github.com/repos/chrisdennis/ehcache3/contributors","subscribers_url":"https://api.github.com/repos/chrisdennis/ehcache3/subscribers","subscription_url":"https://api.github.com/repos/chrisdennis/ehcache3/subscription","commits_url":"https://api.github.com/repos/chrisdennis/ehcache3/commits{/sha}","git_commits_url":"https://api.github.com/repos/chrisdennis/ehcache3/git/commits{/sha}","comments_url":"https://api.github.com/repos/chrisdennis/ehcache3/comments{/number}","issue_comment_url":"https://api.github.com/repos/chrisdennis/ehcache3/issues/comments{/number}","contents_url":"https://api.github.com/repos/chrisdennis/ehcache3/contents/{+path}","compare_url":"https://api.github.com/repos/chrisdennis/ehcache3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/chrisdennis/ehcache3/merges","archive_url":"https://api.github.com/repos/chrisdennis/ehcache3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/chrisdennis/ehcache3/downloads","issues_url":"https://api.github.com/repos/chrisdennis/ehcache3/issues{/number}","pulls_url":"https://api.github.com/repos/chrisdennis/ehcache3/pulls{/number}","milestones_url":"https://api.github.com/repos/chrisdennis/ehcache3/milestones{/number}","notifications_url":"https://api.github.com/repos/chrisdennis/ehcache3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/chrisdennis/ehcache3/labels{/name}","releases_url":"https://api.github.com/repos/chrisdennis/ehcache3/releases{/id}","deployments_url":"https://api.github.com/repos/chrisdennis/ehcache3/deployments","created_at":"2014-08-06T18:50:40Z","updated_at":"2016-01-15T15:51:26Z","pushed_at":"2016-04-01T13:26:08Z","git_url":"git://github.com/chrisdennis/ehcache3.git","ssh_url":"git@github.com:chrisdennis/ehcache3.git","clone_url":"https://github.com/chrisdennis/ehcache3.git","svn_url":"https://github.com/chrisdennis/ehcache3","homepage":"ehcache.org","size":7949,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"ehcache:master","ref":"master","sha":"f36f807f8b3fa8b6fd1e204495ec54a914b5f43a","user":{"login":"ehcache","id":5504982,"avatar_url":"https://avatars.githubusercontent.com/u/5504982?v=3","gravatar_id":"","url":"https://api.github.com/users/ehcache","html_url":"https://github.com/ehcache","followers_url":"https://api.github.com/users/ehcache/followers","following_url":"https://api.github.com/users/ehcache/following{/other_user}","gists_url":"https://api.github.com/users/ehcache/gists{/gist_id}","starred_url":"https://api.github.com/users/ehcache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehcache/subscriptions","organizations_url":"https://api.github.com/users/ehcache/orgs","repos_url":"https://api.github.com/users/ehcache/repos","events_url":"https://api.github.com/users/ehcache/events{/privacy}","received_events_url":"https://api.github.com/users/ehcache/received_events","type":"Organization","site_admin":false},"repo":{"id":17224514,"name":"ehcache3","full_name":"ehcache/ehcache3","owner":{"login":"ehcache","id":5504982,"avatar_url":"https://avatars.githubusercontent.com/u/5504982?v=3","gravatar_id":"","url":"https://api.github.com/users/ehcache","html_url":"https://github.com/ehcache","followers_url":"https://api.github.com/users/ehcache/followers","following_url":"https://api.github.com/users/ehcache/following{/other_user}","gists_url":"https://api.github.com/users/ehcache/gists{/gist_id}","starred_url":"https://api.github.com/users/ehcache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ehcache/subscriptions","organizations_url":"https://api.github.com/users/ehcache/orgs","repos_url":"https://api.github.com/users/ehcache/repos","events_url":"https://api.github.com/users/ehcache/events{/privacy}","received_events_url":"https://api.github.com/users/ehcache/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/ehcache/ehcache3","description":"Ehcache 3.x line ","fork":false,"url":"https://api.github.com/repos/ehcache/ehcache3","forks_url":"https://api.github.com/repos/ehcache/ehcache3/forks","keys_url":"https://api.github.com/repos/ehcache/ehcache3/keys{/key_id}","collaborators_url":"https://api.github.com/repos/ehcache/ehcache3/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/ehcache/ehcache3/teams","hooks_url":"https://api.github.com/repos/ehcache/ehcache3/hooks","issue_events_url":"https://api.github.com/repos/ehcache/ehcache3/issues/events{/number}","events_url":"https://api.github.com/repos/ehcache/ehcache3/events","assignees_url":"https://api.github.com/repos/ehcache/ehcache3/assignees{/user}","branches_url":"https://api.github.com/repos/ehcache/ehcache3/branches{/branch}","tags_url":"https://api.github.com/repos/ehcache/ehcache3/tags","blobs_url":"https://api.github.com/repos/ehcache/ehcache3/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/ehcache/ehcache3/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/ehcache/ehcache3/git/refs{/sha}","trees_url":"https://api.github.com/repos/ehcache/ehcache3/git/trees{/sha}","statuses_url":"https://api.github.com/repos/ehcache/ehcache3/statuses/{sha}","languages_url":"https://api.github.com/repos/ehcache/ehcache3/languages","stargazers_url":"https://api.github.com/repos/ehcache/ehcache3/stargazers","contributors_url":"https://api.github.com/repos/ehcache/ehcache3/contributors","subscribers_url":"https://api.github.com/repos/ehcache/ehcache3/subscribers","subscription_url":"https://api.github.com/repos/ehcache/ehcache3/subscription","commits_url":"https://api.github.com/repos/ehcache/ehcache3/commits{/sha}","git_commits_url":"https://api.github.com/repos/ehcache/ehcache3/git/commits{/sha}","comments_url":"https://api.github.com/repos/ehcache/ehcache3/comments{/number}","issue_comment_url":"https://api.github.com/repos/ehcache/ehcache3/issues/comments{/number}","contents_url":"https://api.github.com/repos/ehcache/ehcache3/contents/{+path}","compare_url":"https://api.github.com/repos/ehcache/ehcache3/compare/{base}...{head}","merges_url":"https://api.github.com/repos/ehcache/ehcache3/merges","archive_url":"https://api.github.com/repos/ehcache/ehcache3/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/ehcache/ehcache3/downloads","issues_url":"https://api.github.com/repos/ehcache/ehcache3/issues{/number}","pulls_url":"https://api.github.com/repos/ehcache/ehcache3/pulls{/number}","milestones_url":"https://api.github.com/repos/ehcache/ehcache3/milestones{/number}","notifications_url":"https://api.github.com/repos/ehcache/ehcache3/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/ehcache/ehcache3/labels{/name}","releases_url":"https://api.github.com/repos/ehcache/ehcache3/releases{/id}","deployments_url":"https://api.github.com/repos/ehcache/ehcache3/deployments","created_at":"2014-02-26T20:39:16Z","updated_at":"2016-03-30T18:33:01Z","pushed_at":"2016-04-01T13:26:08Z","git_url":"git://github.com/ehcache/ehcache3.git","ssh_url":"git@github.com:ehcache/ehcache3.git","clone_url":"https://github.com/ehcache/ehcache3.git","svn_url":"https://github.com/ehcache/ehcache3","homepage":"http://www.ehcache.org","size":10183,"stargazers_count":327,"watchers_count":327,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":183,"mirror_url":null,"open_issues_count":59,"forks":183,"open_issues":59,"watchers":327,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/914"},"html":{"href":"https://github.com/ehcache/ehcache3/pull/914"},"issue":{"href":"https://api.github.com/repos/ehcache/ehcache3/issues/914"},"comments":{"href":"https://api.github.com/repos/ehcache/ehcache3/issues/914/comments"},"review_comments":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/914/comments"},"review_comment":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/ehcache/ehcache3/pulls/914/commits"},"statuses":{"href":"https://api.github.com/repos/ehcache/ehcache3/statuses/f10d6909f7146c0f44c6f648f14a75f5066555cf"}}}}