{"action":"created","comment":{"url":"https://api.github.com/repos/uber/zanzibar/pulls/comments/139511119","pull_request_review_id":63453944,"id":139511119,"diff_hunk":"@@ -0,0 +1,327 @@\n+// Copyright (c) 2017 Uber Technologies, Inc.\n+//\n+// Permission is hereby granted, free of charge, to any person obtaining a copy\n+// of this software and associated documentation files (the \"Software\"), to deal\n+// in the Software without restriction, including without limitation the rights\n+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n+// copies of the Software, and to permit persons to whom the Software is\n+// furnished to do so, subject to the following conditions:\n+//\n+// The above copyright notice and this permission notice shall be included in\n+// all copies or substantial portions of the Software.\n+//\n+// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+// THE SOFTWARE.\n+\n+package zanzibar\n+\n+import (\n+\t\"bytes\"\n+\t\"encoding/json\"\n+\t\"fmt\"\n+\t\"io/ioutil\"\n+\t\"os\"\n+\t\"sync\"\n+\t\"sync/atomic\"\n+\t\"time\"\n+\n+\t\"github.com/buger/jsonparser\"\n+\t\"github.com/pkg/errors\"\n+\t\"github.com/uber-go/tally\"\n+\t\"go.uber.org/zap\"\n+)\n+\n+// RemoteConfig allow accessing values from a periodically refreshed json file\n+type RemoteConfig interface {\n+\tGetBoolean(string, bool) bool\n+\tGetFloat(string, float64) float64\n+\tGetInt(string, int64) int64\n+\tGetString(string, string) string\n+\tGetStruct(string, interface{}) bool\n+\tSubscribe(string, string, *func())\n+\tUnsubscribe(string)\n+\tRefresh() error\n+\tClose()\n+}\n+\n+// RemoteConfigOptions configs remote config file path and refresh frequency\n+type RemoteConfigOptions struct {\n+\tFilePath        string\n+\tPollingInterval time.Duration\n+}\n+\n+// Subscriber is used to track subscribers' callbacks and keys they subscribe\n+type Subscriber struct {\n+\tCallback *func()\n+\tKey      string\n+}\n+\n+// RemoteConfigValue represents a json serialized string\n+type RemoteConfigValue struct {\n+\tbytes    []byte\n+\tdataType jsonparser.ValueType\n+}\n+\n+// RemoteConfigMap allows lock-free concurrent rw\n+// TODO consider https://golang.org/pkg/sync/#Map golang@1.9^\n+type RemoteConfigMap map[string]*RemoteConfigValue\n+\n+type remoteConfig struct {\n+\tconfig      *RemoteConfigOptions\n+\tsubscribers map[string]*Subscriber\n+\tprops       atomic.Value\n+\tclose       chan struct{}\n+\tcurrStat    os.FileInfo\n+\tlogger      *zap.Logger\n+\tscope       tally.Scope\n+\tpoller      *time.Ticker\n+\tmutex       sync.RWMutex\n+\twg          sync.WaitGroup\n+}\n+\n+// NewRemoteConfig allocates a config that can be dynamically changed during runtime.\n+// RemoteConfigOptions takes two args, config file path (that remote config will read from)\n+// and polling interval (decides how frequent we check ).\n+// remote config file follows the same requirements with runtime/static_config/StaticConfig\n+// remote config consider fallback legit case, fallback happens silent without throwing error\n+// Why RemoteConfig:\n+// \t\tWhat diverge staticConfig with remoteConfig is that staticConfig allows value setting\n+//\t\twhile remoteConfig is read only.\n+//\t\tremoteConfig also provides pub/sub to allow caller act on specific key changes\n+func NewRemoteConfig(cfg *RemoteConfigOptions, logger *zap.Logger, scope tally.Scope) (RemoteConfig, error) {\n+\tif logger == nil {\n+\t\tlogger = zap.NewNop()","path":"runtime/remote_config.go","position":98,"original_position":98,"commit_id":"3ca57682b1ec3fde754b7f1fb4c0819f03ea0b77","original_commit_id":"3ca57682b1ec3fde754b7f1fb4c0819f03ea0b77","user":{"login":"Raynos","id":479538,"avatar_url":"https://avatars3.githubusercontent.com/u/479538?v=4","gravatar_id":"","url":"https://api.github.com/users/Raynos","html_url":"https://github.com/Raynos","followers_url":"https://api.github.com/users/Raynos/followers","following_url":"https://api.github.com/users/Raynos/following{/other_user}","gists_url":"https://api.github.com/users/Raynos/gists{/gist_id}","starred_url":"https://api.github.com/users/Raynos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Raynos/subscriptions","organizations_url":"https://api.github.com/users/Raynos/orgs","repos_url":"https://api.github.com/users/Raynos/repos","events_url":"https://api.github.com/users/Raynos/events{/privacy}","received_events_url":"https://api.github.com/users/Raynos/received_events","type":"User","site_admin":false},"body":"let's make logger mandatory as we need to see `logger.error()`","created_at":"2017-09-18T19:01:18Z","updated_at":"2017-09-18T19:17:48Z","html_url":"https://github.com/uber/zanzibar/pull/206#discussion_r139511119","pull_request_url":"https://api.github.com/repos/uber/zanzibar/pulls/206","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/comments/139511119"},"html":{"href":"https://github.com/uber/zanzibar/pull/206#discussion_r139511119"},"pull_request":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/206"}}},"pull_request":{"url":"https://api.github.com/repos/uber/zanzibar/pulls/206","id":140899373,"html_url":"https://github.com/uber/zanzibar/pull/206","diff_url":"https://github.com/uber/zanzibar/pull/206.diff","patch_url":"https://github.com/uber/zanzibar/pull/206.patch","issue_url":"https://api.github.com/repos/uber/zanzibar/issues/206","number":206,"state":"open","locked":false,"title":"add remote config","user":{"login":"cl1337","id":5126179,"avatar_url":"https://avatars3.githubusercontent.com/u/5126179?v=4","gravatar_id":"","url":"https://api.github.com/users/cl1337","html_url":"https://github.com/cl1337","followers_url":"https://api.github.com/users/cl1337/followers","following_url":"https://api.github.com/users/cl1337/following{/other_user}","gists_url":"https://api.github.com/users/cl1337/gists{/gist_id}","starred_url":"https://api.github.com/users/cl1337/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cl1337/subscriptions","organizations_url":"https://api.github.com/users/cl1337/orgs","repos_url":"https://api.github.com/users/cl1337/repos","events_url":"https://api.github.com/users/cl1337/events{/privacy}","received_events_url":"https://api.github.com/users/cl1337/received_events","type":"User","site_admin":false},"body":"implement remote config in addition to static config. What diverges remote config from static config is remote config is read only, remote config is been periodically reloaded from a config json file that could be updated by other services.\r\n\r\n- periodically polling routine to refreshing config\r\n- pub/sub with a callback function upon config change","created_at":"2017-09-13T18:36:59Z","updated_at":"2017-09-18T19:17:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"418ae2ddb465c66051db4ab980cb0b07ed7c619b","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/uber/zanzibar/pulls/206/commits","review_comments_url":"https://api.github.com/repos/uber/zanzibar/pulls/206/comments","review_comment_url":"https://api.github.com/repos/uber/zanzibar/pulls/comments{/number}","comments_url":"https://api.github.com/repos/uber/zanzibar/issues/206/comments","statuses_url":"https://api.github.com/repos/uber/zanzibar/statuses/3ca57682b1ec3fde754b7f1fb4c0819f03ea0b77","head":{"label":"cl1337:cli.add-remote-config","ref":"cli.add-remote-config","sha":"3ca57682b1ec3fde754b7f1fb4c0819f03ea0b77","user":{"login":"cl1337","id":5126179,"avatar_url":"https://avatars3.githubusercontent.com/u/5126179?v=4","gravatar_id":"","url":"https://api.github.com/users/cl1337","html_url":"https://github.com/cl1337","followers_url":"https://api.github.com/users/cl1337/followers","following_url":"https://api.github.com/users/cl1337/following{/other_user}","gists_url":"https://api.github.com/users/cl1337/gists{/gist_id}","starred_url":"https://api.github.com/users/cl1337/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cl1337/subscriptions","organizations_url":"https://api.github.com/users/cl1337/orgs","repos_url":"https://api.github.com/users/cl1337/repos","events_url":"https://api.github.com/users/cl1337/events{/privacy}","received_events_url":"https://api.github.com/users/cl1337/received_events","type":"User","site_admin":false},"repo":{"id":102514479,"name":"zanzibar","full_name":"cl1337/zanzibar","owner":{"login":"cl1337","id":5126179,"avatar_url":"https://avatars3.githubusercontent.com/u/5126179?v=4","gravatar_id":"","url":"https://api.github.com/users/cl1337","html_url":"https://github.com/cl1337","followers_url":"https://api.github.com/users/cl1337/followers","following_url":"https://api.github.com/users/cl1337/following{/other_user}","gists_url":"https://api.github.com/users/cl1337/gists{/gist_id}","starred_url":"https://api.github.com/users/cl1337/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cl1337/subscriptions","organizations_url":"https://api.github.com/users/cl1337/orgs","repos_url":"https://api.github.com/users/cl1337/repos","events_url":"https://api.github.com/users/cl1337/events{/privacy}","received_events_url":"https://api.github.com/users/cl1337/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/cl1337/zanzibar","description":"A build system & configuration system to generate versionsed API gateways.","fork":true,"url":"https://api.github.com/repos/cl1337/zanzibar","forks_url":"https://api.github.com/repos/cl1337/zanzibar/forks","keys_url":"https://api.github.com/repos/cl1337/zanzibar/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cl1337/zanzibar/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cl1337/zanzibar/teams","hooks_url":"https://api.github.com/repos/cl1337/zanzibar/hooks","issue_events_url":"https://api.github.com/repos/cl1337/zanzibar/issues/events{/number}","events_url":"https://api.github.com/repos/cl1337/zanzibar/events","assignees_url":"https://api.github.com/repos/cl1337/zanzibar/assignees{/user}","branches_url":"https://api.github.com/repos/cl1337/zanzibar/branches{/branch}","tags_url":"https://api.github.com/repos/cl1337/zanzibar/tags","blobs_url":"https://api.github.com/repos/cl1337/zanzibar/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cl1337/zanzibar/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cl1337/zanzibar/git/refs{/sha}","trees_url":"https://api.github.com/repos/cl1337/zanzibar/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cl1337/zanzibar/statuses/{sha}","languages_url":"https://api.github.com/repos/cl1337/zanzibar/languages","stargazers_url":"https://api.github.com/repos/cl1337/zanzibar/stargazers","contributors_url":"https://api.github.com/repos/cl1337/zanzibar/contributors","subscribers_url":"https://api.github.com/repos/cl1337/zanzibar/subscribers","subscription_url":"https://api.github.com/repos/cl1337/zanzibar/subscription","commits_url":"https://api.github.com/repos/cl1337/zanzibar/commits{/sha}","git_commits_url":"https://api.github.com/repos/cl1337/zanzibar/git/commits{/sha}","comments_url":"https://api.github.com/repos/cl1337/zanzibar/comments{/number}","issue_comment_url":"https://api.github.com/repos/cl1337/zanzibar/issues/comments{/number}","contents_url":"https://api.github.com/repos/cl1337/zanzibar/contents/{+path}","compare_url":"https://api.github.com/repos/cl1337/zanzibar/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cl1337/zanzibar/merges","archive_url":"https://api.github.com/repos/cl1337/zanzibar/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cl1337/zanzibar/downloads","issues_url":"https://api.github.com/repos/cl1337/zanzibar/issues{/number}","pulls_url":"https://api.github.com/repos/cl1337/zanzibar/pulls{/number}","milestones_url":"https://api.github.com/repos/cl1337/zanzibar/milestones{/number}","notifications_url":"https://api.github.com/repos/cl1337/zanzibar/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cl1337/zanzibar/labels{/name}","releases_url":"https://api.github.com/repos/cl1337/zanzibar/releases{/id}","deployments_url":"https://api.github.com/repos/cl1337/zanzibar/deployments","created_at":"2017-09-05T18:11:46Z","updated_at":"2017-09-05T18:11:48Z","pushed_at":"2017-09-16T00:52:39Z","git_url":"git://github.com/cl1337/zanzibar.git","ssh_url":"git@github.com:cl1337/zanzibar.git","clone_url":"https://github.com/cl1337/zanzibar.git","svn_url":"https://github.com/cl1337/zanzibar","homepage":"","size":8275,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_projects":true,"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":"uber:master","ref":"master","sha":"5b1fa6f0f647f15fd9dd204b0ddb4f8b46e87a8a","user":{"login":"uber","id":538264,"avatar_url":"https://avatars3.githubusercontent.com/u/538264?v=4","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"repo":{"id":85628655,"name":"zanzibar","full_name":"uber/zanzibar","owner":{"login":"uber","id":538264,"avatar_url":"https://avatars3.githubusercontent.com/u/538264?v=4","gravatar_id":"","url":"https://api.github.com/users/uber","html_url":"https://github.com/uber","followers_url":"https://api.github.com/users/uber/followers","following_url":"https://api.github.com/users/uber/following{/other_user}","gists_url":"https://api.github.com/users/uber/gists{/gist_id}","starred_url":"https://api.github.com/users/uber/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/uber/subscriptions","organizations_url":"https://api.github.com/users/uber/orgs","repos_url":"https://api.github.com/users/uber/repos","events_url":"https://api.github.com/users/uber/events{/privacy}","received_events_url":"https://api.github.com/users/uber/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/uber/zanzibar","description":"A build system & configuration system to generate versionsed API gateways.","fork":false,"url":"https://api.github.com/repos/uber/zanzibar","forks_url":"https://api.github.com/repos/uber/zanzibar/forks","keys_url":"https://api.github.com/repos/uber/zanzibar/keys{/key_id}","collaborators_url":"https://api.github.com/repos/uber/zanzibar/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/uber/zanzibar/teams","hooks_url":"https://api.github.com/repos/uber/zanzibar/hooks","issue_events_url":"https://api.github.com/repos/uber/zanzibar/issues/events{/number}","events_url":"https://api.github.com/repos/uber/zanzibar/events","assignees_url":"https://api.github.com/repos/uber/zanzibar/assignees{/user}","branches_url":"https://api.github.com/repos/uber/zanzibar/branches{/branch}","tags_url":"https://api.github.com/repos/uber/zanzibar/tags","blobs_url":"https://api.github.com/repos/uber/zanzibar/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/uber/zanzibar/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/uber/zanzibar/git/refs{/sha}","trees_url":"https://api.github.com/repos/uber/zanzibar/git/trees{/sha}","statuses_url":"https://api.github.com/repos/uber/zanzibar/statuses/{sha}","languages_url":"https://api.github.com/repos/uber/zanzibar/languages","stargazers_url":"https://api.github.com/repos/uber/zanzibar/stargazers","contributors_url":"https://api.github.com/repos/uber/zanzibar/contributors","subscribers_url":"https://api.github.com/repos/uber/zanzibar/subscribers","subscription_url":"https://api.github.com/repos/uber/zanzibar/subscription","commits_url":"https://api.github.com/repos/uber/zanzibar/commits{/sha}","git_commits_url":"https://api.github.com/repos/uber/zanzibar/git/commits{/sha}","comments_url":"https://api.github.com/repos/uber/zanzibar/comments{/number}","issue_comment_url":"https://api.github.com/repos/uber/zanzibar/issues/comments{/number}","contents_url":"https://api.github.com/repos/uber/zanzibar/contents/{+path}","compare_url":"https://api.github.com/repos/uber/zanzibar/compare/{base}...{head}","merges_url":"https://api.github.com/repos/uber/zanzibar/merges","archive_url":"https://api.github.com/repos/uber/zanzibar/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/uber/zanzibar/downloads","issues_url":"https://api.github.com/repos/uber/zanzibar/issues{/number}","pulls_url":"https://api.github.com/repos/uber/zanzibar/pulls{/number}","milestones_url":"https://api.github.com/repos/uber/zanzibar/milestones{/number}","notifications_url":"https://api.github.com/repos/uber/zanzibar/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/uber/zanzibar/labels{/name}","releases_url":"https://api.github.com/repos/uber/zanzibar/releases{/id}","deployments_url":"https://api.github.com/repos/uber/zanzibar/deployments","created_at":"2017-03-20T21:22:09Z","updated_at":"2017-09-12T03:20:49Z","pushed_at":"2017-09-18T19:04:35Z","git_url":"git://github.com/uber/zanzibar.git","ssh_url":"git@github.com:uber/zanzibar.git","clone_url":"https://github.com/uber/zanzibar.git","svn_url":"https://github.com/uber/zanzibar","homepage":"","size":8273,"stargazers_count":33,"watchers_count":33,"language":"Go","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":11,"mirror_url":null,"open_issues_count":22,"forks":11,"open_issues":22,"watchers":33,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/206"},"html":{"href":"https://github.com/uber/zanzibar/pull/206"},"issue":{"href":"https://api.github.com/repos/uber/zanzibar/issues/206"},"comments":{"href":"https://api.github.com/repos/uber/zanzibar/issues/206/comments"},"review_comments":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/206/comments"},"review_comment":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/uber/zanzibar/pulls/206/commits"},"statuses":{"href":"https://api.github.com/repos/uber/zanzibar/statuses/3ca57682b1ec3fde754b7f1fb4c0819f03ea0b77"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"Raynos"}}