)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dc5283d4ce1a9a35a92e2ef5a82e9854a18c1d88","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"8881375e_853e164c","updated":"2021-11-19 19:36:28.000000000","message":"recheck","commit_id":"d5000148a63bce569c9c369284f5491ed7bb74b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"d3ed5fa1_afde39ef","updated":"2021-11-22 15:52:19.000000000","message":"I\u0027m a little torn here; but I think mostly it\u0027s stylistic concerns - is this a high priority to cleanup?  what\u0027s the negative impact of not doing anything for now?","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92c9454b9d665cf575e9fea03b7793518d9a9b7e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"9776f3c9_2b182243","updated":"2021-11-22 11:13:28.000000000","message":"rebased to avoid conflict with https://review.opendev.org/c/openstack/swift/+/818017","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"d8ba50335a7cb5d9630e295a2de363b9b3bf6c71","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"7628ba13_5e1d3986","updated":"2021-11-23 14:55:53.000000000","message":"the positive impact of the change is less distraction from error level logging and Broke Pipe exceptions when the protocol is actually behaving itself.","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}],"swift/common/exceptions.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dc5283d4ce1a9a35a92e2ef5a82e9854a18c1d88","unresolved":true,"context_lines":[{"line_number":223,"context_line":"    pass"},{"line_number":224,"context_line":""},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"class SsyncWarning(Exception):"},{"line_number":227,"context_line":"    pass"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"5a5916ca_4f3afe9a","line":226,"range":{"start_line":226,"start_character":19,"end_line":226,"end_character":28},"updated":"2021-11-19 19:36:28.000000000","message":"Not SwiftException? I see we\u0027ve got some others that go direct from Exception, though... not sure why we\u0027d want one vs. the other.","commit_id":"d5000148a63bce569c9c369284f5491ed7bb74b0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92c9454b9d665cf575e9fea03b7793518d9a9b7e","unresolved":true,"context_lines":[{"line_number":223,"context_line":"    pass"},{"line_number":224,"context_line":""},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"class SsyncWarning(Exception):"},{"line_number":227,"context_line":"    pass"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":""}],"source_content_type":"text/x-python","patch_set":2,"id":"15640b3b_8e6cc5f6","line":226,"range":{"start_line":226,"start_character":19,"end_line":226,"end_character":28},"in_reply_to":"5a5916ca_4f3afe9a","updated":"2021-11-22 11:13:28.000000000","message":"I followed the example ReplicationException, but like you I\u0027m not sure what   pattern we have for using the SwiftException subclass","commit_id":"d5000148a63bce569c9c369284f5491ed7bb74b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":224,"context_line":""},{"line_number":225,"context_line":""},{"line_number":226,"context_line":"class SsyncWarning(Exception):"},{"line_number":227,"context_line":"    pass"},{"line_number":228,"context_line":""},{"line_number":229,"context_line":""},{"line_number":230,"context_line":"class MimeInvalid(SwiftException):"}],"source_content_type":"text/x-python","patch_set":3,"id":"ed0e9f18_48aeefb6","line":227,"updated":"2021-11-22 15:52:19.000000000","message":"I think exceptions that aren\u0027t errors are an anti-pattern","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}],"swift/obj/ssync_receiver.py":[{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"dc5283d4ce1a9a35a92e2ef5a82e9854a18c1d88","unresolved":true,"context_lines":[{"line_number":191,"context_line":"                        self.request.remote_addr, self.device, self.partition,"},{"line_number":192,"context_line":"                        err))"},{"line_number":193,"context_line":"                yield (\u0027:WARN: %d %r\\n\u0027 % (0, str(err))).encode(\u0027utf8\u0027)"},{"line_number":194,"context_line":"                self.disconnect \u003d False"},{"line_number":195,"context_line":"            except exceptions.MessageTimeout as err:"},{"line_number":196,"context_line":"                self.app.logger.error("},{"line_number":197,"context_line":"                    \u0027%s/%s/%s TIMEOUT in ssync.Receiver: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":2,"id":"95c1f81b_6f9f097e","line":194,"updated":"2021-11-19 19:36:28.000000000","message":"Does this have any rolling upgrade implications? Or was the client already doing sane things?","commit_id":"d5000148a63bce569c9c369284f5491ed7bb74b0"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"92c9454b9d665cf575e9fea03b7793518d9a9b7e","unresolved":true,"context_lines":[{"line_number":191,"context_line":"                        self.request.remote_addr, self.device, self.partition,"},{"line_number":192,"context_line":"                        err))"},{"line_number":193,"context_line":"                yield (\u0027:WARN: %d %r\\n\u0027 % (0, str(err))).encode(\u0027utf8\u0027)"},{"line_number":194,"context_line":"                self.disconnect \u003d False"},{"line_number":195,"context_line":"            except exceptions.MessageTimeout as err:"},{"line_number":196,"context_line":"                self.app.logger.error("},{"line_number":197,"context_line":"                    \u0027%s/%s/%s TIMEOUT in ssync.Receiver: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":2,"id":"88933db1_f647a473","line":194,"in_reply_to":"95c1f81b_6f9f097e","updated":"2021-11-22 11:13:28.000000000","message":"An old sender will continue to log an error, but with the :WARN: message:\n\n  test-ssync-sender ERROR: 127.0.0.1:52162/dev/9 Unexpected response: \":WARN: 0 \u00270.9990620613098145 seconds: /var/folders/n4/nf8krx110f39llj82fbw_xjm0000gp/T/tmp4o2g1z66/tmp_test_ssync_receiver/dev/.lock\u0027\"\n\nAs for the disconnect:\n\nIf the sender has sent all its missing check bytes and is waiting for a receiver response, it will get the timeout message and close its connection. The change avoids a BrokenPipe exception on the receiver.\n\nIf the sender has stalled while sending missing_check bytes, it will eventually timeout (same as before) . Maybe bytes get drained in receiver\u0027s wsgi, but these are just missing check bytes so relatively few, and the change avoids the BrokenPipe traceback.\n\nThe forceful disconnect seems more valuable when the protocol has reached updates phase and the sender is sending object data.","commit_id":"d5000148a63bce569c9c369284f5491ed7bb74b0"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":191,"context_line":"                        self.request.remote_addr, self.device, self.partition,"},{"line_number":192,"context_line":"                        err))"},{"line_number":193,"context_line":"                yield (\u0027:WARN: %d %r\\n\u0027 % (0, str(err))).encode(\u0027utf8\u0027)"},{"line_number":194,"context_line":"                self.disconnect \u003d False"},{"line_number":195,"context_line":"            except exceptions.MessageTimeout as err:"},{"line_number":196,"context_line":"                self.app.logger.error("},{"line_number":197,"context_line":"                    \u0027%s/%s/%s TIMEOUT in ssync.Receiver: %s\u0027 % ("}],"source_content_type":"text/x-python","patch_set":3,"id":"2eedc8b0_c806432e","line":194,"updated":"2021-11-22 15:52:19.000000000","message":"the assumption is the sender will close the connection when it reads back the warning (after sending all the missing check or blocking and timing out)","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}],"swift/obj/ssync_sender.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":186,"context_line":"                # to be sync\u0027ed;"},{"line_number":187,"context_line":"                # each entry maps an object hash \u003d\u003e dict of wanted parts"},{"line_number":188,"context_line":"                available_map, send_map \u003d self.missing_check(connection,"},{"line_number":189,"context_line":"                                                             response)"},{"line_number":190,"context_line":"                if self.remote_check_objs is None:"},{"line_number":191,"context_line":"                    self.updates(connection, response, send_map)"},{"line_number":192,"context_line":"                    can_delete_obj \u003d available_map"}],"source_content_type":"text/x-python","patch_set":3,"id":"85862e6a_05972338","line":189,"updated":"2021-11-22 15:52:19.000000000","message":"... but there\u0027s no other way to return an \"warning\" from this interface","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":354,"context_line":"                        pass"},{"line_number":355,"context_line":"                if line.startswith(\u0027:WARN:\u0027):"},{"line_number":356,"context_line":"                    raise exceptions.SsyncWarning("},{"line_number":357,"context_line":"                        \u0027Terminating after missing_check: %r\u0027 % line[:1024])"},{"line_number":358,"context_line":"                else:"},{"line_number":359,"context_line":"                    raise exceptions.ReplicationException("},{"line_number":360,"context_line":"                        \u0027Unexpected response: %r\u0027 % line[:1024])"}],"source_content_type":"text/x-python","patch_set":3,"id":"61aa40b2_af25bb6d","line":357,"updated":"2021-11-22 15:52:19.000000000","message":"this feels like using an exception as flow control - like a goto","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8cf9581f05017d297778c6978f744e4f031b7ef5","unresolved":true,"context_lines":[{"line_number":354,"context_line":"                        pass"},{"line_number":355,"context_line":"                if line.startswith(\u0027:WARN:\u0027):"},{"line_number":356,"context_line":"                    raise exceptions.SsyncWarning("},{"line_number":357,"context_line":"                        \u0027Terminating after missing_check: %r\u0027 % line[:1024])"},{"line_number":358,"context_line":"                else:"},{"line_number":359,"context_line":"                    raise exceptions.ReplicationException("},{"line_number":360,"context_line":"                        \u0027Unexpected response: %r\u0027 % line[:1024])"}],"source_content_type":"text/x-python","patch_set":3,"id":"544d1a26_cc45fd7a","line":357,"in_reply_to":"61aa40b2_af25bb6d","updated":"2021-11-23 14:54:13.000000000","message":"yes. I didn\u0027t *like* this but as you observe there\u0027s no other return path (without major surgery).\n\nMaybe the \u0027SsyncWarning\u0027 is a misnomer for an Exception, but I\u0027m not sure I think of it as an anti-pattern any more than StopIteration or DiskFileExpired.","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}],"test/unit/obj/test_ssync.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":1421,"context_line":"                \u0027device\u0027: self.device,"},{"line_number":1422,"context_line":"                \u0027index\u0027: 0}"},{"line_number":1423,"context_line":"        sender \u003d ssync_sender.Sender(self.daemon, node, job, [\u0027abc\u0027])"},{"line_number":1424,"context_line":"        sender.connect, trace \u003d self.make_connect_wrapper(sender)"},{"line_number":1425,"context_line":""},{"line_number":1426,"context_line":"        with lock_path(self.rx_device):"},{"line_number":1427,"context_line":"            # receiver cannot get the device level lock"}],"source_content_type":"text/x-python","patch_set":3,"id":"e455f5f7_2b70d65c","line":1424,"updated":"2021-11-22 15:52:19.000000000","message":"here\u0027s were all the tracing is installed on the sender instance","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":1446,"context_line":"        self.assertEqual(1, len(warn_lines), warn_lines)"},{"line_number":1447,"context_line":"        self.assertIn(\u0027SSYNC LOCK TIMEOUT\u0027, warn_lines[0])"},{"line_number":1448,"context_line":"        self.assertIn(self.rx_device, warn_lines[0])"},{"line_number":1449,"context_line":"        self.assertTrue(trace[\u0027tx_connection_closed\u0027])"},{"line_number":1450,"context_line":""},{"line_number":1451,"context_line":"    def test_meta_file_sync(self):"},{"line_number":1452,"context_line":"        policy \u003d POLICIES.default"}],"source_content_type":"text/x-python","patch_set":3,"id":"9c74f0c5_151d3e72","line":1449,"updated":"2021-11-22 15:52:19.000000000","message":"so the sender is closing the connection","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}],"test/unit/obj/test_ssync_sender.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"30c90a9343a4311cac96234d40e6141edd59f932","unresolved":true,"context_lines":[{"line_number":1110,"context_line":"        self.assertEqual("},{"line_number":1111,"context_line":"            b\u0027\u0027.join(connection.sent),"},{"line_number":1112,"context_line":"            b\u002717\\r\\n:MISSING_CHECK: START\\r\\n\\r\\n\u0027"},{"line_number":1113,"context_line":"            b\u002733\\r\\n9d41d8cd98f00b204e9800998ecf0abc 1380144470.00000\\r\\n\\r\\n\u0027"},{"line_number":1114,"context_line":"            b\u002715\\r\\n:MISSING_CHECK: END\\r\\n\\r\\n\u0027)"},{"line_number":1115,"context_line":""},{"line_number":1116,"context_line":"    def test_missing_check_send_map(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"35cca1cb_876aafc5","line":1113,"updated":"2021-11-22 15:52:19.000000000","message":"i\u0027m sure it\u0027d be harder to simulate a sender getting blocked on send only to discover the warning","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"8cf9581f05017d297778c6978f744e4f031b7ef5","unresolved":true,"context_lines":[{"line_number":1110,"context_line":"        self.assertEqual("},{"line_number":1111,"context_line":"            b\u0027\u0027.join(connection.sent),"},{"line_number":1112,"context_line":"            b\u002717\\r\\n:MISSING_CHECK: START\\r\\n\\r\\n\u0027"},{"line_number":1113,"context_line":"            b\u002733\\r\\n9d41d8cd98f00b204e9800998ecf0abc 1380144470.00000\\r\\n\\r\\n\u0027"},{"line_number":1114,"context_line":"            b\u002715\\r\\n:MISSING_CHECK: END\\r\\n\\r\\n\u0027)"},{"line_number":1115,"context_line":""},{"line_number":1116,"context_line":"    def test_missing_check_send_map(self):"}],"source_content_type":"text/x-python","patch_set":3,"id":"0be1a424_860ab56b","line":1113,"in_reply_to":"35cca1cb_876aafc5","updated":"2021-11-23 14:54:13.000000000","message":"it is, although I did hack some sleeps into Sender to manually verify","commit_id":"5bf21649f061cf528d7aece0d4350eba3f98a32d"}]}
