{"action":"created","comment":{"url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/comments/146929484","pull_request_review_id":71940360,"id":146929484,"diff_hunk":"@@ -27,105 +31,135 @@ class SolrRequest(object):\n     \"\"\"\n     Handle requests to SOLR and response from SOLR\n     \"\"\"\n+\n+    REFRESH_FREQUENCY = 2\n+\n     def __init__(self, solr_hosts, zookeeper_hosts=None, timeout=15):\n         self.client = requests.Session()\n         self.master_hosts = solr_hosts\n-        self.current_hosts = solr_hosts\n+        self.zookeeper_hosts = zookeeper_hosts\n         self.servers = []\n         self.timeout = timeout\n-        if zookeeper_hosts is not None:\n-            self.zookeeper = Zookeeper(zookeeper_hosts)\n-        else:\n-            self.zookeeper = None\n-\n-        self.last_error = None\n-        # time to revert to old host list (in minutes) after an error\n-        self.check_hosts = 5\n-\n-    def request(self, path, params, method, body=None):\n+        self.current_hosts = self.master_hosts  # Backwards Compat\n+        self._zookeeper = None\n+        self._last_request = None\n+        self.attempt_zookeeper_refresh()\n+\n+    @property\n+    def zookeeper(self):\n+        if self._zookeeper is None and self.zookeeper_hosts:\n+            self._zookeeper = Zookeeper(self.zookeeper_hosts)\n+        return self._zookeeper\n+\n+    def attempt_zookeeper_refresh(self):\n+        zk = self.zookeeper\n+        if zk:\n+            logger.debug('Fetching solr from zookeeper')\n+            try:\n+                self.master_hosts = zk.get_active_hosts()\n+                self.current_hosts = self.master_hosts  # backward compat\n+                logger.info(\n+                    'Got solr nodes from zookeeper: %s',\n+                    ','.join(self.master_hosts)\n+                )\n+                if not self.master_hosts:\n+                    logger.error('Unable to find any solr nodes to make requests to')\n+                    raise SolrError(\"zookeeper reporting all SOLR nodes as down\")\n+                return True\n+            except Exception as e:\n+                logger.exception('Failing to retrieve new SOLR hosts from zookeeper')\n+        return False\n+\n+    def request(self, path, params, method, body=None, headers=None, is_retry=False):\n         \"\"\"\n         Prepare data and send request to SOLR servers\n         \"\"\"\n-        def handle_error():\n-            # if the sdk knows where zookeeper lives\n-            if self.zookeeper is not None:\n-                self.last_error = time.time()\n-                # get the current list of active nodes from zookeeper\n-                curr_hosts = self.zookeeper.get_active_hosts()\n-                if len(curr_hosts) == 0:\n-                    # all nodes are down - so raise an error\n-                    raise SolrError(\"SOLR reporting all nodes as down\")\n-                else:\n-                    # if all nodes are not down, update the current_hosts list\n-                    # and the servers list\n-                    self.current_hosts = curr_hosts\n-                    self.servers = curr_hosts\n-\n-            host = self.servers.pop(0)\n-            return make_request(host, path)\n-\n-        headers = {'content-type': 'application/json'}\n-        resultparams = {'wt': 'json',\n-                        'omitHeader': 'true',\n-                        'json.nl': 'map'}\n-\n-        if params is not None:\n-            resultparams.update(params)\n-\n-        # if there hasn't been an error in 5 minutes, reset the solr_hosts\n-        if self.last_error is not None and \\\n-                (time.time() - self.last_error) % 60 > self.check_hosts:\n-\n-            self.current_hosts = self.master_hosts\n-            self.last_error = None\n-\n-        def make_request(host, path):\n-            fullpath = urljoin(host, path)\n+        request_headers = {\n+            'content-type': 'application/json',\n+        }\n+        if headers:\n+            request_headers.update(headers)\n+\n+        # Refresh our list of hosts\n+        if (self.zookeeper and\n+            not is_retry and\n+            self._last_request and\n+            ((time.time() - self._last_request) / 60) > self.REFRESH_FREQUENCY):\n+            self.attempt_zookeeper_refresh()\n+\n+        request_params = {\n+            'wt': 'json',\n+            'omitHeader': True,","path":"wukong/request.py","position":null,"original_position":130,"commit_id":"f9d841677095f1f53524118ea0f8cd7affac25d1","original_commit_id":"4e66cc30fae1c2dadf917e974e407ef6d2dd6173","user":{"login":"TylerLubeck","id":1408986,"avatar_url":"https://avatars2.githubusercontent.com/u/1408986?v=4","gravatar_id":"","url":"https://api.github.com/users/TylerLubeck","html_url":"https://github.com/TylerLubeck","followers_url":"https://api.github.com/users/TylerLubeck/followers","following_url":"https://api.github.com/users/TylerLubeck/following{/other_user}","gists_url":"https://api.github.com/users/TylerLubeck/gists{/gist_id}","starred_url":"https://api.github.com/users/TylerLubeck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TylerLubeck/subscriptions","organizations_url":"https://api.github.com/users/TylerLubeck/orgs","repos_url":"https://api.github.com/users/TylerLubeck/repos","events_url":"https://api.github.com/users/TylerLubeck/events{/privacy}","received_events_url":"https://api.github.com/users/TylerLubeck/received_events","type":"User","site_admin":false},"body":"In the old version this was `'omitHeader': 'true'` but I switched it to use a real boolean. Do we know if it matters?","created_at":"2017-10-25T17:29:54Z","updated_at":"2017-10-25T17:31:19Z","html_url":"https://github.com/SurveyMonkey/wukong/pull/18#discussion_r146929484","pull_request_url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/comments/146929484"},"html":{"href":"https://github.com/SurveyMonkey/wukong/pull/18#discussion_r146929484"},"pull_request":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18"}}},"pull_request":{"url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18","id":148688331,"html_url":"https://github.com/SurveyMonkey/wukong/pull/18","diff_url":"https://github.com/SurveyMonkey/wukong/pull/18.diff","patch_url":"https://github.com/SurveyMonkey/wukong/pull/18.patch","issue_url":"https://api.github.com/repos/SurveyMonkey/wukong/issues/18","number":18,"state":"open","locked":false,"title":"Simply request with retry","user":{"login":"joual","id":157877,"avatar_url":"https://avatars0.githubusercontent.com/u/157877?v=4","gravatar_id":"","url":"https://api.github.com/users/joual","html_url":"https://github.com/joual","followers_url":"https://api.github.com/users/joual/followers","following_url":"https://api.github.com/users/joual/following{/other_user}","gists_url":"https://api.github.com/users/joual/gists{/gist_id}","starred_url":"https://api.github.com/users/joual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joual/subscriptions","organizations_url":"https://api.github.com/users/joual/orgs","repos_url":"https://api.github.com/users/joual/repos","events_url":"https://api.github.com/users/joual/events{/privacy}","received_events_url":"https://api.github.com/users/joual/received_events","type":"User","site_admin":false},"body":"","created_at":"2017-10-25T14:42:05Z","updated_at":"2017-10-25T17:31:19Z","closed_at":null,"merged_at":null,"merge_commit_sha":"eb72d4876c9c0fa28092891032a13c753826dd14","assignee":null,"assignees":[],"requested_reviewers":[],"milestone":null,"commits_url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18/commits","review_comments_url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18/comments","review_comment_url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/comments{/number}","comments_url":"https://api.github.com/repos/SurveyMonkey/wukong/issues/18/comments","statuses_url":"https://api.github.com/repos/SurveyMonkey/wukong/statuses/f9d841677095f1f53524118ea0f8cd7affac25d1","head":{"label":"joual:simply_request_with_retry","ref":"simply_request_with_retry","sha":"f9d841677095f1f53524118ea0f8cd7affac25d1","user":{"login":"joual","id":157877,"avatar_url":"https://avatars0.githubusercontent.com/u/157877?v=4","gravatar_id":"","url":"https://api.github.com/users/joual","html_url":"https://github.com/joual","followers_url":"https://api.github.com/users/joual/followers","following_url":"https://api.github.com/users/joual/following{/other_user}","gists_url":"https://api.github.com/users/joual/gists{/gist_id}","starred_url":"https://api.github.com/users/joual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joual/subscriptions","organizations_url":"https://api.github.com/users/joual/orgs","repos_url":"https://api.github.com/users/joual/repos","events_url":"https://api.github.com/users/joual/events{/privacy}","received_events_url":"https://api.github.com/users/joual/received_events","type":"User","site_admin":false},"repo":{"id":84346900,"name":"wukong","full_name":"joual/wukong","owner":{"login":"joual","id":157877,"avatar_url":"https://avatars0.githubusercontent.com/u/157877?v=4","gravatar_id":"","url":"https://api.github.com/users/joual","html_url":"https://github.com/joual","followers_url":"https://api.github.com/users/joual/followers","following_url":"https://api.github.com/users/joual/following{/other_user}","gists_url":"https://api.github.com/users/joual/gists{/gist_id}","starred_url":"https://api.github.com/users/joual/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joual/subscriptions","organizations_url":"https://api.github.com/users/joual/orgs","repos_url":"https://api.github.com/users/joual/repos","events_url":"https://api.github.com/users/joual/events{/privacy}","received_events_url":"https://api.github.com/users/joual/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/joual/wukong","description":"An ORM Client library for SolrCloud http://wukong.readthedocs.io/en/latest/","fork":true,"url":"https://api.github.com/repos/joual/wukong","forks_url":"https://api.github.com/repos/joual/wukong/forks","keys_url":"https://api.github.com/repos/joual/wukong/keys{/key_id}","collaborators_url":"https://api.github.com/repos/joual/wukong/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/joual/wukong/teams","hooks_url":"https://api.github.com/repos/joual/wukong/hooks","issue_events_url":"https://api.github.com/repos/joual/wukong/issues/events{/number}","events_url":"https://api.github.com/repos/joual/wukong/events","assignees_url":"https://api.github.com/repos/joual/wukong/assignees{/user}","branches_url":"https://api.github.com/repos/joual/wukong/branches{/branch}","tags_url":"https://api.github.com/repos/joual/wukong/tags","blobs_url":"https://api.github.com/repos/joual/wukong/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/joual/wukong/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/joual/wukong/git/refs{/sha}","trees_url":"https://api.github.com/repos/joual/wukong/git/trees{/sha}","statuses_url":"https://api.github.com/repos/joual/wukong/statuses/{sha}","languages_url":"https://api.github.com/repos/joual/wukong/languages","stargazers_url":"https://api.github.com/repos/joual/wukong/stargazers","contributors_url":"https://api.github.com/repos/joual/wukong/contributors","subscribers_url":"https://api.github.com/repos/joual/wukong/subscribers","subscription_url":"https://api.github.com/repos/joual/wukong/subscription","commits_url":"https://api.github.com/repos/joual/wukong/commits{/sha}","git_commits_url":"https://api.github.com/repos/joual/wukong/git/commits{/sha}","comments_url":"https://api.github.com/repos/joual/wukong/comments{/number}","issue_comment_url":"https://api.github.com/repos/joual/wukong/issues/comments{/number}","contents_url":"https://api.github.com/repos/joual/wukong/contents/{+path}","compare_url":"https://api.github.com/repos/joual/wukong/compare/{base}...{head}","merges_url":"https://api.github.com/repos/joual/wukong/merges","archive_url":"https://api.github.com/repos/joual/wukong/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/joual/wukong/downloads","issues_url":"https://api.github.com/repos/joual/wukong/issues{/number}","pulls_url":"https://api.github.com/repos/joual/wukong/pulls{/number}","milestones_url":"https://api.github.com/repos/joual/wukong/milestones{/number}","notifications_url":"https://api.github.com/repos/joual/wukong/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/joual/wukong/labels{/name}","releases_url":"https://api.github.com/repos/joual/wukong/releases{/id}","deployments_url":"https://api.github.com/repos/joual/wukong/deployments","created_at":"2017-03-08T17:17:22Z","updated_at":"2017-03-08T17:17:24Z","pushed_at":"2017-10-25T17:28:29Z","git_url":"git://github.com/joual/wukong.git","ssh_url":"git@github.com:joual/wukong.git","clone_url":"https://github.com/joual/wukong.git","svn_url":"https://github.com/joual/wukong","homepage":"","size":64,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"SurveyMonkey:master","ref":"master","sha":"50740e9bb5d33b258b886c0725b116b8cd01aded","user":{"login":"SurveyMonkey","id":4458558,"avatar_url":"https://avatars0.githubusercontent.com/u/4458558?v=4","gravatar_id":"","url":"https://api.github.com/users/SurveyMonkey","html_url":"https://github.com/SurveyMonkey","followers_url":"https://api.github.com/users/SurveyMonkey/followers","following_url":"https://api.github.com/users/SurveyMonkey/following{/other_user}","gists_url":"https://api.github.com/users/SurveyMonkey/gists{/gist_id}","starred_url":"https://api.github.com/users/SurveyMonkey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SurveyMonkey/subscriptions","organizations_url":"https://api.github.com/users/SurveyMonkey/orgs","repos_url":"https://api.github.com/users/SurveyMonkey/repos","events_url":"https://api.github.com/users/SurveyMonkey/events{/privacy}","received_events_url":"https://api.github.com/users/SurveyMonkey/received_events","type":"Organization","site_admin":false},"repo":{"id":66986285,"name":"wukong","full_name":"SurveyMonkey/wukong","owner":{"login":"SurveyMonkey","id":4458558,"avatar_url":"https://avatars0.githubusercontent.com/u/4458558?v=4","gravatar_id":"","url":"https://api.github.com/users/SurveyMonkey","html_url":"https://github.com/SurveyMonkey","followers_url":"https://api.github.com/users/SurveyMonkey/followers","following_url":"https://api.github.com/users/SurveyMonkey/following{/other_user}","gists_url":"https://api.github.com/users/SurveyMonkey/gists{/gist_id}","starred_url":"https://api.github.com/users/SurveyMonkey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/SurveyMonkey/subscriptions","organizations_url":"https://api.github.com/users/SurveyMonkey/orgs","repos_url":"https://api.github.com/users/SurveyMonkey/repos","events_url":"https://api.github.com/users/SurveyMonkey/events{/privacy}","received_events_url":"https://api.github.com/users/SurveyMonkey/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/SurveyMonkey/wukong","description":"An ORM Client library for SolrCloud http://wukong.readthedocs.io/en/latest/","fork":false,"url":"https://api.github.com/repos/SurveyMonkey/wukong","forks_url":"https://api.github.com/repos/SurveyMonkey/wukong/forks","keys_url":"https://api.github.com/repos/SurveyMonkey/wukong/keys{/key_id}","collaborators_url":"https://api.github.com/repos/SurveyMonkey/wukong/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/SurveyMonkey/wukong/teams","hooks_url":"https://api.github.com/repos/SurveyMonkey/wukong/hooks","issue_events_url":"https://api.github.com/repos/SurveyMonkey/wukong/issues/events{/number}","events_url":"https://api.github.com/repos/SurveyMonkey/wukong/events","assignees_url":"https://api.github.com/repos/SurveyMonkey/wukong/assignees{/user}","branches_url":"https://api.github.com/repos/SurveyMonkey/wukong/branches{/branch}","tags_url":"https://api.github.com/repos/SurveyMonkey/wukong/tags","blobs_url":"https://api.github.com/repos/SurveyMonkey/wukong/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/SurveyMonkey/wukong/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/SurveyMonkey/wukong/git/refs{/sha}","trees_url":"https://api.github.com/repos/SurveyMonkey/wukong/git/trees{/sha}","statuses_url":"https://api.github.com/repos/SurveyMonkey/wukong/statuses/{sha}","languages_url":"https://api.github.com/repos/SurveyMonkey/wukong/languages","stargazers_url":"https://api.github.com/repos/SurveyMonkey/wukong/stargazers","contributors_url":"https://api.github.com/repos/SurveyMonkey/wukong/contributors","subscribers_url":"https://api.github.com/repos/SurveyMonkey/wukong/subscribers","subscription_url":"https://api.github.com/repos/SurveyMonkey/wukong/subscription","commits_url":"https://api.github.com/repos/SurveyMonkey/wukong/commits{/sha}","git_commits_url":"https://api.github.com/repos/SurveyMonkey/wukong/git/commits{/sha}","comments_url":"https://api.github.com/repos/SurveyMonkey/wukong/comments{/number}","issue_comment_url":"https://api.github.com/repos/SurveyMonkey/wukong/issues/comments{/number}","contents_url":"https://api.github.com/repos/SurveyMonkey/wukong/contents/{+path}","compare_url":"https://api.github.com/repos/SurveyMonkey/wukong/compare/{base}...{head}","merges_url":"https://api.github.com/repos/SurveyMonkey/wukong/merges","archive_url":"https://api.github.com/repos/SurveyMonkey/wukong/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/SurveyMonkey/wukong/downloads","issues_url":"https://api.github.com/repos/SurveyMonkey/wukong/issues{/number}","pulls_url":"https://api.github.com/repos/SurveyMonkey/wukong/pulls{/number}","milestones_url":"https://api.github.com/repos/SurveyMonkey/wukong/milestones{/number}","notifications_url":"https://api.github.com/repos/SurveyMonkey/wukong/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/SurveyMonkey/wukong/labels{/name}","releases_url":"https://api.github.com/repos/SurveyMonkey/wukong/releases{/id}","deployments_url":"https://api.github.com/repos/SurveyMonkey/wukong/deployments","created_at":"2016-08-30T23:56:22Z","updated_at":"2017-03-01T16:57:14Z","pushed_at":"2017-10-25T17:28:30Z","git_url":"git://github.com/SurveyMonkey/wukong.git","ssh_url":"git@github.com:SurveyMonkey/wukong.git","clone_url":"https://github.com/SurveyMonkey/wukong.git","svn_url":"https://github.com/SurveyMonkey/wukong","homepage":"","size":60,"stargazers_count":10,"watchers_count":10,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"archived":false,"open_issues_count":7,"forks":4,"open_issues":7,"watchers":10,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18"},"html":{"href":"https://github.com/SurveyMonkey/wukong/pull/18"},"issue":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/issues/18"},"comments":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/issues/18/comments"},"review_comments":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18/comments"},"review_comment":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/pulls/18/commits"},"statuses":{"href":"https://api.github.com/repos/SurveyMonkey/wukong/statuses/f9d841677095f1f53524118ea0f8cd7affac25d1"}},"author_association":"NONE"}}
{"actor":{"display_login":"TylerLubeck"}}