)]}'
{"etc/proxy-server.conf-sample":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"dbbd41b8cb3639e86faec0fb0126c4e779134b72","unresolved":false,"context_lines":[{"line_number":204,"context_line":"# when rebalancing. If you\u0027re rebalancing more aggressively, increase this"},{"line_number":205,"context_line":"# to avoid erroneously returning a 404 when the primary assignments that"},{"line_number":206,"context_line":"# *didn\u0027t* change get overloaded."},{"line_number":207,"context_line":"# ignore_rebalance_404s \u003d 1"},{"line_number":208,"context_line":"#"},{"line_number":209,"context_line":"# By default on a GET/HEAD swift will connect to a minimum number storage nodes"},{"line_number":210,"context_line":"# in a minimum number of threads - for replicated data just a single request to"}],"source_content_type":"application/octet-stream","patch_set":6,"id":"9f560f44_e36c8737","line":207,"updated":"2020-08-24 21:07:09.000000000","message":"I like having \"rebalance\" in the name to keep it topical, we could maybe lead with that.\n\nI think we should avoid numbers in config vars names.  I\u0027m not sure there\u0027s any tool that would parse it wrong; but I could imagine some contexts where we wouldn\u0027t wan a variable name to *start* with a number - so maybe it\u0027s ok to avoid them?\n\nRather than 404 (which is ambiguous with tombstone), I think \"missing from primary\" might be more descriptive.\n\nWe have a lot of config vars with similar interfaces that tend to end with \"_count\"\n \nmaybe:\n\nrebalance_missing_suppression_count \u003d 1","commit_id":"59af1824ac872f1f28456c7fd741a4adae5b6a63"}],"swift/proxy/controllers/base.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":875,"context_line":"        self.latest_404_timestamp \u003d Timestamp(0)"},{"line_number":876,"context_line":"        self.ignore_rebalance_404s \u003d min("},{"line_number":877,"context_line":"            self.app.get_policy_options(self.policy).ignore_rebalance_404s,"},{"line_number":878,"context_line":"            node_iter.num_primary_nodes - 1)"},{"line_number":879,"context_line":""},{"line_number":880,"context_line":"        # stuff from request"},{"line_number":881,"context_line":"        self.req_method \u003d req.method"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_7cab681c","line":878,"updated":"2020-08-17 18:25:13.000000000","message":"so single replica is always 0, triple replica can\u0027t be more than 2...\n\nnum_primary_nodes was added for waterfall-ec; but this is the first time it\u0027s used in here...","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f71f73945ac96c4bae9bb39c5420f3422dc36ee7","unresolved":false,"context_lines":[{"line_number":875,"context_line":"        self.latest_404_timestamp \u003d Timestamp(0)"},{"line_number":876,"context_line":"        self.ignore_rebalance_404s \u003d min("},{"line_number":877,"context_line":"            self.app.get_policy_options(self.policy).ignore_rebalance_404s,"},{"line_number":878,"context_line":"            node_iter.num_primary_nodes - 1)"},{"line_number":879,"context_line":""},{"line_number":880,"context_line":"        # stuff from request"},{"line_number":881,"context_line":"        self.req_method \u003d req.method"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_f76f93c2","line":878,"in_reply_to":"9f560f44_7cab681c","updated":"2020-08-17 18:44:30.000000000","message":"Yeah, and the issue I was hitting was that some tempest tests would run with a single replica and expect 404s for data that\u0027s not there yet (which seems reasonable). I wanted to make sure that if *all* primaries responded 404-no-timestamp, we\u0027d still 404.","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":1327,"context_line":"            if self.ignore_rebalance_404s \u003e 0 and \\"},{"line_number":1328,"context_line":"                    possible_source.status \u003d\u003d HTTP_NOT_FOUND and \\"},{"line_number":1329,"context_line":"                    not Timestamp(src_headers.get(\u0027x-backend-timestamp\u0027, 0)):"},{"line_number":1330,"context_line":"                self.ignore_rebalance_404s -\u003d 1"},{"line_number":1331,"context_line":"                return False"},{"line_number":1332,"context_line":""},{"line_number":1333,"context_line":"            self.statuses.append(possible_source.status)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_3cb1f090","line":1330,"updated":"2020-08-17 18:25:13.000000000","message":"so the logic is something like \"throw out N non-timestamped 404s\" and then let the rest of the responses decide what to send.","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4f7c5a4fa37237192a711625dca21abfe0c828be","unresolved":false,"context_lines":[{"line_number":1328,"context_line":"                    possible_source.status \u003d\u003d HTTP_NOT_FOUND and \\"},{"line_number":1329,"context_line":"                    not Timestamp(src_headers.get(\u0027x-backend-timestamp\u0027, 0)):"},{"line_number":1330,"context_line":"                self.ignore_rebalance_404s -\u003d 1"},{"line_number":1331,"context_line":"                return False"},{"line_number":1332,"context_line":""},{"line_number":1333,"context_line":"            self.statuses.append(possible_source.status)"},{"line_number":1334,"context_line":"            self.reasons.append(possible_source.reason)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_dfd6f353","line":1331,"updated":"2020-08-17 04:46:23.000000000","message":"More evidence of the righteousness of https://review.opendev.org/#/c/733911/ -- ECFragGetter does *not* need this logic. It\u0027s not responsible for collecting and sifting through responses, just getting *a* response.","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":1363,"context_line":"        self.source_headers \u003d []"},{"line_number":1364,"context_line":"        self.sources \u003d []"},{"line_number":1365,"context_line":""},{"line_number":1366,"context_line":"        nodes \u003d GreenthreadSafeIterator(self.node_iter)"},{"line_number":1367,"context_line":""},{"line_number":1368,"context_line":"        node_timeout \u003d self.app.node_timeout"},{"line_number":1369,"context_line":"        if self.server_type \u003d\u003d \u0027Object\u0027 and not self.newest:"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_1c5a2c4f","line":1366,"updated":"2020-08-17 18:25:13.000000000","message":"so the node_iter in __init__ isn\u0027t a safe iter yet","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"}],"swift/proxy/controllers/obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":2922,"context_line":"                        get.last_status \u003d\u003d HTTP_NOT_FOUND and not timestamp:"},{"line_number":2923,"context_line":"                    ignore_rebalance_404s -\u003d 1"},{"line_number":2924,"context_line":"                else:"},{"line_number":2925,"context_line":"                    try:"},{"line_number":2926,"context_line":"                        buckets.add_response(get, parts_iter)"},{"line_number":2927,"context_line":"                    except ValueError as err:"},{"line_number":2928,"context_line":"                        self.app.logger.error("}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_fce93880","line":2925,"updated":"2020-08-17 18:25:13.000000000","message":"I think there\u0027s a smell here that stinks particularly bad with EC where we already do a bunch of work to bucket-ize responses as they come in so we can make the best decisions about additional requests and how to respond.","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"f71f73945ac96c4bae9bb39c5420f3422dc36ee7","unresolved":false,"context_lines":[{"line_number":2922,"context_line":"                        get.last_status \u003d\u003d HTTP_NOT_FOUND and not timestamp:"},{"line_number":2923,"context_line":"                    ignore_rebalance_404s -\u003d 1"},{"line_number":2924,"context_line":"                else:"},{"line_number":2925,"context_line":"                    try:"},{"line_number":2926,"context_line":"                        buckets.add_response(get, parts_iter)"},{"line_number":2927,"context_line":"                    except ValueError as err:"},{"line_number":2928,"context_line":"                        self.app.logger.error("}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_37ae2be7","line":2925,"in_reply_to":"9f560f44_fce93880","updated":"2020-08-17 18:44:30.000000000","message":"Maybe I could plumb it into the individual buckets instead, and have it only get used by the 404 bucket? *shrug*","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"4f7c5a4fa37237192a711625dca21abfe0c828be","unresolved":false,"context_lines":[{"line_number":3007,"context_line":"                        headers.append(getter.source_headers)"},{"line_number":3008,"context_line":""},{"line_number":3009,"context_line":"            if not statuses and is_success("},{"line_number":3010,"context_line":"                    best_bucket.status) and not best_bucket.durable:"},{"line_number":3011,"context_line":"                # pretend that non-durable bucket was 404s"},{"line_number":3012,"context_line":"                statuses.append(404)"},{"line_number":3013,"context_line":"                reasons.append(\u0027404 Not Found\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_7fe88715","line":3010,"updated":"2020-08-17 04:46:23.000000000","message":"Clay, we should maybe roll this into the waterfall-EC patch.","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":3007,"context_line":"                        headers.append(getter.source_headers)"},{"line_number":3008,"context_line":""},{"line_number":3009,"context_line":"            if not statuses and is_success("},{"line_number":3010,"context_line":"                    best_bucket.status) and not best_bucket.durable:"},{"line_number":3011,"context_line":"                # pretend that non-durable bucket was 404s"},{"line_number":3012,"context_line":"                statuses.append(404)"},{"line_number":3013,"context_line":"                reasons.append(\u0027404 Not Found\u0027)"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_3c03b044","line":3010,"in_reply_to":"9f560f44_7fe88715","updated":"2020-08-17 18:25:13.000000000","message":"maybe, i\u0027ll try to find a test that\u0027s up in here and see if I can tweek it to demonstrate the difference","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"dbbd41b8cb3639e86faec0fb0126c4e779134b72","unresolved":false,"context_lines":[{"line_number":3007,"context_line":"                                getter.status \u003d\u003d HTTP_NOT_FOUND and"},{"line_number":3008,"context_line":"                                not timestamp):"},{"line_number":3009,"context_line":"                            ignore_rebalance_404s -\u003d 1"},{"line_number":3010,"context_line":"                            continue"},{"line_number":3011,"context_line":"                        statuses.append(getter.status)"},{"line_number":3012,"context_line":"                        reasons.append(getter.reason)"},{"line_number":3013,"context_line":"                        bodies.append(getter.body)"}],"source_content_type":"text/x-python","patch_set":7,"id":"9f560f44_1210e2ff","line":3010,"updated":"2020-08-24 21:07:09.000000000","message":"but then I accidentally got inspired to try out some refactoring because I felt all safe and secure with my tests...\n\nSomehow I think I like it a little better down here where we\u0027re making decisions instead of up there where we\u0027re collecting responses?","commit_id":"0693e806c3899b3ae677b61ca0a835ff5ebfa2ac"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"dbbd41b8cb3639e86faec0fb0126c4e779134b72","unresolved":false,"context_lines":[{"line_number":3019,"context_line":"                statuses.append(404)"},{"line_number":3020,"context_line":"                reasons.append(\u0027404 Not Found\u0027)"},{"line_number":3021,"context_line":"                bodies.append(b\u0027\u0027)"},{"line_number":3022,"context_line":"                headers.append({})"},{"line_number":3023,"context_line":""},{"line_number":3024,"context_line":"            resp \u003d self.best_response("},{"line_number":3025,"context_line":"                req, statuses, reasons, bodies, \u0027Object\u0027,"}],"source_content_type":"text/x-python","patch_set":7,"id":"9f560f44_92fb52bc","line":3022,"updated":"2020-08-24 21:07:09.000000000","message":"this block feels *very* similar to the sneaky above - so maybe it\u0027s useful to keep the tricks we\u0027re playing on best_response closer together","commit_id":"0693e806c3899b3ae677b61ca0a835ff5ebfa2ac"}],"test/unit/proxy/controllers/test_base.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"daad73fb85ad11ab1c95ae4d094c83604c3d2120","unresolved":false,"context_lines":[{"line_number":1119,"context_line":"        source2 \u003d TestChunkedSource([b\u0027efgh5678\u0027])"},{"line_number":1120,"context_line":"        req \u003d Request.blank(\u0027/v1/a/c/o\u0027)"},{"line_number":1121,"context_line":"        handler \u003d GetOrHeadHandler("},{"line_number":1122,"context_line":"            self.app, req, \u0027Object\u0027, Namespace(num_primary_nodes\u003d1), None,"},{"line_number":1123,"context_line":"            None, {}, client_chunk_size\u003d8)"},{"line_number":1124,"context_line":""},{"line_number":1125,"context_line":"        app_iter \u003d handler._make_app_iter(req, node, source1)"}],"source_content_type":"text/x-python","patch_set":8,"id":"9f560f44_b46234d8","line":1122,"updated":"2020-09-02 17:37:30.000000000","message":"I didn\u0027t notice any problems making these 3 instead of 1?\n\n\tdiff --git a/test/unit/proxy/controllers/test_base.py b/test/unit/proxy/controllers/test_base.py\n\tindex 54736f016..bd4309e67 100644\n\t--- a/test/unit/proxy/controllers/test_base.py\n\t+++ b/test/unit/proxy/controllers/test_base.py\n\t@@ -923,7 +923,7 @@ class TestFuncs(BaseTest):\n\t\t # send out a new request. That new request must be for all 1000\n\t\t # bytes.\n\t\t handler \u003d GetOrHeadHandler(\n\t-            self.app, req, None, Namespace(num_primary_nodes\u003d1), None, None,\n\t+            self.app, req, None, Namespace(num_primary_nodes\u003d3), None, None,\n\t\t     {})\n\t\t handler.learn_size_from_content_range(0, 999, 1000)\n\t\t handler.fast_forward(0)\n\t@@ -932,7 +932,7 @@ class TestFuncs(BaseTest):\n\t\t # Same story as above, but a 1-byte object so we can have our byte\n\t\t # indices be 0.\n\t\t handler \u003d GetOrHeadHandler(\n\t-            self.app, req, None, Namespace(num_primary_nodes\u003d1), None, None,\n\t+            self.app, req, None, Namespace(num_primary_nodes\u003d3), None, None,\n\t\t     {})\n\t\t handler.learn_size_from_content_range(0, 0, 1)\n\t\t handler.fast_forward(0)\n\t@@ -940,7 +940,7 @@ class TestFuncs(BaseTest):\n\t \n\t\t # last 100 bytes\n\t\t handler \u003d GetOrHeadHandler(\n\t-            self.app, req, None, Namespace(num_primary_nodes\u003d1), None, None,\n\t+            self.app, req, None, Namespace(num_primary_nodes\u003d3), None, None,\n\t\t     {\u0027Range\u0027: \u0027bytes\u003d-100\u0027})\n\t\t handler.learn_size_from_content_range(900, 999, 1000)\n\t\t handler.fast_forward(0)","commit_id":"f497eaea9352d4baa4cd8e5735c04aede70d8c61"}],"test/unit/proxy/controllers/test_container.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"c8bbedb8060eaf2fe297a21728899123600f0afb","unresolved":false,"context_lines":[{"line_number":397,"context_line":"        # One more test, simulating all nodes being error-limited"},{"line_number":398,"context_line":"        class FakeIter(object):"},{"line_number":399,"context_line":"            num_primary_nodes \u003d 3"},{"line_number":400,"context_line":"            def __iter__(self):"},{"line_number":401,"context_line":"                return iter([])"},{"line_number":402,"context_line":""},{"line_number":403,"context_line":"        with mocked_http_conn(), mock.patch.object(self.app, \u0027iter_nodes\u0027,"}],"source_content_type":"text/x-python","patch_set":3,"id":"9f560f44_0ee84814","line":400,"updated":"2020-08-14 20:58:53.000000000","message":"pep8: E306 expected 1 blank line before a nested definition, found 0","commit_id":"3608b740ea279673309e5711b6b6265ed8695f0a"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"b031d143ed27640930566f37b86a490a0bb39bff","unresolved":false,"context_lines":[{"line_number":369,"context_line":"            ([Timeout()] * (nodes + handoffs), 503),"},{"line_number":370,"context_line":"            ([Timeout()] * (nodes + handoffs - 1) + [404], 503),"},{"line_number":371,"context_line":"            ([Timeout()] * (nodes - 1) + [404] * (handoffs + 1), 503),"},{"line_number":372,"context_line":"            ([Timeout()] * (nodes - 2) + [404] * (handoffs + 2), 404),"},{"line_number":373,"context_line":"            ([500] * (nodes - 1) + [404] * (handoffs + 1), 503),"},{"line_number":374,"context_line":"            ([503, 200], 200),"},{"line_number":375,"context_line":"            ([507, 200], 200),"}],"source_content_type":"text/x-python","patch_set":5,"id":"9f560f44_bc622015","line":372,"updated":"2020-08-17 18:25:13.000000000","message":"I wonder if this is the next one we want to change, and this would be 503 too if we increase ignore","commit_id":"d1351c1d8552df03eaf769d74446dc382bf6f5da"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"daad73fb85ad11ab1c95ae4d094c83604c3d2120","unresolved":false,"context_lines":[{"line_number":369,"context_line":"            ([Timeout()] * (nodes + handoffs), 503),"},{"line_number":370,"context_line":"            ([Timeout()] * (nodes + handoffs - 1) + [404], 503),"},{"line_number":371,"context_line":"            ([Timeout()] * (nodes - 1) + [404] * (handoffs + 1), 503),"},{"line_number":372,"context_line":"            ([Timeout()] * (nodes - 2) + [404] * (handoffs + 2), 404),"},{"line_number":373,"context_line":"            ([500] * (nodes - 1) + [404] * (handoffs + 1), 503),"},{"line_number":374,"context_line":"            ([503, 200], 200),"},{"line_number":375,"context_line":"            ([507, 200], 200),"}],"source_content_type":"text/x-python","patch_set":8,"id":"9f560f44_f45cac1a","line":372,"updated":"2020-09-02 17:37:30.000000000","message":"hawtness","commit_id":"f497eaea9352d4baa4cd8e5735c04aede70d8c61"}],"test/unit/proxy/controllers/test_obj.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"fd8e6d1464b7257731c79cc73667e9b229f3760c","unresolved":false,"context_lines":[{"line_number":1602,"context_line":"    def test_GET_primaries_error_during_rebalance(self):"},{"line_number":1603,"context_line":"        req \u003d swift.common.swob.Request.blank(\u0027/v1/a/c/o\u0027)"},{"line_number":1604,"context_line":"        primary_codes \u003d [Timeout(), Exception(\u0027kaboom!\u0027)] + \\"},{"line_number":1605,"context_line":"            [404] * (self.obj_ring.replicas - 2)"},{"line_number":1606,"context_line":"        random.shuffle(primary_codes)"},{"line_number":1607,"context_line":"        handoff_codes \u003d [404] * self.obj_ring.max_more_nodes"},{"line_number":1608,"context_line":"        with set_http_connect(*primary_codes + handoff_codes):"}],"source_content_type":"text/x-python","patch_set":1,"id":"9f560f44_afa1db48","line":1605,"updated":"2020-08-05 16:24:13.000000000","message":"if this test only ever runs with 3 replicas it might be more obvious to use a literal primary_codes:\n\n    [Timeout(), Exception(\u0027kaboom!\u0027), 404]","commit_id":"269c565afe621bbdbaaf30f06622c89e7cb020a6"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"dbbd41b8cb3639e86faec0fb0126c4e779134b72","unresolved":false,"context_lines":[{"line_number":2339,"context_line":"        # unless we have tombstones"},{"line_number":2340,"context_line":"        with mocked_http_conn(*codes, headers\u003d{\u0027X-Backend-Timestamp\u0027: \u00271\u0027}):"},{"line_number":2341,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2342,"context_line":"        self.assertEqual(resp.status_int, 404)"},{"line_number":2343,"context_line":""},{"line_number":2344,"context_line":"    def _test_if_match(self, method):"},{"line_number":2345,"context_line":"        num_responses \u003d self.policy.ec_ndata if method \u003d\u003d \u0027GET\u0027 else 1"}],"source_content_type":"text/x-python","patch_set":7,"id":"9f560f44_9266b2ba","line":2342,"updated":"2020-08-24 21:07:09.000000000","message":"so, i was just gunna add this test (because nothing was failing when i reverted changes to proxy.controller.obj)","commit_id":"0693e806c3899b3ae677b61ca0a835ff5ebfa2ac"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"daad73fb85ad11ab1c95ae4d094c83604c3d2120","unresolved":false,"context_lines":[{"line_number":1624,"context_line":"        # unless we explicitly *don\u0027t* want to trust it"},{"line_number":1625,"context_line":"        policy_opts \u003d self.app.get_policy_options(None)"},{"line_number":1626,"context_line":"        policy_opts.rebalance_missing_suppression_count \u003d 2"},{"line_number":1627,"context_line":"        do_test([Timeout(), 404, 404], 503)"},{"line_number":1628,"context_line":""},{"line_number":1629,"context_line":"    def test_GET_primaries_mixed_explode_and_timeout(self):"},{"line_number":1630,"context_line":"        req \u003d swift.common.swob.Request.blank(\u0027/v1/a/c/o\u0027)"}],"source_content_type":"text/x-python","patch_set":8,"id":"9f560f44_94ca909e","line":1627,"updated":"2020-09-02 17:37:30.000000000","message":"this is so great","commit_id":"f497eaea9352d4baa4cd8e5735c04aede70d8c61"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"daad73fb85ad11ab1c95ae4d094c83604c3d2120","unresolved":false,"context_lines":[{"line_number":2340,"context_line":"        # unless we have tombstones"},{"line_number":2341,"context_line":"        with mocked_http_conn(*codes, headers\u003d{\u0027X-Backend-Timestamp\u0027: \u00271\u0027}):"},{"line_number":2342,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2343,"context_line":"        self.assertEqual(resp.status_int, 404)"},{"line_number":2344,"context_line":""},{"line_number":2345,"context_line":"    def _test_if_match(self, method):"},{"line_number":2346,"context_line":"        num_responses \u003d self.policy.ec_ndata if method \u003d\u003d \u0027GET\u0027 else 1"}],"source_content_type":"text/x-python","patch_set":8,"id":"9f560f44_d448882f","line":2343,"updated":"2020-09-02 17:37:30.000000000","message":"about the same as the other one - belts and braces","commit_id":"f497eaea9352d4baa4cd8e5735c04aede70d8c61"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c673e3f350f28fc7cd773652ddcc793fc21d634b","unresolved":false,"context_lines":[{"line_number":2340,"context_line":"        # unless we have tombstones"},{"line_number":2341,"context_line":"        with mocked_http_conn(*codes, headers\u003d{\u0027X-Backend-Timestamp\u0027: \u00271\u0027}):"},{"line_number":2342,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2343,"context_line":"        self.assertEqual(resp.status_int, 404)"},{"line_number":2344,"context_line":""},{"line_number":2345,"context_line":"    def _test_if_match(self, method):"},{"line_number":2346,"context_line":"        num_responses \u003d self.policy.ec_ndata if method \u003d\u003d \u0027GET\u0027 else 1"}],"source_content_type":"text/x-python","patch_set":8,"id":"9f560f44_9a447776","line":2343,"in_reply_to":"9f560f44_d448882f","updated":"2020-09-02 22:56:09.000000000","message":"EC vs replicated -- seemed worth having both given how EC is handled by the changes in swift/proxy/controllers/obj.py while replicated is handled by changes in swift/proxy/controllers/base.py","commit_id":"f497eaea9352d4baa4cd8e5735c04aede70d8c61"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"c673e3f350f28fc7cd773652ddcc793fc21d634b","unresolved":false,"context_lines":[{"line_number":2327,"context_line":"        with mocked_http_conn(*codes):"},{"line_number":2328,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2329,"context_line":"        self.assertEqual(resp.status_int, 404)"},{"line_number":2330,"context_line":"        for i in range(self.policy.object_ring.replica_count - 2):"},{"line_number":2331,"context_line":"            codes[i] \u003d Timeout()"},{"line_number":2332,"context_line":"            with mocked_http_conn(*codes):"},{"line_number":2333,"context_line":"                resp \u003d req.get_response(self.app)"}],"source_content_type":"text/x-python","patch_set":9,"id":"9f560f44_dac8aa76","line":2330,"updated":"2020-09-02 22:56:09.000000000","message":"Re-using the app with all this looping makes for a flakey test: a node may get error-limited, causing the test to fail like\n\n FAIL: test_GET_primaries_error_during_rebalance (test.unit.proxy.controllers.test_obj.TestECObjController)\n ----------------------------------------------------------------------\n Traceback (most recent call last):\n   File \"/home/zuul/src/opendev.org/openstack/swift/test/unit/proxy/controllers/test_obj.py\", line 2342, in test_GET_primaries_error_during_rebalance\n     resp \u003d req.get_response(self.app)\n   File \"/usr/lib/python2.7/contextlib.py\", line 24, in __exit__\n     self.gen.next()\n   File \"/home/zuul/src/opendev.org/openstack/swift/test/unit/__init__.py\", line 1130, in mocked_http_conn\n     raise AssertionError(\u0027left over status %r\u0027 % left_over_status)\n AssertionError: left over status [404]\n\nWe ought to do something like\n\ndiff --git a/test/unit/proxy/controllers/test_obj.py b/test/unit/proxy/controllers/test_obj.py\nindex 880a9f12c..b173e64df 100644\n--- a/test/unit/proxy/controllers/test_obj.py\n+++ b/test/unit/proxy/controllers/test_obj.py\n@@ -2332,11 +2332,15 @@ class TestECObjController(ECObjectControllerMixin, unittest.TestCase):\n             with mocked_http_conn(*codes):\n                 resp \u003d req.get_response(self.app)\n             self.assertEqual(resp.status_int, 404)\n+            self.app._error_limiting \u003d {}  # Reset error limiting\n+\n         # one more timeout is past the tipping point\n         codes[self.policy.object_ring.replica_count - 2] \u003d Timeout()\n         with mocked_http_conn(*codes):\n             resp \u003d req.get_response(self.app)\n         self.assertEqual(resp.status_int, 503)\n+        self.app._error_limiting \u003d {}  # Reset error limiting\n+\n         # unless we have tombstones\n         with mocked_http_conn(*codes, headers\u003d{\u0027X-Backend-Timestamp\u0027: \u00271\u0027}):\n             resp \u003d req.get_response(self.app)\n\nto make it stable.","commit_id":"ea0737b56906ea2e42b3998410a58b8b31cd93a3"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"59f4afbaa4acaa3315bfaa7aaaae8cf675141ee5","unresolved":false,"context_lines":[{"line_number":2327,"context_line":"        with mocked_http_conn(*codes):"},{"line_number":2328,"context_line":"            resp \u003d req.get_response(self.app)"},{"line_number":2329,"context_line":"        self.assertEqual(resp.status_int, 404)"},{"line_number":2330,"context_line":"        for i in range(self.policy.object_ring.replica_count - 2):"},{"line_number":2331,"context_line":"            codes[i] \u003d Timeout()"},{"line_number":2332,"context_line":"            with mocked_http_conn(*codes):"},{"line_number":2333,"context_line":"                resp \u003d req.get_response(self.app)"}],"source_content_type":"text/x-python","patch_set":9,"id":"9f560f44_ac3a96c9","line":2330,"in_reply_to":"9f560f44_dac8aa76","updated":"2020-09-08 19:58:07.000000000","message":"oh that error limiting!","commit_id":"ea0737b56906ea2e42b3998410a58b8b31cd93a3"}],"test/unit/proxy/test_server.py":[{"author":{"_account_id":22348,"name":"Zuul","username":"zuul","tags":["SERVICE_USER"]},"tag":"autogenerated:zuul:check","change_message_id":"c8bbedb8060eaf2fe297a21728899123600f0afb","unresolved":false,"context_lines":[{"line_number":1022,"context_line":"        def fake_iter_nodes(*arg, **karg):"},{"line_number":1023,"context_line":"            class FakeNodeIter(object):"},{"line_number":1024,"context_line":"                num_primary_nodes \u003d 3"},{"line_number":1025,"context_line":"                def __iter__(self):"},{"line_number":1026,"context_line":"                    return iter(nodes)"},{"line_number":1027,"context_line":""},{"line_number":1028,"context_line":"            return FakeNodeIter()"}],"source_content_type":"text/x-python","patch_set":3,"id":"9f560f44_ae8ddc7c","line":1025,"updated":"2020-08-14 20:58:53.000000000","message":"pep8: E306 expected 1 blank line before a nested definition, found 0","commit_id":"3608b740ea279673309e5711b6b6265ed8695f0a"}]}
