{"action":"created","comment":{"url":"https://api.github.com/repos/coreos/etcd/pulls/comments/28814268","id":28814268,"diff_hunk":"@@ -0,0 +1,476 @@\n+## Design\n+\n+1. Flatten binary key-value space\n+    \n+2. Keep the event history until compaction\n+    - access to old version of keys\n+    - user controlled history compaction\n+    \n+3. Support range query\n+    - Pagination support with limit argument\n+    \n+4. Replace TTL key with Lease\n+    - more efficient/ low cost keep alive\n+    - a logical group of TTL keys\n+    \n+5. Replace CAS/CAD with multi-object Tnx\n+    - MUCH MORE powerful and flexible\n+    \n+6. Support efficient watching with multiple ranges\n+\n+7. RPC API supports the completed set of APIs. \n+    - more efficient than JSON/HTTP\n+    - additional tnx/lease support\n+\n+8. HTTP API supports a subset of APIs.\n+    - easy for people to try out etcd\n+    - easy for people to write simple etcd application\n+\n+\n+## Protobuf Defined API\n+\n+``` protobuf\n+syntax = \"proto3\";\n+\n+// Interface exported by the server.\n+service etcd {\n+  // Range gets the keys in the range from the store.\n+  // Maybe rename it to GET?\n+  rpc Range(RangeRequest) returns (RangeResponse) {}\n+\n+  // Put puts the given key into the store.\n+  // A put request increases the index of the store,\n+  // and generates one event in the event history.\n+  rpc Put(PutRequest) returns (PutResponse) {}\n+\n+  // Delete deletes the given key from the store.\n+  // A delete request increase the index of the store,\n+  // and generates one event in the event history.\n+  rpc Delete(DeleteRequest) returns (DeleteResponse) {}\n+\n+  // Tnx processes all the requests in one transaction.\n+  // A tnx request increases the index of the store,\n+  // and generates one event in the event history.\n+  rpc Tnx(TnxRequest) returns (TnxResponse) {}\n+\n+  // Watch watches the events happening or happened in etcd. Both input and output\n+  // are stream. One watch rpc can watch for multiple ranges and get a stream of\n+  // events. The whole events history can be watched unless compacted.\n+  rpc Watch(stream WatchRequest) returns (stream WatchResponse) {}\n+\n+  // Compact compacts the event history in etcd. User should compact the\n+  // event history periodically, or it will grow infinitely.\n+  rpc Compact(CompactRequest) returns (CompactResponse) {}\n+\n+  // LeaseCreate creates a lease. A lease has a TTL. The lease will expire if the\n+  // server does not receive a keepAlive within TTL from the lease holder.\n+  // All keys attached to the lease will be expired and deleted if the lease expires.\n+  // The key expiration generates an event in event history.\n+  rpc LeaseCreate(LeaseCreateRequest) returns (LeaseCreateResponse) {}\n+\n+  // LeaseRevoke revokes a lease. All the key attached to the lease will be expired and deleted.\n+  rpc LeaseRevoke(LeaseRevokeRequest) returns (LeaseRevokeResponse) {}\n+\n+  // LeaseAttach attaches keys with a lease.\n+  rpc LeaseAttach(LeaseAttachRequest) returns (LeaseAttachResponse) {}\n+\n+  // LeaseTnx likes Tnx. It does one additional thing that all the keys put into the\n+  // store are attached with the given lease. This is rpc is useful when you want to\n+  // put a key and attach it to a lease atomically.\n+  rpc LeaseTnx(LeaseTnxRequest) returns (LeaseTnxResponse) {}\n+\n+  // KeepAlive keeps the lease alive.\n+  rpc LeaseKeepAlive(stream LeaseKeepAliveRequest) returns (stream LeaseKeepAliveResponse) {}\n+}\n+\n+message RequestHeader {\n+  // the cluster id to check with\n+  // if the cluster id is not matched, an error is returned.\n+  optional uint64 cluster_id = 1;\n+}\n+\n+message ResponseHeader {\n+  // an error type message?\n+  optional string error = 1;\n+  optional uint64 cluster_id = 2;\n+  optional uint64 member_id = 3;\n+  // index of the store when the request was applied.\n+  optional int64 index = 4;\n+  // term of raft when the request was applied.\n+  optional uint64 raft_term = 5;\n+}\n+\n+message RangeRequest {\n+  optional bytes key = 1;\n+  // if the end_key is not given, it is a get.\n+  // if the end_key is given, it gets the keys in range [key, end_key).\n+  optional bytes end_key = 2;\n+  // limit the number of keys returned.\n+  optional int64 limit = 3;\n+  // if not all the keys are returned, a continue id will be \n+  // returned in the range response if consistent is set.\n+  // the returned continue id only works with the previous \n+  // etcdserver the client connected to. \n+  optional bool consistent = 4\n+  // continue the previous range request in a consistent\n+  // manner if a continue id is provided.\n+  optional int64 continue_id = 5;\n+}\n+\n+message RangeResponse {\n+  optional ResponseHeader header = 1;\n+  repeated KeyValue kvs = 2;\n+  optional continue_id = 3;\n+  // the next range request with continue_id must\n+  // be issued with in continue_timeout to the\n+  // same server.\n+  optional continue_timeout = 4;\n+}\n+\n+message PutRequest {\n+  optional bytes key = 1;\n+  optional bytes value = 2;\n+}\n+\n+message PutResponse {\n+  optional ResponseHeader header = 1;\n+}\n+\n+message DeleteRequest {\n+  optional bytes key = 1;\n+}\n+\n+message DeleteResponse {\n+  optional ResponseHeader header = 1;\n+}\n+\n+message RequestUnion {\n+  oneof value {\n+    RangeRequest request_range = 1;\n+    PutRequest request_put = 2;\n+    DeleteRequest request_delete = 3;\n+  }\n+}\n+\n+message ResponseUnion {\n+  oneof value {","path":"Documentation/rfc/v3api.md","position":156,"original_position":156,"commit_id":"053517c8eff37b91e3fe7eb513475b447d512db6","original_commit_id":"053517c8eff37b91e3fe7eb513475b447d512db6","user":{"login":"barakmich","id":98356,"avatar_url":"https://avatars.githubusercontent.com/u/98356?v=3","gravatar_id":"","url":"https://api.github.com/users/barakmich","html_url":"https://github.com/barakmich","followers_url":"https://api.github.com/users/barakmich/followers","following_url":"https://api.github.com/users/barakmich/following{/other_user}","gists_url":"https://api.github.com/users/barakmich/gists{/gist_id}","starred_url":"https://api.github.com/users/barakmich/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/barakmich/subscriptions","organizations_url":"https://api.github.com/users/barakmich/orgs","repos_url":"https://api.github.com/users/barakmich/repos","events_url":"https://api.github.com/users/barakmich/events{/privacy}","received_events_url":"https://api.github.com/users/barakmich/received_events","type":"User","site_admin":false},"body":"Are leases not things that can be transacted upon?","created_at":"2015-04-21T19:39:11Z","updated_at":"2015-04-21T19:39:11Z","html_url":"https://github.com/coreos/etcd/pull/2675#discussion_r28814268","pull_request_url":"https://api.github.com/repos/coreos/etcd/pulls/2675","_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments/28814268"},"html":{"href":"https://github.com/coreos/etcd/pull/2675#discussion_r28814268"},"pull_request":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2675"}}},"pull_request":{"url":"https://api.github.com/repos/coreos/etcd/pulls/2675","id":33223406,"html_url":"https://github.com/coreos/etcd/pull/2675","diff_url":"https://github.com/coreos/etcd/pull/2675.diff","patch_url":"https://github.com/coreos/etcd/pull/2675.patch","issue_url":"https://api.github.com/repos/coreos/etcd/issues/2675","number":2675,"state":"open","locked":false,"title":"doc: v3api rfc","user":{"login":"xiang90","id":4479947,"avatar_url":"https://avatars.githubusercontent.com/u/4479947?v=3","gravatar_id":"","url":"https://api.github.com/users/xiang90","html_url":"https://github.com/xiang90","followers_url":"https://api.github.com/users/xiang90/followers","following_url":"https://api.github.com/users/xiang90/following{/other_user}","gists_url":"https://api.github.com/users/xiang90/gists{/gist_id}","starred_url":"https://api.github.com/users/xiang90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiang90/subscriptions","organizations_url":"https://api.github.com/users/xiang90/orgs","repos_url":"https://api.github.com/users/xiang90/repos","events_url":"https://api.github.com/users/xiang90/events{/privacy}","received_events_url":"https://api.github.com/users/xiang90/received_events","type":"User","site_admin":false},"body":"This is a real Request For Comments thing. \r\n\r\nAll feedbacks are welcomed! Any question are also welcomed!\r\n\r\n```\r\nWe have been working really hard on the internal raft. As the new raft getting stable, we are starting to design the new API/store for etcd.\r\n\r\nHere are the feature requests from the community that we plan to support:\r\n\r\nOptimistic concurrency GoogleCloudPlatform/kubernetes#1957 (comment)\r\nAccess to past versions of objects (after history compaction) GoogleCloudPlatform/kubernetes#1957 (comment)\r\nEfficient reliable and recursive watch GoogleCloudPlatform/kubernetes#1957 (comment)\r\nMulti-object transactions #1282 #860 #652\r\nThe ability to somehow build multiple indices #860 #1548\r\nPagination support GoogleCloudPlatform/kubernetes#1957 (comment)\r\nLow per-object memory footprint GoogleCloudPlatform/kubernetes#1957 (comment)\r\nObject TTLs (for events, logically deleted objects) #1232\r\nAllow clients to request watch heartbeats to refresh the clients window #2048\r\nBinary key and value #1548\r\nOn-disk storage #732\r\n```\r\n\r\nFor #2647","created_at":"2015-04-14T03:19:25Z","updated_at":"2015-04-21T19:39:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ed801d0a6bc318bdab608d3e8e0dc4d8e309fb67","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/coreos/etcd/pulls/2675/commits","review_comments_url":"https://api.github.com/repos/coreos/etcd/pulls/2675/comments","review_comment_url":"https://api.github.com/repos/coreos/etcd/pulls/comments{/number}","comments_url":"https://api.github.com/repos/coreos/etcd/issues/2675/comments","statuses_url":"https://api.github.com/repos/coreos/etcd/statuses/053517c8eff37b91e3fe7eb513475b447d512db6","head":{"label":"xiang90:v3rfc","ref":"v3rfc","sha":"053517c8eff37b91e3fe7eb513475b447d512db6","user":{"login":"xiang90","id":4479947,"avatar_url":"https://avatars.githubusercontent.com/u/4479947?v=3","gravatar_id":"","url":"https://api.github.com/users/xiang90","html_url":"https://github.com/xiang90","followers_url":"https://api.github.com/users/xiang90/followers","following_url":"https://api.github.com/users/xiang90/following{/other_user}","gists_url":"https://api.github.com/users/xiang90/gists{/gist_id}","starred_url":"https://api.github.com/users/xiang90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiang90/subscriptions","organizations_url":"https://api.github.com/users/xiang90/orgs","repos_url":"https://api.github.com/users/xiang90/repos","events_url":"https://api.github.com/users/xiang90/events{/privacy}","received_events_url":"https://api.github.com/users/xiang90/received_events","type":"User","site_admin":false},"repo":{"id":11245678,"name":"etcd","full_name":"xiang90/etcd","owner":{"login":"xiang90","id":4479947,"avatar_url":"https://avatars.githubusercontent.com/u/4479947?v=3","gravatar_id":"","url":"https://api.github.com/users/xiang90","html_url":"https://github.com/xiang90","followers_url":"https://api.github.com/users/xiang90/followers","following_url":"https://api.github.com/users/xiang90/following{/other_user}","gists_url":"https://api.github.com/users/xiang90/gists{/gist_id}","starred_url":"https://api.github.com/users/xiang90/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xiang90/subscriptions","organizations_url":"https://api.github.com/users/xiang90/orgs","repos_url":"https://api.github.com/users/xiang90/repos","events_url":"https://api.github.com/users/xiang90/events{/privacy}","received_events_url":"https://api.github.com/users/xiang90/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/xiang90/etcd","description":null,"fork":true,"url":"https://api.github.com/repos/xiang90/etcd","forks_url":"https://api.github.com/repos/xiang90/etcd/forks","keys_url":"https://api.github.com/repos/xiang90/etcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/xiang90/etcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/xiang90/etcd/teams","hooks_url":"https://api.github.com/repos/xiang90/etcd/hooks","issue_events_url":"https://api.github.com/repos/xiang90/etcd/issues/events{/number}","events_url":"https://api.github.com/repos/xiang90/etcd/events","assignees_url":"https://api.github.com/repos/xiang90/etcd/assignees{/user}","branches_url":"https://api.github.com/repos/xiang90/etcd/branches{/branch}","tags_url":"https://api.github.com/repos/xiang90/etcd/tags","blobs_url":"https://api.github.com/repos/xiang90/etcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/xiang90/etcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/xiang90/etcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/xiang90/etcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/xiang90/etcd/statuses/{sha}","languages_url":"https://api.github.com/repos/xiang90/etcd/languages","stargazers_url":"https://api.github.com/repos/xiang90/etcd/stargazers","contributors_url":"https://api.github.com/repos/xiang90/etcd/contributors","subscribers_url":"https://api.github.com/repos/xiang90/etcd/subscribers","subscription_url":"https://api.github.com/repos/xiang90/etcd/subscription","commits_url":"https://api.github.com/repos/xiang90/etcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/xiang90/etcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/xiang90/etcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/xiang90/etcd/issues/comments{/number}","contents_url":"https://api.github.com/repos/xiang90/etcd/contents/{+path}","compare_url":"https://api.github.com/repos/xiang90/etcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/xiang90/etcd/merges","archive_url":"https://api.github.com/repos/xiang90/etcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/xiang90/etcd/downloads","issues_url":"https://api.github.com/repos/xiang90/etcd/issues{/number}","pulls_url":"https://api.github.com/repos/xiang90/etcd/pulls{/number}","milestones_url":"https://api.github.com/repos/xiang90/etcd/milestones{/number}","notifications_url":"https://api.github.com/repos/xiang90/etcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/xiang90/etcd/labels{/name}","releases_url":"https://api.github.com/repos/xiang90/etcd/releases{/id}","created_at":"2013-07-08T04:17:14Z","updated_at":"2014-12-15T22:29:22Z","pushed_at":"2015-04-21T19:22:29Z","git_url":"git://github.com/xiang90/etcd.git","ssh_url":"git@github.com:xiang90/etcd.git","clone_url":"https://github.com/xiang90/etcd.git","svn_url":"https://github.com/xiang90/etcd","homepage":null,"size":18768,"stargazers_count":4,"watchers_count":4,"language":"Go","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":4,"default_branch":"master"}},"base":{"label":"coreos:master","ref":"master","sha":"b99c80874f76384fd139bdc91633d4658905c498","user":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=3","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"repo":{"id":11225014,"name":"etcd","full_name":"coreos/etcd","owner":{"login":"coreos","id":3730757,"avatar_url":"https://avatars.githubusercontent.com/u/3730757?v=3","gravatar_id":"","url":"https://api.github.com/users/coreos","html_url":"https://github.com/coreos","followers_url":"https://api.github.com/users/coreos/followers","following_url":"https://api.github.com/users/coreos/following{/other_user}","gists_url":"https://api.github.com/users/coreos/gists{/gist_id}","starred_url":"https://api.github.com/users/coreos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coreos/subscriptions","organizations_url":"https://api.github.com/users/coreos/orgs","repos_url":"https://api.github.com/users/coreos/repos","events_url":"https://api.github.com/users/coreos/events{/privacy}","received_events_url":"https://api.github.com/users/coreos/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/coreos/etcd","description":"A highly-available key value store for shared configuration and service discovery","fork":false,"url":"https://api.github.com/repos/coreos/etcd","forks_url":"https://api.github.com/repos/coreos/etcd/forks","keys_url":"https://api.github.com/repos/coreos/etcd/keys{/key_id}","collaborators_url":"https://api.github.com/repos/coreos/etcd/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/coreos/etcd/teams","hooks_url":"https://api.github.com/repos/coreos/etcd/hooks","issue_events_url":"https://api.github.com/repos/coreos/etcd/issues/events{/number}","events_url":"https://api.github.com/repos/coreos/etcd/events","assignees_url":"https://api.github.com/repos/coreos/etcd/assignees{/user}","branches_url":"https://api.github.com/repos/coreos/etcd/branches{/branch}","tags_url":"https://api.github.com/repos/coreos/etcd/tags","blobs_url":"https://api.github.com/repos/coreos/etcd/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/coreos/etcd/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/coreos/etcd/git/refs{/sha}","trees_url":"https://api.github.com/repos/coreos/etcd/git/trees{/sha}","statuses_url":"https://api.github.com/repos/coreos/etcd/statuses/{sha}","languages_url":"https://api.github.com/repos/coreos/etcd/languages","stargazers_url":"https://api.github.com/repos/coreos/etcd/stargazers","contributors_url":"https://api.github.com/repos/coreos/etcd/contributors","subscribers_url":"https://api.github.com/repos/coreos/etcd/subscribers","subscription_url":"https://api.github.com/repos/coreos/etcd/subscription","commits_url":"https://api.github.com/repos/coreos/etcd/commits{/sha}","git_commits_url":"https://api.github.com/repos/coreos/etcd/git/commits{/sha}","comments_url":"https://api.github.com/repos/coreos/etcd/comments{/number}","issue_comment_url":"https://api.github.com/repos/coreos/etcd/issues/comments{/number}","contents_url":"https://api.github.com/repos/coreos/etcd/contents/{+path}","compare_url":"https://api.github.com/repos/coreos/etcd/compare/{base}...{head}","merges_url":"https://api.github.com/repos/coreos/etcd/merges","archive_url":"https://api.github.com/repos/coreos/etcd/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/coreos/etcd/downloads","issues_url":"https://api.github.com/repos/coreos/etcd/issues{/number}","pulls_url":"https://api.github.com/repos/coreos/etcd/pulls{/number}","milestones_url":"https://api.github.com/repos/coreos/etcd/milestones{/number}","notifications_url":"https://api.github.com/repos/coreos/etcd/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/coreos/etcd/labels{/name}","releases_url":"https://api.github.com/repos/coreos/etcd/releases{/id}","created_at":"2013-07-06T21:57:21Z","updated_at":"2015-04-21T19:35:51Z","pushed_at":"2015-04-21T19:22:30Z","git_url":"git://github.com/coreos/etcd.git","ssh_url":"git@github.com:coreos/etcd.git","clone_url":"https://github.com/coreos/etcd.git","svn_url":"https://github.com/coreos/etcd","homepage":"","size":32142,"stargazers_count":6214,"watchers_count":6214,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":784,"mirror_url":null,"open_issues_count":159,"forks":784,"open_issues":159,"watchers":6214,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2675"},"html":{"href":"https://github.com/coreos/etcd/pull/2675"},"issue":{"href":"https://api.github.com/repos/coreos/etcd/issues/2675"},"comments":{"href":"https://api.github.com/repos/coreos/etcd/issues/2675/comments"},"review_comments":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2675/comments"},"review_comment":{"href":"https://api.github.com/repos/coreos/etcd/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/coreos/etcd/pulls/2675/commits"},"statuses":{"href":"https://api.github.com/repos/coreos/etcd/statuses/053517c8eff37b91e3fe7eb513475b447d512db6"}}}}