)]}'
{"nova/scheduler/client/report.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9368b6ac972b948204e19fd5f2c59e3479c169ac","unresolved":false,"context_lines":[{"line_number":94,"context_line":"    return wrapper"},{"line_number":95,"context_line":""},{"line_number":96,"context_line":""},{"line_number":97,"context_line":"class Retry(Exception):"},{"line_number":98,"context_line":"    def __init__(self, operation, reason):"},{"line_number":99,"context_line":"        self.operation \u003d operation"},{"line_number":100,"context_line":"        self.reason \u003d reason"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_bec47f41","line":97,"updated":"2017-10-31 16:06:46.000000000","message":"We could use this RetryDecorator from oslo:\n\nhttps://github.com/openstack/oslo.service/blob/master/oslo_service/loopingcall.py#L345\n\nThat includes a sleep time which you could just set to 0, and you provide an expected set of exceptions that you retry on until either some other exception is raised, or an exception in the list isn\u0027t raised, or you hit max retries. We\u0027d still re-use the Retry exception probably. Maybe it\u0027s more heavyweight than what you\u0027re going for here though.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":1063,"name":"Ed Leafe","email":"ed@leafe.com","username":"ed-leafe"},"change_message_id":"691e3b2ee257a63094b9c426bfa501469e5bdf8c","unresolved":false,"context_lines":[{"line_number":103,"context_line":"def retries(f):"},{"line_number":104,"context_line":"    @functools.wraps(f)"},{"line_number":105,"context_line":"    def wrapper(self, *a, **k):"},{"line_number":106,"context_line":"        for retry in range(0, 3):"},{"line_number":107,"context_line":"            try:"},{"line_number":108,"context_line":"                return f(self, *a, **k)"},{"line_number":109,"context_line":"            except Retry as e:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_b82a567b","line":106,"range":{"start_line":106,"start_character":21,"end_line":106,"end_character":32},"updated":"2017-10-31 15:06:02.000000000","message":"Curious - why is this hardcoded to 3?","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"814953aa15298753778759153a3b15cedd3906be","unresolved":false,"context_lines":[{"line_number":103,"context_line":"def retries(f):"},{"line_number":104,"context_line":"    @functools.wraps(f)"},{"line_number":105,"context_line":"    def wrapper(self, *a, **k):"},{"line_number":106,"context_line":"        for retry in range(0, 3):"},{"line_number":107,"context_line":"            try:"},{"line_number":108,"context_line":"                return f(self, *a, **k)"},{"line_number":109,"context_line":"            except Retry as e:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_81304609","line":106,"range":{"start_line":106,"start_character":21,"end_line":106,"end_character":32},"in_reply_to":"3f4b6375_9859daff","updated":"2017-10-31 17:02:55.000000000","message":"Yeah, I dunno that this needs to be configurable really. I think three failed retries probably means we\u0027re stuck. I\u0027d rather wait for proof from the field that three doesn\u0027t work but four does before making this a knob.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"44a97fe97bb67ed601f3596070566bb902c21693","unresolved":false,"context_lines":[{"line_number":103,"context_line":"def retries(f):"},{"line_number":104,"context_line":"    @functools.wraps(f)"},{"line_number":105,"context_line":"    def wrapper(self, *a, **k):"},{"line_number":106,"context_line":"        for retry in range(0, 3):"},{"line_number":107,"context_line":"            try:"},{"line_number":108,"context_line":"                return f(self, *a, **k)"},{"line_number":109,"context_line":"            except Retry as e:"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_9859daff","line":106,"range":{"start_line":106,"start_character":21,"end_line":106,"end_character":32},"in_reply_to":"3f4b6375_b82a567b","updated":"2017-10-31 15:13:41.000000000","message":"It was hard-coded to 3 in the report client claim_resources method, and this is partly pulled from that logic. See the next patch in the series too.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9368b6ac972b948204e19fd5f2c59e3479c169ac","unresolved":false,"context_lines":[{"line_number":108,"context_line":"                return f(self, *a, **k)"},{"line_number":109,"context_line":"            except Retry as e:"},{"line_number":110,"context_line":"                LOG.warning("},{"line_number":111,"context_line":"                    \u0027Unable to %(op)s because %(reason)s; retrying...\u0027 % {"},{"line_number":112,"context_line":"                        \u0027op\u0027: e.operation, \u0027reason\u0027: e.reason})"},{"line_number":113,"context_line":"        LOG.error(\u0027Failed scheduler client operation %s: out of retries\u0027 % ("},{"line_number":114,"context_line":"            f.__name__))"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_1e1033a8","line":111,"range":{"start_line":111,"start_character":21,"end_line":111,"end_character":57},"updated":"2017-10-31 16:06:46.000000000","message":"nit: so we don\u0027t have to make sure the \u0027reason\u0027 fits this message always, you could just do something like:\n\n\u0027Unable to %(ops). Reason: %(reason)s; retrying...\u0027","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9368b6ac972b948204e19fd5f2c59e3479c169ac","unresolved":false,"context_lines":[{"line_number":110,"context_line":"                LOG.warning("},{"line_number":111,"context_line":"                    \u0027Unable to %(op)s because %(reason)s; retrying...\u0027 % {"},{"line_number":112,"context_line":"                        \u0027op\u0027: e.operation, \u0027reason\u0027: e.reason})"},{"line_number":113,"context_line":"        LOG.error(\u0027Failed scheduler client operation %s: out of retries\u0027 % ("},{"line_number":114,"context_line":"            f.__name__))"},{"line_number":115,"context_line":"        return False"},{"line_number":116,"context_line":"    return wrapper"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_be759ffc","line":115,"range":{"start_line":113,"start_character":8,"end_line":115,"end_character":20},"updated":"2017-10-31 16:06:46.000000000","message":"Should probably have a test for the timeout condition. Also, this will work for put_allocations and claim_resources which return a boolean, but might not work for other methods that don\u0027t return booleans and try to use this later - probably something to keep in mind. Maybe add a comment / docstring with the retries decorator itself for usage considerations?","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"814953aa15298753778759153a3b15cedd3906be","unresolved":false,"context_lines":[{"line_number":110,"context_line":"                LOG.warning("},{"line_number":111,"context_line":"                    \u0027Unable to %(op)s because %(reason)s; retrying...\u0027 % {"},{"line_number":112,"context_line":"                        \u0027op\u0027: e.operation, \u0027reason\u0027: e.reason})"},{"line_number":113,"context_line":"        LOG.error(\u0027Failed scheduler client operation %s: out of retries\u0027 % ("},{"line_number":114,"context_line":"            f.__name__))"},{"line_number":115,"context_line":"        return False"},{"line_number":116,"context_line":"    return wrapper"},{"line_number":117,"context_line":""},{"line_number":118,"context_line":""}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_413a4ee7","line":115,"range":{"start_line":113,"start_character":8,"end_line":115,"end_character":20},"in_reply_to":"3f4b6375_be759ffc","updated":"2017-10-31 17:02:55.000000000","message":"Sure.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9368b6ac972b948204e19fd5f2c59e3479c169ac","unresolved":false,"context_lines":[{"line_number":1192,"context_line":"            # NOTE(jaypipes): Yes, it sucks doing string comparison like this"},{"line_number":1193,"context_line":"            # but we have no error codes, only error messages."},{"line_number":1194,"context_line":"            if \u0027concurrently updated\u0027 in r.text:"},{"line_number":1195,"context_line":"                reason \u003d (\u0027another process changed the resource providers \u0027"},{"line_number":1196,"context_line":"                          \u0027involved in our attempt to put allocations for \u0027"},{"line_number":1197,"context_line":"                          \u0027consumer %s\u0027 % consumer_uuid)"},{"line_number":1198,"context_line":"                raise Retry(\u0027put_allocations\u0027, reason)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_bed91f23","line":1195,"range":{"start_line":1195,"start_character":27,"end_line":1195,"end_character":34},"updated":"2017-10-31 16:06:46.000000000","message":"Another\n\nOh I guess you did this intentionally so it fits with the warning message logged in the retries decorator.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"814953aa15298753778759153a3b15cedd3906be","unresolved":false,"context_lines":[{"line_number":1192,"context_line":"            # NOTE(jaypipes): Yes, it sucks doing string comparison like this"},{"line_number":1193,"context_line":"            # but we have no error codes, only error messages."},{"line_number":1194,"context_line":"            if \u0027concurrently updated\u0027 in r.text:"},{"line_number":1195,"context_line":"                reason \u003d (\u0027another process changed the resource providers \u0027"},{"line_number":1196,"context_line":"                          \u0027involved in our attempt to put allocations for \u0027"},{"line_number":1197,"context_line":"                          \u0027consumer %s\u0027 % consumer_uuid)"},{"line_number":1198,"context_line":"                raise Retry(\u0027put_allocations\u0027, reason)"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_213d12dd","line":1195,"range":{"start_line":1195,"start_character":27,"end_line":1195,"end_character":34},"in_reply_to":"3f4b6375_bed91f23","updated":"2017-10-31 17:02:55.000000000","message":"Yep.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"6f6a9db672dfbdc76cd55b1fa55112986c24ae5f","unresolved":false,"context_lines":[{"line_number":112,"context_line":"            try:"},{"line_number":113,"context_line":"                return f(self, *a, **k)"},{"line_number":114,"context_line":"            except Retry as e:"},{"line_number":115,"context_line":"                LOG.warning("},{"line_number":116,"context_line":"                    \u0027Unable to %(op)s because %(reason)s; retrying...\u0027,"},{"line_number":117,"context_line":"                    {\u0027op\u0027: e.operation, \u0027reason\u0027: e.reason})"},{"line_number":118,"context_line":"        LOG.error(\u0027Failed scheduler client operation %s: out of retries\u0027,"}],"source_content_type":"text/x-python","patch_set":2,"id":"3f4b6375_e4d4a8bd","line":115,"range":{"start_line":115,"start_character":20,"end_line":115,"end_character":27},"updated":"2017-10-31 17:44:24.000000000","message":"We might want this to be debug instead of warning, especially since claim_resources uses debug today.","commit_id":"12f5a2a317ed54d843896375890bbe9ae355f422"}],"nova/tests/unit/scheduler/client/test_report.py":[{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"9368b6ac972b948204e19fd5f2c59e3479c169ac","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    def test_put_allocations_retries_conflict(self, mock_put):"},{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        failed \u003d mock.MagicMock()"},{"line_number":299,"context_line":"        failed.status_code \u003d 400"},{"line_number":300,"context_line":"        failed.text \u003d \"concurrently updated\""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        succeeded \u003d mock.MagicMock()"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_3e82cfc9","line":299,"range":{"start_line":299,"start_character":29,"end_line":299,"end_character":32},"updated":"2017-10-31 16:06:46.000000000","message":"nit: 409 would be more realistic","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":4393,"name":"Dan Smith","email":"dms@danplanet.com","username":"danms"},"change_message_id":"814953aa15298753778759153a3b15cedd3906be","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    def test_put_allocations_retries_conflict(self, mock_put):"},{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        failed \u003d mock.MagicMock()"},{"line_number":299,"context_line":"        failed.status_code \u003d 400"},{"line_number":300,"context_line":"        failed.text \u003d \"concurrently updated\""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        succeeded \u003d mock.MagicMock()"}],"source_content_type":"text/x-python","patch_set":1,"id":"3f4b6375_216f52fd","line":299,"range":{"start_line":299,"start_character":29,"end_line":299,"end_character":32},"in_reply_to":"3f4b6375_3e82cfc9","updated":"2017-10-31 17:02:55.000000000","message":"All the other tests here seem to just use 400, but sure.","commit_id":"7c2621de360ee6f28462a63a4b0aa54f9d115aed"},{"author":{"_account_id":6873,"name":"Matt Riedemann","email":"mriedem.os@gmail.com","username":"mriedem"},"change_message_id":"7779ec92728f4edeb3da3935d682674cf40fd5f0","unresolved":false,"context_lines":[{"line_number":296,"context_line":"    def test_put_allocations_retries_conflict(self, mock_put):"},{"line_number":297,"context_line":""},{"line_number":298,"context_line":"        failed \u003d mock.MagicMock()"},{"line_number":299,"context_line":"        failed.status_code \u003d 400"},{"line_number":300,"context_line":"        failed.text \u003d \"concurrently updated\""},{"line_number":301,"context_line":""},{"line_number":302,"context_line":"        succeeded \u003d mock.MagicMock()"}],"source_content_type":"text/x-python","patch_set":2,"id":"3f4b6375_44d01cca","line":299,"range":{"start_line":299,"start_character":29,"end_line":299,"end_character":32},"updated":"2017-10-31 17:44:02.000000000","message":"You changed this in the top change in the series, I think you meant to do it here.","commit_id":"12f5a2a317ed54d843896375890bbe9ae355f422"}]}
