)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":19,"context_line":"from \u0027shard-listing/\u003caccount\u003e/\u003ccontainer\u003e\u0027 to"},{"line_number":20,"context_line":"\u0027shard-listing-v2/\u003caccount\u003e/\u003ccontainer\u003e\u0027, and cache data is"},{"line_number":21,"context_line":"changed to be a list of [lower bound, name]. As a result, this"},{"line_number":22,"context_line":"will invalid all existing listing shard ranges stored in the"},{"line_number":23,"context_line":"memcache cluster."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I54a32fd16e3d02b00c18b769c6f675bae3ba8e01"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"561f9534_cb39c5fa","line":22,"range":{"start_line":22,"start_character":5,"end_line":22,"end_character":13},"updated":"2023-03-16 17:55:47.000000000","message":"s/invalid/invalidate/","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":19,"context_line":"from \u0027shard-listing/\u003caccount\u003e/\u003ccontainer\u003e\u0027 to"},{"line_number":20,"context_line":"\u0027shard-listing-v2/\u003caccount\u003e/\u003ccontainer\u003e\u0027, and cache data is"},{"line_number":21,"context_line":"changed to be a list of [lower bound, name]. As a result, this"},{"line_number":22,"context_line":"will invalid all existing listing shard ranges stored in the"},{"line_number":23,"context_line":"memcache cluster."},{"line_number":24,"context_line":""},{"line_number":25,"context_line":"Change-Id: I54a32fd16e3d02b00c18b769c6f675bae3ba8e01"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":3,"id":"0c34e390_93491b7b","line":22,"range":{"start_line":22,"start_character":5,"end_line":22,"end_character":13},"in_reply_to":"561f9534_cb39c5fa","updated":"2023-03-19 00:00:37.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8ec8f2f8a9f880d48b2f010f17c5903eb0a90a06","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"338c2761_02411d0e","updated":"2023-03-09 07:02:21.000000000","message":"still need fix/add tests in test_container.","commit_id":"a89c6ab5a6e730eef9e99577f29ac1bbe65fe84c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"17416c16_c8c2b4ca","updated":"2023-03-16 17:55:47.000000000","message":"This is looking pretty good.\n\nSome suggestions here (some addressing my comments) https://review.opendev.org/c/openstack/swift/+/877703\n\nI want to think more about what happens when the backend returns a list of shard ranges with a gap. \n\nBefore, IIUC, the gap would remain in the cached list, and I want to refresh my understanding of what happens when the listing logic encounters that gap.\n\nAfter this change, IIUC, the gap will be filled as a result of round-tripping though a NamespaceBoundsList, such that the gap namespace before the gap expands to cover the gap.","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"36b66870cc416eedbe493701e2377434b4182fa1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":3,"id":"b59a75ab_30d65c8b","updated":"2023-03-14 02:20:00.000000000","message":"recheck\nall unit/probe tests passed. Failed tests seem not related to this patch.\n\"An error occurred (BucketAlreadyOwnedByYou) when calling the CreateBucket operation: Your previous request to create the named bucket succeeded and you already own it.\"","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"edf1c84b9ed679cbcdc6f2b7d426ec9405a92519","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"556c3a44_7e8a3509","updated":"2023-03-17 12:43:38.000000000","message":"@Jianjian I added https://review.opendev.org/c/openstack/swift/+/877787 as a pre-requisite. I think the git history will be easier to follow if the new test and test fixes merge ahead of this patch which then changes the assertions.\n\nI\u0027d prefer the follow changes to be squashed https://review.opendev.org/c/openstack/swift/+/877703, and I\u0027m not keen on the convert() method naming, but functionally this all makes sense.","commit_id":"1bce37fdecee84f5ddaec6a4a5b7e307f7701c6e"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"aaa02fd434f6040bc8822a731b95691dd4b2b612","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"a4bf0aa8_e25612de","updated":"2023-03-17 14:53:25.000000000","message":"I squashed in the docstrings from follow on patch","commit_id":"110847a9415b7a73928b47315f96697a71282f24"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"ca629788cf53c40f782212807c55a62336e93d8a","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"9395cf36_c112cd08","updated":"2023-03-18 02:43:38.000000000","message":"recheck\n\"503 Service Unavailable\" during test setup, not related.","commit_id":"110847a9415b7a73928b47315f96697a71282f24"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"11ea6cb5_47418d6c","updated":"2023-03-19 00:00:37.000000000","message":"thanks for the review and help!","commit_id":"110847a9415b7a73928b47315f96697a71282f24"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"4b88c2ced23a62d8e6679d37fbeeacfff0e92c96","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"b6663172_5b254fba","updated":"2023-04-28 15:00:20.000000000","message":"recheck","commit_id":"71d507f8e17295fac1a97c8aab3883e042665fc4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c703e359cc3760359089bfda50619fde4fe739e7","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"d7a33d2b_32cf98d2","updated":"2023-04-28 04:40:10.000000000","message":"recheck","commit_id":"71d507f8e17295fac1a97c8aab3883e042665fc4"},{"author":{"_account_id":15343,"name":"Tim Burke","email":"tburke@nvidia.com","username":"tburke"},"change_message_id":"3dc799c45effa2230768c88e26c4fa064d6eee16","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"57ced702_df399d22","updated":"2023-04-28 17:23:53.000000000","message":"recheck\n\n```\n[ERROR] /opt/stack/new/grenade/inc/plugin:123 Failed to run /opt/stack/new/grenade/projects/70_cinder/resources.sh verify pre-upgrade\n```\n\nThe grenade job generally looks reasonably healthy, though.","commit_id":"71d507f8e17295fac1a97c8aab3883e042665fc4"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2c69a80e960e751c629b128319e881a973bea8e2","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"c689a61b_6fd5d21f","updated":"2023-04-28 12:55:34.000000000","message":"recheck\n\nflakey probe test has been fixed https://review.opendev.org/c/openstack/swift/+/881672","commit_id":"71d507f8e17295fac1a97c8aab3883e042665fc4"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"52539d58ce2e13a24968088d82b6b754683637dc","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":7,"id":"e046f708_2796559e","updated":"2023-04-28 16:27:32.000000000","message":"we\u0027ve been running this in production for a while. The change makes the listing state shard range cache format the same as the updating shard range cache format that already merged.","commit_id":"71d507f8e17295fac1a97c8aab3883e042665fc4"}],"swift/common/utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":5551,"context_line":"        # test for equality of NamespaceBoundList objects only"},{"line_number":5552,"context_line":"        if not isinstance(other, NamespaceBoundList):"},{"line_number":5553,"context_line":"            return False"},{"line_number":5554,"context_line":"        return self.bounds \u003d\u003d other.bounds"},{"line_number":5555,"context_line":""},{"line_number":5556,"context_line":"    @classmethod"},{"line_number":5557,"context_line":"    def parse(cls, namespaces):"}],"source_content_type":"text/x-python","patch_set":3,"id":"b3dfd1cf_8c03cadf","line":5554,"updated":"2023-03-16 17:55:47.000000000","message":"This is added so that unit tests can assert equality of the lists","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":5551,"context_line":"        # test for equality of NamespaceBoundList objects only"},{"line_number":5552,"context_line":"        if not isinstance(other, NamespaceBoundList):"},{"line_number":5553,"context_line":"            return False"},{"line_number":5554,"context_line":"        return self.bounds \u003d\u003d other.bounds"},{"line_number":5555,"context_line":""},{"line_number":5556,"context_line":"    @classmethod"},{"line_number":5557,"context_line":"    def parse(cls, namespaces):"}],"source_content_type":"text/x-python","patch_set":3,"id":"64602fa5_275cd165","line":5554,"in_reply_to":"b3dfd1cf_8c03cadf","updated":"2023-03-19 00:00:37.000000000","message":"Ack","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":5624,"context_line":"                 else self.bounds[pos + 1][0])"},{"line_number":5625,"context_line":"        return Namespace(name, lower, upper)"},{"line_number":5626,"context_line":""},{"line_number":5627,"context_line":"    def convert(self):"},{"line_number":5628,"context_line":"        \"\"\""},{"line_number":5629,"context_line":"        Convert this NamespaceBoundList object to a list of Namespaces."},{"line_number":5630,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"748ccbf7_e907b3bd","line":5627,"range":{"start_line":5627,"start_character":8,"end_line":5627,"end_character":15},"updated":"2023-03-16 17:55:47.000000000","message":"I\u0027m not sure about calling this convert(), and the docstring saying \"Convert this NamespaceBoundList object to a list of Namespaces.\" That could be interpreted as converting the list that this instance is wrapping, in situ, rather than creating a new list.\n\nget_namespaces() would perhaps be better, and relate better to get_namespace()?\n\n  \"Get the contained namespaces as a list of contiguous Namespaces ordered\n   by lower bound.\"","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":5624,"context_line":"                 else self.bounds[pos + 1][0])"},{"line_number":5625,"context_line":"        return Namespace(name, lower, upper)"},{"line_number":5626,"context_line":""},{"line_number":5627,"context_line":"    def convert(self):"},{"line_number":5628,"context_line":"        \"\"\""},{"line_number":5629,"context_line":"        Convert this NamespaceBoundList object to a list of Namespaces."},{"line_number":5630,"context_line":""}],"source_content_type":"text/x-python","patch_set":3,"id":"11495463_b0bc8001","line":5627,"range":{"start_line":5627,"start_character":8,"end_line":5627,"end_character":15},"in_reply_to":"748ccbf7_e907b3bd","updated":"2023-03-19 00:00:37.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3f9779acf31fc2c6866d7370b909b3fe074c5069","unresolved":true,"context_lines":[{"line_number":5717,"context_line":"        \u0027_deleted\u0027, \u0027_state\u0027, \u0027_count\u0027, \u0027_bytes\u0027,"},{"line_number":5718,"context_line":"        \u0027_tombstones\u0027, \u0027_reported\u0027)"},{"line_number":5719,"context_line":""},{"line_number":5720,"context_line":"    def __init__(self, name, timestamp\u003d0,"},{"line_number":5721,"context_line":"                 lower\u003dNamespace.MIN, upper\u003dNamespace.MAX,"},{"line_number":5722,"context_line":"                 object_count\u003d0, bytes_used\u003d0, meta_timestamp\u003dNone,"},{"line_number":5723,"context_line":"                 deleted\u003dFalse, state\u003dNone, state_timestamp\u003dNone, epoch\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"e2280195_9217a12f","line":5720,"range":{"start_line":5720,"start_character":29,"end_line":5720,"end_character":40},"updated":"2023-03-17 12:36:21.000000000","message":"note to self: this change is necessary so that we can construct a ShardRange using just lower, upper and name from a Namespace.","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":5717,"context_line":"        \u0027_deleted\u0027, \u0027_state\u0027, \u0027_count\u0027, \u0027_bytes\u0027,"},{"line_number":5718,"context_line":"        \u0027_tombstones\u0027, \u0027_reported\u0027)"},{"line_number":5719,"context_line":""},{"line_number":5720,"context_line":"    def __init__(self, name, timestamp\u003d0,"},{"line_number":5721,"context_line":"                 lower\u003dNamespace.MIN, upper\u003dNamespace.MAX,"},{"line_number":5722,"context_line":"                 object_count\u003d0, bytes_used\u003d0, meta_timestamp\u003dNone,"},{"line_number":5723,"context_line":"                 deleted\u003dFalse, state\u003dNone, state_timestamp\u003dNone, epoch\u003dNone,"}],"source_content_type":"text/x-python","patch_set":3,"id":"bb6df892_4aaec204","line":5720,"range":{"start_line":5720,"start_character":29,"end_line":5720,"end_character":40},"in_reply_to":"e2280195_9217a12f","updated":"2023-03-19 00:00:37.000000000","message":"Ack","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3f9779acf31fc2c6866d7370b909b3fe074c5069","unresolved":true,"context_lines":[{"line_number":6349,"context_line":"    ``end_marker``. If none of ``includes``, ``marker`` or ``end_marker`` are"},{"line_number":6350,"context_line":"    specified then all Namespaces/ShardRanges will be returned."},{"line_number":6351,"context_line":""},{"line_number":6352,"context_line":"    :param namespaces: A list of :class:`~swift.common.utils.Namespace` or"},{"line_number":6353,"context_line":"        :class:`~swift.common.utils.ShardRange`."},{"line_number":6354,"context_line":"    :param includes: a string; if not empty then only the Namespace/ShardRange,"},{"line_number":6355,"context_line":"        if any, whose namespace includes this string will be returned,"},{"line_number":6356,"context_line":"        ``marker`` and ``end_marker`` will be ignored."}],"source_content_type":"text/x-python","patch_set":3,"id":"eaa7477f_297a7440","line":6353,"range":{"start_line":6352,"start_character":33,"end_line":6353,"end_character":47},"updated":"2023-03-17 12:36:21.000000000","message":"I\u0027m not convinced that we need to keep reminding ourselves that a ShardRange is a Namespace. Maybe once in the overview of the docstring.","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":6349,"context_line":"    ``end_marker``. If none of ``includes``, ``marker`` or ``end_marker`` are"},{"line_number":6350,"context_line":"    specified then all Namespaces/ShardRanges will be returned."},{"line_number":6351,"context_line":""},{"line_number":6352,"context_line":"    :param namespaces: A list of :class:`~swift.common.utils.Namespace` or"},{"line_number":6353,"context_line":"        :class:`~swift.common.utils.ShardRange`."},{"line_number":6354,"context_line":"    :param includes: a string; if not empty then only the Namespace/ShardRange,"},{"line_number":6355,"context_line":"        if any, whose namespace includes this string will be returned,"},{"line_number":6356,"context_line":"        ``marker`` and ``end_marker`` will be ignored."}],"source_content_type":"text/x-python","patch_set":3,"id":"d451af62_c5d33eeb","line":6353,"range":{"start_line":6352,"start_character":33,"end_line":6353,"end_character":47},"in_reply_to":"eaa7477f_297a7440","updated":"2023-03-19 00:00:37.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"}],"swift/proxy/controllers/container.py":[{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"8ec8f2f8a9f880d48b2f010f17c5903eb0a90a06","unresolved":true,"context_lines":[{"line_number":252,"context_line":"        if (resp_record_type \u003d\u003d \u0027shard\u0027 and"},{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"}],"source_content_type":"text/x-python","patch_set":1,"id":"f265acf8_84437b1f","line":255,"updated":"2023-03-09 07:02:21.000000000","message":"Since we only store shard ranges in cache when container is \"sharded\", that means the shard ranges are complete, and we don\u0027t need to worry about gaps. So we can continue to reuse the same format of updating shard range cache v2, only store a list of [lower, name].","commit_id":"a89c6ab5a6e730eef9e99577f29ac1bbe65fe84c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":252,"context_line":"        if (resp_record_type \u003d\u003d \u0027shard\u0027 and"},{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"}],"source_content_type":"text/x-python","patch_set":1,"id":"8ed77f14_7e187612","line":255,"in_reply_to":"7d86bba5_626ba04a","updated":"2023-03-16 17:55:47.000000000","message":"That comment is referring to when the backend has *filled* a gap with it\u0027s own shard range, so the proxy gets a gap-less list of shard ranges. The backend currently only fills gaps at the end of the requested namespace. For example, there may be a gap in listing shard ranges when not all shard have yet cleaved (i.e. not all shard ranges are yet in one of the SHARD_LISTING_STATES [1]). This is expected during sharding.\n\nI\u0027m more concerned about how we handle gaps due to some error/bug that causes a shard range to be deleted from the root container\u0027s list, in the middle of the list.\n\n[1] https://github.com/openstack/swift/blob/6994200026f7a1f2721a57943a7c346405551d55/swift/container/backend.py#L54","commit_id":"a89c6ab5a6e730eef9e99577f29ac1bbe65fe84c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":false,"context_lines":[{"line_number":252,"context_line":"        if (resp_record_type \u003d\u003d \u0027shard\u0027 and"},{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"}],"source_content_type":"text/x-python","patch_set":1,"id":"1ad5aa8a_86670508","line":255,"in_reply_to":"8ed77f14_7e187612","updated":"2023-03-19 00:00:37.000000000","message":"Ack","commit_id":"a89c6ab5a6e730eef9e99577f29ac1bbe65fe84c"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"a448ff8317fe0379183e819827c8754247fa9c3a","unresolved":true,"context_lines":[{"line_number":252,"context_line":"        if (resp_record_type \u003d\u003d \u0027shard\u0027 and"},{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"}],"source_content_type":"text/x-python","patch_set":1,"id":"7d86bba5_626ba04a","line":255,"in_reply_to":"f265acf8_84437b1f","updated":"2023-03-10 01:39:11.000000000","message":"Alistair, is this the potential gap listing shard ranges could encounter?\nhttps://github.com/openstack/swift/blob/ece4b04e8215f80b55c367abc523290b503efc76/swift/proxy/controllers/container.py#L381","commit_id":"a89c6ab5a6e730eef9e99577f29ac1bbe65fe84c"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":133,"context_line":"            namespaces.reverse()"},{"line_number":134,"context_line":"        return json.dumps([dict(ns) for ns in namespaces]).encode(\u0027ascii\u0027)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    def _get_shard_ranges_from_cache(self, req, headers):"},{"line_number":137,"context_line":"        infocache \u003d req.environ.setdefault(\u0027swift.infocache\u0027, {})"},{"line_number":138,"context_line":"        memcache \u003d cache_from_env(req.environ, True)"},{"line_number":139,"context_line":"        cache_key \u003d get_cache_key(self.account_name,"}],"source_content_type":"text/x-python","patch_set":3,"id":"effaed75_040b7432","line":136,"updated":"2023-03-16 17:55:47.000000000","message":"I think it\u0027s worth adding a docstring to match _get_shard_ranges_from_backend (at least to help keep track of the return types). Something like:\n\n  \"\"\"\n  Try to fetch shard namespace data from cache and return a response.\n  The response body will be a list of dicts each of which describes\n  a Namespace (i.e. includes the keys ``lower``, ``upper`` and ``name``).\n    \n  :param req: an instance of swob.Request\n  :return: an instance of swob.Response, or None if no namespaces were \n      found in cache\n  \"\"\"","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"aaa02fd434f6040bc8822a731b95691dd4b2b612","unresolved":false,"context_lines":[{"line_number":133,"context_line":"            namespaces.reverse()"},{"line_number":134,"context_line":"        return json.dumps([dict(ns) for ns in namespaces]).encode(\u0027ascii\u0027)"},{"line_number":135,"context_line":""},{"line_number":136,"context_line":"    def _get_shard_ranges_from_cache(self, req, headers):"},{"line_number":137,"context_line":"        infocache \u003d req.environ.setdefault(\u0027swift.infocache\u0027, {})"},{"line_number":138,"context_line":"        memcache \u003d cache_from_env(req.environ, True)"},{"line_number":139,"context_line":"        cache_key \u003d get_cache_key(self.account_name,"}],"source_content_type":"text/x-python","patch_set":3,"id":"e79870fc_6c362e04","line":136,"in_reply_to":"effaed75_040b7432","updated":"2023-03-17 14:53:25.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":156,"context_line":"                        cache_key, raise_on_error\u003dTrue)"},{"line_number":157,"context_line":"                    if cached_namespaces:"},{"line_number":158,"context_line":"                        cache_state \u003d \u0027hit\u0027"},{"line_number":159,"context_line":"                        if six.PY2:"},{"line_number":160,"context_line":"                            # json.loads() in memcache.get will convert json"},{"line_number":161,"context_line":"                            # \u0027string\u0027 to \u0027unicode\u0027 with python2, here we cast"},{"line_number":162,"context_line":"                            # \u0027unicode\u0027 back to \u0027str\u0027"},{"line_number":163,"context_line":"                            cached_namespaces \u003d ["},{"line_number":164,"context_line":"                                [lower.encode(\u0027utf-8\u0027), name.encode(\u0027utf-8\u0027)]"},{"line_number":165,"context_line":"                                for lower, name in cached_namespaces]"},{"line_number":166,"context_line":"                        ns_bound_list \u003d NamespaceBoundList(cached_namespaces)"},{"line_number":167,"context_line":"                        resp_body \u003d self._make_namespaces_response_body("},{"line_number":168,"context_line":"                            req, ns_bound_list)"},{"line_number":169,"context_line":"                    else:"}],"source_content_type":"text/x-python","patch_set":3,"id":"fb8def78_6701b845","line":166,"range":{"start_line":159,"start_character":0,"end_line":166,"end_character":0},"updated":"2023-03-16 17:55:47.000000000","message":"can we move this to the NamespaceBoundsList contructor? we have the same encoding in obj.py","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"aaa02fd434f6040bc8822a731b95691dd4b2b612","unresolved":false,"context_lines":[{"line_number":156,"context_line":"                        cache_key, raise_on_error\u003dTrue)"},{"line_number":157,"context_line":"                    if cached_namespaces:"},{"line_number":158,"context_line":"                        cache_state \u003d \u0027hit\u0027"},{"line_number":159,"context_line":"                        if six.PY2:"},{"line_number":160,"context_line":"                            # json.loads() in memcache.get will convert json"},{"line_number":161,"context_line":"                            # \u0027string\u0027 to \u0027unicode\u0027 with python2, here we cast"},{"line_number":162,"context_line":"                            # \u0027unicode\u0027 back to \u0027str\u0027"},{"line_number":163,"context_line":"                            cached_namespaces \u003d ["},{"line_number":164,"context_line":"                                [lower.encode(\u0027utf-8\u0027), name.encode(\u0027utf-8\u0027)]"},{"line_number":165,"context_line":"                                for lower, name in cached_namespaces]"},{"line_number":166,"context_line":"                        ns_bound_list \u003d NamespaceBoundList(cached_namespaces)"},{"line_number":167,"context_line":"                        resp_body \u003d self._make_namespaces_response_body("},{"line_number":168,"context_line":"                            req, ns_bound_list)"},{"line_number":169,"context_line":"                    else:"}],"source_content_type":"text/x-python","patch_set":3,"id":"b9e99fb8_2db62b34","line":166,"range":{"start_line":159,"start_character":0,"end_line":166,"end_character":0},"in_reply_to":"fb8def78_6701b845","updated":"2023-03-17 14:53:25.000000000","message":"changed my mind about this - there are other places that call the constructor","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":225,"context_line":"        return ns_bound_list"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def _get_shard_ranges_from_backend(self, req):"},{"line_number":228,"context_line":"        # Make a backend request for shard ranges. The response is cached and"},{"line_number":229,"context_line":"        # then returned as a list of dicts."},{"line_number":230,"context_line":"        # Note: We instruct the backend server to ignore name constraints in"},{"line_number":231,"context_line":"        # request params if returning shard ranges so that the response can"},{"line_number":232,"context_line":"        # potentially be cached. Only do this if the container state is"}],"source_content_type":"text/x-python","patch_set":3,"id":"b486ec04_bbc8ca2d","line":229,"range":{"start_line":228,"start_character":51,"end_line":229,"end_character":43},"updated":"2023-03-16 17:55:47.000000000","message":"This should say something like:\n\n  \"\"\"\n  Make a backend request for shard ranges and return a response.\n  The response body will be a list of dicts each of which describes\n  a Namespace (i.e. includes the keys ``lower``, ``upper`` and ``name``).\n  :param req: an instance of swob.Request\n  :return: an instance of swob.Response\n  \"\"\"","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"aaa02fd434f6040bc8822a731b95691dd4b2b612","unresolved":false,"context_lines":[{"line_number":225,"context_line":"        return ns_bound_list"},{"line_number":226,"context_line":""},{"line_number":227,"context_line":"    def _get_shard_ranges_from_backend(self, req):"},{"line_number":228,"context_line":"        # Make a backend request for shard ranges. The response is cached and"},{"line_number":229,"context_line":"        # then returned as a list of dicts."},{"line_number":230,"context_line":"        # Note: We instruct the backend server to ignore name constraints in"},{"line_number":231,"context_line":"        # request params if returning shard ranges so that the response can"},{"line_number":232,"context_line":"        # potentially be cached. Only do this if the container state is"}],"source_content_type":"text/x-python","patch_set":3,"id":"9aebc21c_95ba59ad","line":229,"range":{"start_line":228,"start_character":51,"end_line":229,"end_character":43},"in_reply_to":"b486ec04_bbc8ca2d","updated":"2023-03-17 14:53:25.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"},{"line_number":259,"context_line":"        return resp"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def _record_shard_listing_cache_metrics("}],"source_content_type":"text/x-python","patch_set":3,"id":"d210214e_a1c5825e","line":258,"range":{"start_line":256,"start_character":12,"end_line":258,"end_character":39},"updated":"2023-03-16 17:55:47.000000000","message":"is this strictly necessary? there is a case where the response body is still a list of full shard range dicts (rather than namespace dicts), so should we just make the response body uniform in all cases?\n\nor flip the other way and always transform to a bound list?","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3e03111afc7a9512185164ce6f96046126e3c194","unresolved":false,"context_lines":[{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"},{"line_number":259,"context_line":"        return resp"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def _record_shard_listing_cache_metrics("}],"source_content_type":"text/x-python","patch_set":3,"id":"c70d37a0_1ed27c1b","line":258,"range":{"start_line":256,"start_character":12,"end_line":258,"end_character":39},"in_reply_to":"6a930a55_6fbd3427","updated":"2023-03-20 10:44:30.000000000","message":"Ack","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"4a02c1c12c33e3a50f2895d51b9a4f26b37dbc0d","unresolved":true,"context_lines":[{"line_number":253,"context_line":"                sharding_state \u003d\u003d \u0027sharded\u0027 and"},{"line_number":254,"context_line":"                complete_listing):"},{"line_number":255,"context_line":"            ns_bound_list \u003d self._store_shard_ranges_in_cache(req, resp)"},{"line_number":256,"context_line":"            if ns_bound_list:"},{"line_number":257,"context_line":"                resp.body \u003d self._make_namespaces_response_body("},{"line_number":258,"context_line":"                    req, ns_bound_list)"},{"line_number":259,"context_line":"        return resp"},{"line_number":260,"context_line":""},{"line_number":261,"context_line":"    def _record_shard_listing_cache_metrics("}],"source_content_type":"text/x-python","patch_set":3,"id":"6a930a55_6fbd3427","line":258,"range":{"start_line":256,"start_character":12,"end_line":258,"end_character":39},"in_reply_to":"d210214e_a1c5825e","updated":"2023-03-19 00:00:37.000000000","message":"Actually, current patch already does this, makes the response body uniform in all cases by returning \"namespace dicts\" for both \"_get_shard_ranges_from_cache\" and \"_get_shard_ranges_from_backend\".","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":445,"context_line":"            req.headers[policy_key] \u003d resp.headers[policy_key]"},{"line_number":446,"context_line":"        shard_listing_history.append((self.account_name, self.container_name))"},{"line_number":447,"context_line":"        # Note: when the response body has been synthesised from cached data,"},{"line_number":448,"context_line":"        # the ShardRange objects only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 set."},{"line_number":449,"context_line":"        # TODO: ideally we\u0027d like to construct Namespace objects here but we"},{"line_number":450,"context_line":"        #   don\u0027t want Namespace to have account and container properties that"},{"line_number":451,"context_line":"        #   ShardRange has."}],"source_content_type":"text/x-python","patch_set":3,"id":"d4f3bed0_63302ca9","line":448,"updated":"2023-03-16 17:55:47.000000000","message":"nit: could you please amend this comment\n\n  Note: when the response body has been synthesised from cached data\n  only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 are available in each item of the \n  list. We therefore cannot use ShardRange.from_dict(), and the ShardRange\n  instances will only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 attributes set.","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3f9779acf31fc2c6866d7370b909b3fe074c5069","unresolved":false,"context_lines":[{"line_number":445,"context_line":"            req.headers[policy_key] \u003d resp.headers[policy_key]"},{"line_number":446,"context_line":"        shard_listing_history.append((self.account_name, self.container_name))"},{"line_number":447,"context_line":"        # Note: when the response body has been synthesised from cached data,"},{"line_number":448,"context_line":"        # the ShardRange objects only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 set."},{"line_number":449,"context_line":"        # TODO: ideally we\u0027d like to construct Namespace objects here but we"},{"line_number":450,"context_line":"        #   don\u0027t want Namespace to have account and container properties that"},{"line_number":451,"context_line":"        #   ShardRange has."}],"source_content_type":"text/x-python","patch_set":3,"id":"ace45ce4_139b52f2","line":448,"in_reply_to":"d4f3bed0_63302ca9","updated":"2023-03-17 12:36:21.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":446,"context_line":"        shard_listing_history.append((self.account_name, self.container_name))"},{"line_number":447,"context_line":"        # Note: when the response body has been synthesised from cached data,"},{"line_number":448,"context_line":"        # the ShardRange objects only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 set."},{"line_number":449,"context_line":"        # TODO: ideally we\u0027d like to construct Namespace objects here but we"},{"line_number":450,"context_line":"        #   don\u0027t want Namespace to have account and container properties that"},{"line_number":451,"context_line":"        #   ShardRange has."},{"line_number":452,"context_line":"        shard_ranges \u003d [ShardRange(**data) for data in json.loads(resp.body)]"}],"source_content_type":"text/x-python","patch_set":3,"id":"cd7c0f96_856a5afb","line":449,"range":{"start_line":449,"start_character":10,"end_line":449,"end_character":15},"updated":"2023-03-16 17:55:47.000000000","message":"perhaps delete the TODO but keep rest of the comment?","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3f9779acf31fc2c6866d7370b909b3fe074c5069","unresolved":false,"context_lines":[{"line_number":446,"context_line":"        shard_listing_history.append((self.account_name, self.container_name))"},{"line_number":447,"context_line":"        # Note: when the response body has been synthesised from cached data,"},{"line_number":448,"context_line":"        # the ShardRange objects only have \u0027name\u0027, \u0027lower\u0027 and \u0027upper\u0027 set."},{"line_number":449,"context_line":"        # TODO: ideally we\u0027d like to construct Namespace objects here but we"},{"line_number":450,"context_line":"        #   don\u0027t want Namespace to have account and container properties that"},{"line_number":451,"context_line":"        #   ShardRange has."},{"line_number":452,"context_line":"        shard_ranges \u003d [ShardRange(**data) for data in json.loads(resp.body)]"}],"source_content_type":"text/x-python","patch_set":3,"id":"8abaa53c_aefe5116","line":449,"range":{"start_line":449,"start_character":10,"end_line":449,"end_character":15},"in_reply_to":"cd7c0f96_856a5afb","updated":"2023-03-17 12:36:21.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"24f71b483ae739d34643879e402956f105a83e23","unresolved":true,"context_lines":[{"line_number":4262,"context_line":"            if tempdir:"},{"line_number":4263,"context_line":"                shutil.rmtree(tempdir)"},{"line_number":4264,"context_line":""},{"line_number":4265,"context_line":"    def test_find_shard_range(self):"},{"line_number":4266,"context_line":"        ts \u003d utils.Timestamp.now().internal"},{"line_number":4267,"context_line":"        start \u003d utils.ShardRange(\u0027a/-a\u0027, ts, \u0027\u0027, \u0027a\u0027)"},{"line_number":4268,"context_line":"        atof \u003d utils.ShardRange(\u0027a/a-f\u0027, ts, \u0027a\u0027, \u0027f\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"5704eae9_75172127","line":4265,"range":{"start_line":4265,"start_character":8,"end_line":4265,"end_character":30},"updated":"2023-03-16 17:55:47.000000000","message":"please change test name to match i.e. test_find_namespace","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3f9779acf31fc2c6866d7370b909b3fe074c5069","unresolved":false,"context_lines":[{"line_number":4262,"context_line":"            if tempdir:"},{"line_number":4263,"context_line":"                shutil.rmtree(tempdir)"},{"line_number":4264,"context_line":""},{"line_number":4265,"context_line":"    def test_find_shard_range(self):"},{"line_number":4266,"context_line":"        ts \u003d utils.Timestamp.now().internal"},{"line_number":4267,"context_line":"        start \u003d utils.ShardRange(\u0027a/-a\u0027, ts, \u0027\u0027, \u0027a\u0027)"},{"line_number":4268,"context_line":"        atof \u003d utils.ShardRange(\u0027a/a-f\u0027, ts, \u0027a\u0027, \u0027f\u0027)"}],"source_content_type":"text/x-python","patch_set":3,"id":"9b4a6537_21d07aee","line":4265,"range":{"start_line":4265,"start_character":8,"end_line":4265,"end_character":30},"in_reply_to":"5704eae9_75172127","updated":"2023-03-17 12:36:21.000000000","message":"Done","commit_id":"483de79aeffd91ea13919eeb1a0b1c49bc9ce31b"}]}
