{"action":"created","comment":{"url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/comments/221313184","pull_request_review_id":159936725,"id":221313184,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyMTMxMzE4NA==","diff_hunk":"@@ -0,0 +1,65 @@\n+package pstoreds\n+\n+import (\n+\t\"bytes\"\n+\t\"context\"\n+\t\"encoding/gob\"\n+\n+\tds \"github.com/ipfs/go-datastore\"\n+\n+\tpool \"github.com/libp2p/go-buffer-pool\"\n+\tpeer \"github.com/libp2p/go-libp2p-peer\"\n+\tpstore \"github.com/libp2p/go-libp2p-peerstore\"\n+)\n+\n+// Metadata is stored under the following db key pattern:\n+// /peers/metadata/<b58 peer id>/<key>\n+var pmBase = ds.NewKey(\"/peers/metadata\")\n+\n+type dsPeerMetadata struct {\n+\tds ds.Datastore\n+}\n+\n+var _ pstore.PeerMetadata = (*dsPeerMetadata)(nil)\n+\n+func init() {\n+\t// Gob registers basic types by default.\n+\t//\n+\t// Register complex types used by the peerstore itself.\n+\tgob.Register(make(map[string]struct{}))\n+}\n+\n+// NewPeerMetadata creates a metadata store backed by a persistent db. It uses gob for serialisation.\n+//\n+// See `init()` to learn which types are registered by default. Modules wishing to store\n+// values of other types will need to `gob.Register()` them explicitly, or else callers","path":"pstoreds/metadata.go","position":35,"original_position":35,"commit_id":"dd3cb204213cd05fbb03fb7b3ff2732f6333aaa6","original_commit_id":"dd3cb204213cd05fbb03fb7b3ff2732f6333aaa6","user":{"login":"bigs","id":213338,"node_id":"MDQ6VXNlcjIxMzMzOA==","avatar_url":"https://avatars0.githubusercontent.com/u/213338?v=4","gravatar_id":"","url":"https://api.github.com/users/bigs","html_url":"https://github.com/bigs","followers_url":"https://api.github.com/users/bigs/followers","following_url":"https://api.github.com/users/bigs/following{/other_user}","gists_url":"https://api.github.com/users/bigs/gists{/gist_id}","starred_url":"https://api.github.com/users/bigs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bigs/subscriptions","organizations_url":"https://api.github.com/users/bigs/orgs","repos_url":"https://api.github.com/users/bigs/repos","events_url":"https://api.github.com/users/bigs/events{/privacy}","received_events_url":"https://api.github.com/users/bigs/received_events","type":"User","site_admin":false},"body":"👍 ","created_at":"2018-09-28T16:38:43Z","updated_at":"2018-09-28T16:46:19Z","html_url":"https://github.com/libp2p/go-libp2p-peerstore/pull/37#discussion_r221313184","pull_request_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/comments/221313184"},"html":{"href":"https://github.com/libp2p/go-libp2p-peerstore/pull/37#discussion_r221313184"},"pull_request":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37"}}},"pull_request":{"url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37","id":218964303,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE4OTY0MzAz","html_url":"https://github.com/libp2p/go-libp2p-peerstore/pull/37","diff_url":"https://github.com/libp2p/go-libp2p-peerstore/pull/37.diff","patch_url":"https://github.com/libp2p/go-libp2p-peerstore/pull/37.patch","issue_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/37","number":37,"state":"open","locked":false,"title":"Datastore-backed implementations of KeyBook and PeerMetadata","user":{"login":"raulk","id":1101242,"node_id":"MDQ6VXNlcjExMDEyNDI=","avatar_url":"https://avatars0.githubusercontent.com/u/1101242?v=4","gravatar_id":"","url":"https://api.github.com/users/raulk","html_url":"https://github.com/raulk","followers_url":"https://api.github.com/users/raulk/followers","following_url":"https://api.github.com/users/raulk/following{/other_user}","gists_url":"https://api.github.com/users/raulk/gists{/gist_id}","starred_url":"https://api.github.com/users/raulk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulk/subscriptions","organizations_url":"https://api.github.com/users/raulk/orgs","repos_url":"https://api.github.com/users/raulk/repos","events_url":"https://api.github.com/users/raulk/events{/privacy}","received_events_url":"https://api.github.com/users/raulk/received_events","type":"User","site_admin":false},"body":"All pretty standard, except that the `PeerMetadata` accepts values of wildcard type (`interface{}`), which now need to be serialised and deserialised. \r\n\r\nTook the simple path and used gob, which requires registering non-basic types beforehand, like `map[string]struct{}`, used by the `*Protocol()` methods on `Peerstore`.\r\n\r\nHowever, given the public interface, it's possible for callers to use custom types (e.g. storing custom structs as metadata), which will need to be enlisted with the serialiser. I considered different options:\r\n\r\n1. Dynamically registering types on `Put()` and keeping a type cache to avoid duplicate registrations (even if they are harmless), but this doesn't work on restart, as the user may `Get()` values for a type that hasn't been registered via `Put()` yet.\r\n2. Adding a configuration attribute on `Options`: `SupportedTypes: []interface{}`, but the peerstore is likely initialised before other modules that may need to add custom types.\r\n3. Adding a new method on the interface `RegisterType()`.\r\n4. Informing the user in the docs that they need to register custom types manually.\r\n\r\nI went with 4 for now, but I'm happy to switch to 3 if it's deemed necessary.\r\n\r\n---\r\n\r\nAlso, I segregated storage keys per component:\r\n\r\n* KeyBook pattern: `/peers/keys/<b58 peerid>/{pub,priv}`\r\n* AddrBook pattern: `/peers/addrs/<b58 peerid>/<hash maddr>`\r\n* PeerMetadata pattern: `/peers/metadata/<b58 peerid>/<key>`\r\n\r\nThe natural (hierarchical) pattern would've been like:\r\n* `/peer:<b58 peerid>/key:{pub,priv}`\r\n* `/peer:<b58 peerid>/addr:<hash maddr>`\r\n* `/peer:<b58 peerid>/meta:<key>`\r\n\r\nBut it makes range queries inefficient.","created_at":"2018-09-28T13:15:11Z","updated_at":"2018-09-28T16:46:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f1adfe62f2a2069b720faf96cc37410416b007d8","assignee":{"login":"raulk","id":1101242,"node_id":"MDQ6VXNlcjExMDEyNDI=","avatar_url":"https://avatars0.githubusercontent.com/u/1101242?v=4","gravatar_id":"","url":"https://api.github.com/users/raulk","html_url":"https://github.com/raulk","followers_url":"https://api.github.com/users/raulk/followers","following_url":"https://api.github.com/users/raulk/following{/other_user}","gists_url":"https://api.github.com/users/raulk/gists{/gist_id}","starred_url":"https://api.github.com/users/raulk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulk/subscriptions","organizations_url":"https://api.github.com/users/raulk/orgs","repos_url":"https://api.github.com/users/raulk/repos","events_url":"https://api.github.com/users/raulk/events{/privacy}","received_events_url":"https://api.github.com/users/raulk/received_events","type":"User","site_admin":false},"assignees":[{"login":"raulk","id":1101242,"node_id":"MDQ6VXNlcjExMDEyNDI=","avatar_url":"https://avatars0.githubusercontent.com/u/1101242?v=4","gravatar_id":"","url":"https://api.github.com/users/raulk","html_url":"https://github.com/raulk","followers_url":"https://api.github.com/users/raulk/followers","following_url":"https://api.github.com/users/raulk/following{/other_user}","gists_url":"https://api.github.com/users/raulk/gists{/gist_id}","starred_url":"https://api.github.com/users/raulk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulk/subscriptions","organizations_url":"https://api.github.com/users/raulk/orgs","repos_url":"https://api.github.com/users/raulk/repos","events_url":"https://api.github.com/users/raulk/events{/privacy}","received_events_url":"https://api.github.com/users/raulk/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"Stebalien","id":310393,"node_id":"MDQ6VXNlcjMxMDM5Mw==","avatar_url":"https://avatars2.githubusercontent.com/u/310393?v=4","gravatar_id":"","url":"https://api.github.com/users/Stebalien","html_url":"https://github.com/Stebalien","followers_url":"https://api.github.com/users/Stebalien/followers","following_url":"https://api.github.com/users/Stebalien/following{/other_user}","gists_url":"https://api.github.com/users/Stebalien/gists{/gist_id}","starred_url":"https://api.github.com/users/Stebalien/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Stebalien/subscriptions","organizations_url":"https://api.github.com/users/Stebalien/orgs","repos_url":"https://api.github.com/users/Stebalien/repos","events_url":"https://api.github.com/users/Stebalien/events{/privacy}","received_events_url":"https://api.github.com/users/Stebalien/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":427754958,"node_id":"MDU6TGFiZWw0Mjc3NTQ5NTg=","url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/labels/in%20progress","name":"in progress","color":"ededed","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37/commits","review_comments_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37/comments","review_comment_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/37/comments","statuses_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/statuses/dd3cb204213cd05fbb03fb7b3ff2732f6333aaa6","head":{"label":"raulk:ds-backed-keybook-metadata","ref":"ds-backed-keybook-metadata","sha":"dd3cb204213cd05fbb03fb7b3ff2732f6333aaa6","user":{"login":"raulk","id":1101242,"node_id":"MDQ6VXNlcjExMDEyNDI=","avatar_url":"https://avatars0.githubusercontent.com/u/1101242?v=4","gravatar_id":"","url":"https://api.github.com/users/raulk","html_url":"https://github.com/raulk","followers_url":"https://api.github.com/users/raulk/followers","following_url":"https://api.github.com/users/raulk/following{/other_user}","gists_url":"https://api.github.com/users/raulk/gists{/gist_id}","starred_url":"https://api.github.com/users/raulk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulk/subscriptions","organizations_url":"https://api.github.com/users/raulk/orgs","repos_url":"https://api.github.com/users/raulk/repos","events_url":"https://api.github.com/users/raulk/events{/privacy}","received_events_url":"https://api.github.com/users/raulk/received_events","type":"User","site_admin":false},"repo":{"id":146610144,"node_id":"MDEwOlJlcG9zaXRvcnkxNDY2MTAxNDQ=","name":"go-libp2p-peerstore","full_name":"raulk/go-libp2p-peerstore","private":false,"owner":{"login":"raulk","id":1101242,"node_id":"MDQ6VXNlcjExMDEyNDI=","avatar_url":"https://avatars0.githubusercontent.com/u/1101242?v=4","gravatar_id":"","url":"https://api.github.com/users/raulk","html_url":"https://github.com/raulk","followers_url":"https://api.github.com/users/raulk/followers","following_url":"https://api.github.com/users/raulk/following{/other_user}","gists_url":"https://api.github.com/users/raulk/gists{/gist_id}","starred_url":"https://api.github.com/users/raulk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulk/subscriptions","organizations_url":"https://api.github.com/users/raulk/orgs","repos_url":"https://api.github.com/users/raulk/repos","events_url":"https://api.github.com/users/raulk/events{/privacy}","received_events_url":"https://api.github.com/users/raulk/received_events","type":"User","site_admin":false},"html_url":"https://github.com/raulk/go-libp2p-peerstore","description":"an object to manage sets of peers, their addresses and other metadata","fork":true,"url":"https://api.github.com/repos/raulk/go-libp2p-peerstore","forks_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/forks","keys_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/teams","hooks_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/hooks","issue_events_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/issues/events{/number}","events_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/events","assignees_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/assignees{/user}","branches_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/branches{/branch}","tags_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/tags","blobs_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/git/refs{/sha}","trees_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/statuses/{sha}","languages_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/languages","stargazers_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/stargazers","contributors_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/contributors","subscribers_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/subscribers","subscription_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/subscription","commits_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/commits{/sha}","git_commits_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/git/commits{/sha}","comments_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/comments{/number}","issue_comment_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/issues/comments{/number}","contents_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/contents/{+path}","compare_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/merges","archive_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/downloads","issues_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/issues{/number}","pulls_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/pulls{/number}","milestones_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/milestones{/number}","notifications_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/labels{/name}","releases_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/releases{/id}","deployments_url":"https://api.github.com/repos/raulk/go-libp2p-peerstore/deployments","created_at":"2018-08-29T14:13:01Z","updated_at":"2018-08-31T12:32:57Z","pushed_at":"2018-09-28T13:18:15Z","git_url":"git://github.com/raulk/go-libp2p-peerstore.git","ssh_url":"git@github.com:raulk/go-libp2p-peerstore.git","clone_url":"https://github.com/raulk/go-libp2p-peerstore.git","svn_url":"https://github.com/raulk/go-libp2p-peerstore","homepage":null,"size":251,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"libp2p:master","ref":"master","sha":"dbbd2fd262148a1dda43113e09aa95a0e140b259","user":{"login":"libp2p","id":14838238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0ODM4MjM4","avatar_url":"https://avatars3.githubusercontent.com/u/14838238?v=4","gravatar_id":"","url":"https://api.github.com/users/libp2p","html_url":"https://github.com/libp2p","followers_url":"https://api.github.com/users/libp2p/followers","following_url":"https://api.github.com/users/libp2p/following{/other_user}","gists_url":"https://api.github.com/users/libp2p/gists{/gist_id}","starred_url":"https://api.github.com/users/libp2p/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/libp2p/subscriptions","organizations_url":"https://api.github.com/users/libp2p/orgs","repos_url":"https://api.github.com/users/libp2p/repos","events_url":"https://api.github.com/users/libp2p/events{/privacy}","received_events_url":"https://api.github.com/users/libp2p/received_events","type":"Organization","site_admin":false},"repo":{"id":60113836,"node_id":"MDEwOlJlcG9zaXRvcnk2MDExMzgzNg==","name":"go-libp2p-peerstore","full_name":"libp2p/go-libp2p-peerstore","private":false,"owner":{"login":"libp2p","id":14838238,"node_id":"MDEyOk9yZ2FuaXphdGlvbjE0ODM4MjM4","avatar_url":"https://avatars3.githubusercontent.com/u/14838238?v=4","gravatar_id":"","url":"https://api.github.com/users/libp2p","html_url":"https://github.com/libp2p","followers_url":"https://api.github.com/users/libp2p/followers","following_url":"https://api.github.com/users/libp2p/following{/other_user}","gists_url":"https://api.github.com/users/libp2p/gists{/gist_id}","starred_url":"https://api.github.com/users/libp2p/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/libp2p/subscriptions","organizations_url":"https://api.github.com/users/libp2p/orgs","repos_url":"https://api.github.com/users/libp2p/repos","events_url":"https://api.github.com/users/libp2p/events{/privacy}","received_events_url":"https://api.github.com/users/libp2p/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/libp2p/go-libp2p-peerstore","description":"an object to manage sets of peers, their addresses and other metadata","fork":false,"url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore","forks_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/forks","keys_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/teams","hooks_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/hooks","issue_events_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/events{/number}","events_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/events","assignees_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/assignees{/user}","branches_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/branches{/branch}","tags_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/tags","blobs_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/git/refs{/sha}","trees_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/statuses/{sha}","languages_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/languages","stargazers_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/stargazers","contributors_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/contributors","subscribers_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/subscribers","subscription_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/subscription","commits_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/commits{/sha}","git_commits_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/git/commits{/sha}","comments_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/comments{/number}","issue_comment_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/comments{/number}","contents_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/contents/{+path}","compare_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/merges","archive_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/downloads","issues_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues{/number}","pulls_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls{/number}","milestones_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/milestones{/number}","notifications_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/labels{/name}","releases_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/releases{/id}","deployments_url":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/deployments","created_at":"2016-05-31T18:32:50Z","updated_at":"2018-09-27T20:23:12Z","pushed_at":"2018-09-28T13:18:17Z","git_url":"git://github.com/libp2p/go-libp2p-peerstore.git","ssh_url":"git@github.com:libp2p/go-libp2p-peerstore.git","clone_url":"https://github.com/libp2p/go-libp2p-peerstore.git","svn_url":"https://github.com/libp2p/go-libp2p-peerstore","homepage":null,"size":249,"stargazers_count":30,"watchers_count":30,"language":"Go","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":6,"mirror_url":null,"archived":false,"open_issues_count":6,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":6,"open_issues":6,"watchers":30,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37"},"html":{"href":"https://github.com/libp2p/go-libp2p-peerstore/pull/37"},"issue":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/37"},"comments":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/issues/37/comments"},"review_comments":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37/comments"},"review_comment":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/pulls/37/commits"},"statuses":{"href":"https://api.github.com/repos/libp2p/go-libp2p-peerstore/statuses/dd3cb204213cd05fbb03fb7b3ff2732f6333aaa6"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bigs"}}