)]}'
{".gitignore":[{"author":{"_account_id":447,"name":"dan wendlandt","email":"dan@nicira.com","username":"danwent"},"unresolved":false,"context_lines":[{"line_number":4,"context_line":"build-stamp"},{"line_number":5,"context_line":".coverage"},{"line_number":6,"context_line":"cover/*"},{"line_number":7,"context_line":"quantum_client.egg-info/*"},{"line_number":8,"context_line":"python_quantumclient.egg-info/*"},{"line_number":9,"context_line":"quantum/vcsversion.py"},{"line_number":10,"context_line":"run_tests.err.log"}],"source_content_type":"application/octet-stream","patch_set":2,"id":"AAAAEn%2F%2FxWk%3D","line":7,"updated":"2012-03-06 20:41:34.000000000","message":"I think we can actually remove the line above, as his was the old naming for the directory you are adding below.","commit_id":"71e76c216a80da65f3e7185573df0566b57e3f70"}],"quantum/client/__init__.py":[{"author":{"_account_id":2672,"name":"Madhav Puri","email":"madhav.puri@gmail.com","username":"madhav-puri"},"change_message_id":"aa8bf43c6b2760ea547833ad4983dd65b4606c80","unresolved":false,"context_lines":[{"line_number":255,"context_line":"        Returns the result data, or raises an appropriate exception if"},{"line_number":256,"context_line":"        HTTP status code is not 2xx"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        Only idempotent requests (i.e. GET) should attempt to retry"},{"line_number":259,"context_line":"        failed connection attempts by providing a non-zero value for"},{"line_number":260,"context_line":"        the \u0027retries\u0027 parameter."},{"line_number":261,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEn%2F%2Fy0g%3D","line":258,"updated":"2012-03-03 01:07:52.000000000","message":"It might be good if we ensure that retries are only done for \u0027GET\u0027 action. And make it more \u0027apparent\u0027 in code, than relying on callers of do_request() every time a new  client-side API is added.\n\nOne way might be to write wrappers similar to get() for other actions as well. And then everyone just calls the wrappers.","commit_id":"bf2f36d753c5c51c72d04d46ada4ddfb2875a914"},{"author":{"_account_id":2035,"name":"Maru Newby","email":"marun@redhat.com","username":"maru"},"unresolved":false,"context_lines":[{"line_number":255,"context_line":"        Returns the result data, or raises an appropriate exception if"},{"line_number":256,"context_line":"        HTTP status code is not 2xx"},{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        Only idempotent requests (i.e. GET) should attempt to retry"},{"line_number":259,"context_line":"        failed connection attempts by providing a non-zero value for"},{"line_number":260,"context_line":"        the \u0027retries\u0027 parameter."},{"line_number":261,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"AAAAEn%2F%2Fys4%3D","line":258,"in_reply_to":"AAAAEn%2F%2Fy0g%3D","updated":"2012-03-03 05:39:22.000000000","message":"Done.","commit_id":"bf2f36d753c5c51c72d04d46ada4ddfb2875a914"},{"author":{"_account_id":447,"name":"dan wendlandt","email":"dan@nicira.com","username":"danwent"},"unresolved":false,"context_lines":[{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        Only idempotent requests (i.e. GET) should attempt to retry"},{"line_number":259,"context_line":"        failed connection attempts by providing a non-zero value for"},{"line_number":260,"context_line":"        the \u0027retries\u0027 parameter."},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"        :param method: HTTP method (\"GET\", \"POST\", \"PUT\", etc...)"},{"line_number":263,"context_line":"        :param body: string of data to send, or None (default)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAEn%2F%2FxW0%3D","line":260,"updated":"2012-03-06 20:41:34.000000000","message":"This is an interesting comment, and may be worth teasing apart a bit more.  If the python exception let\u0027s us identify the cases where we weren\u0027t able to establish a successful TCP connection to the server, it seems like it is always safe to retry such requests even if they weren\u0027t idempotent.  It may be worth noting that many PUTs are idempotent as well.  Retrying a DELETE is unlikely to be harmful... the worst case should be that the object was already deleted and you get an error, but that error is likely no worse than if you just give up after a failed try and issue a ConnectionFailed exception.  Even a POST, while never idempotent, may not be harmful to retry.  The worst case would likely be an orphaned port on the network, if the first request succeeded in creating the the port, but then failed to return it, resulting in a retry that successfully created a new port.\n\nI think the conclusion to these questions have implications in the code below.","commit_id":"71e76c216a80da65f3e7185573df0566b57e3f70"},{"author":{"_account_id":2350,"name":"Willian Molinari","email":"pothix@pothix.com","username":"pothix"},"unresolved":false,"context_lines":[{"line_number":257,"context_line":""},{"line_number":258,"context_line":"        Only idempotent requests (i.e. GET) should attempt to retry"},{"line_number":259,"context_line":"        failed connection attempts by providing a non-zero value for"},{"line_number":260,"context_line":"        the \u0027retries\u0027 parameter."},{"line_number":261,"context_line":""},{"line_number":262,"context_line":"        :param method: HTTP method (\"GET\", \"POST\", \"PUT\", etc...)"},{"line_number":263,"context_line":"        :param body: string of data to send, or None (default)"}],"source_content_type":"text/x-python","patch_set":2,"id":"AAAAEn%2F%2FxRQ%3D","line":260,"in_reply_to":"AAAAEn%2F%2FxW0%3D","updated":"2012-03-06 21:52:00.000000000","message":"I think that PUT and DELETE and GET should retry but not POST to avoid the orphan objects problem.","commit_id":"71e76c216a80da65f3e7185573df0566b57e3f70"},{"author":{"_account_id":2672,"name":"Madhav Puri","email":"madhav.puri@gmail.com","username":"madhav-puri"},"change_message_id":"aa8bf43c6b2760ea547833ad4983dd65b4606c80","unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAEn%2F%2FwwQ%3D","line":380,"updated":"2012-03-07 17:23:32.000000000","message":"All reviewers, alternatively we might want to consistently provide retry support across all action types. This ensures uniform (easily explainable?) client behavior.\n\nOne way to achieve this is to selectively provide retries for network error conditions that will benefit all action types.\n\nFrom possible socket related error codes (http://docs.python.org/library/errno.html#module-errno) it looks like \u0027errno.ETIMEDOUT\u0027 and \u0027errno.ECONNREFUSED\u0027 safely fall into this category where the failure happens in early stages of connection itself.\n\nNote that doing this also ensures we don\u0027t retry in certain conditions (and return the failure much earlier) where it is not going to help anyway like errno.ENETDOWN","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"},{"author":{"_account_id":447,"name":"dan wendlandt","email":"dan@nicira.com","username":"danwent"},"unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAE3%2F%2F97M%3D","line":380,"in_reply_to":"AAAAEn%2F%2FwB0%3D","updated":"2012-03-15 13:47:26.000000000","message":"Ok, sounds good.","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"},{"author":{"_account_id":447,"name":"dan wendlandt","email":"dan@nicira.com","username":"danwent"},"unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAE3%2F%2F%2Bso%3D","line":380,"in_reply_to":"AAAAEn%2F%2Fwn0%3D","updated":"2012-03-14 05:12:27.000000000","message":"Hi folks, is there resolution here, or still open questions?  The RC is targeted for tomorrow, so let\u0027s make a call, or we risk an even worse outcome: this patch not getting into essex at all :)","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"},{"author":{"_account_id":2035,"name":"Maru Newby","email":"marun@redhat.com","username":"maru"},"unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAEn%2F%2FwB0%3D","line":380,"in_reply_to":"AAAAEn%2F%2Fwn0%3D","updated":"2012-03-14 21:43:34.000000000","message":"I thought I\u0027d submitted this reply a long time ago, but it appears that I left it as a draft:\n\nAgreed that two categories is simpler and makes sense.\n\nI suggest that a bug be filed to address the suggested improvements in retry support, and that this patch go in as is.","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"},{"author":{"_account_id":2672,"name":"Madhav Puri","email":"madhav.puri@gmail.com","username":"madhav-puri"},"change_message_id":"aa8bf43c6b2760ea547833ad4983dd65b4606c80","unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAEn%2F%2Fwn0%3D","line":380,"in_reply_to":"AAAAEn%2F%2FwtY%3D","updated":"2012-03-07 23:17:14.000000000","message":"I prefer limiting a solution to just first two error categories for \u0027all\u0027 action types i.e. one where we retry and one where we don\u0027t. The third category of errors above can be merged with the category where we don\u0027t retry.\n\nThis, I feel, is easier to explain and document (as simple as saying \"Quatum-client API automatically retries on ETIMEDOUT, ... . Other errors are returned to the user layer immediately.\") .\n\nAlso by a simpler categorization like this the user need not be aware of the nature of \u0027action\u0027 types (idempotent or not; post v/s put differences), which is internal to client API and may change in future. This enables the user to build on these client APIs more easily. Like user-layer may decide to handle specific errno, where retry is not done, by perhaps implementing their own retries (for get operations) and by just querying back quantum later to ensure things went through for update operations (put, post and delete).\n\nHandling the the third category of errors above separately needs the user-layer to be aware of the API internals (i.e. it needs to understand more complex mapping of when a particular error will entail a retry for a particular action). This knowledge shall be needed to make good use of retry mechanism provided by client API under different error/action combinations (if user-layer decides to build on these APIs as described above).\n\nI hope I am making sense. Let me know if I am missing something or if something is not clear.\n\nI agree that other openstack-clients shall be able to benefit from this solution.","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"},{"author":{"_account_id":2035,"name":"Maru Newby","email":"marun@redhat.com","username":"maru"},"unresolved":false,"context_lines":[{"line_number":377,"context_line":"                                  headers\u003dheaders, params\u003dparams)"},{"line_number":378,"context_line":""},{"line_number":379,"context_line":"    def post(self, action, body\u003dNone, headers\u003dNone, params\u003dNone):"},{"line_number":380,"context_line":"        # Do not retry POST requests to avoid the orphan objects problem."},{"line_number":381,"context_line":"        return self.do_request(\"POST\", action, body\u003dbody,"},{"line_number":382,"context_line":"                               headers\u003dheaders, params\u003dparams)"},{"line_number":383,"context_line":""}],"source_content_type":"text/x-python","patch_set":6,"id":"AAAAEn%2F%2FwtY%3D","line":380,"in_reply_to":"AAAAEn%2F%2FwwQ%3D","updated":"2012-03-07 19:29:07.000000000","message":"Taking this further, it may make sense to categorize socket / IO errors into 3 categories:\n\n - errors like ENETDOWN for which retry should not be automatically attempted (but can an error of this type ever occur mid-request?)\n - errors like ETIMEDOUT for which retry should always be automatically attempted\n - errors resulting from a mid-request connection failure (e.g ?) for which retry should only be attempted by idempotent operations, or by non-idempotent operations that query the target state before retrying the request\n\nCareful thought put into the quantum client could hopefully be encapsulated for reuse by the other openstack clients.  Having every client reinvent the wheel isn\u0027t a very good use of resources.","commit_id":"3fa9160195177a2e67d37067e3d8a5a0b950cda9"}]}
