)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"3d64c32966fdcf6efe959a7e08eb37725715efd6","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"d9d216b7_92db5619","updated":"2026-07-28 12:46:36.000000000","message":"I think this is ok, but we could improve this further and avoid unnecessary work? Please see my inline comment.","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"62c68c62b628e80d0eb5a5aee045796d7e93739e","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"94874748_df490c9b","updated":"2026-07-27 10:01:24.000000000","message":"Looking much better.","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"67cb566650258d54b97421efb529dfc9d9ce216d","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":4,"id":"bb345a3c_df736b3b","updated":"2026-07-24 03:21:33.000000000","message":"thanks for the review!","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"}],"swift/obj/reconstructor.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"c53c3a345d3362884dfd0688dbc65dd3f9a740b4","unresolved":true,"context_lines":[{"line_number":670,"context_line":"                \u0027local etag: %s\u0027,"},{"line_number":671,"context_line":"                _full_path(node, partition, path, policy),"},{"line_number":672,"context_line":"                fi_to_rebuild, local_timestamp.internal, local_etag)"},{"line_number":673,"context_line":"            matching_bucket, node_count \u003d self._search_handoffs("},{"line_number":674,"context_line":"                node, policy, partition, fi_to_rebuild, path, headers,"},{"line_number":675,"context_line":"                ring, pile, buckets, error_responses,"},{"line_number":676,"context_line":"                primary_node_count, max_node_count, concurrency,"}],"source_content_type":"text/x-python","patch_set":3,"id":"82b5cdca_bb1c190e","line":673,"updated":"2026-06-01 07:25:57.000000000","message":"What happens if while searching handoffs we get a set of newer complete set as well as a enough on the local time. Then the localtime will win and we\u0027ll rebuild an older verion. Why because we are only checking against the local time. But in that case the local should be obsolete. Do we need to run the `_has_local_newer_mismatch`? on the buckets agein after the handoff check?\n\nI know it\u0027s probably an edgecase:\n\n  - T1: older useful bucket from primaries.\n  - T2: local fragment timestamp, only one matching peer so far.\n  - _has_local_newer_mismatch() says “OK, local is newer than useful peer bucket.”\n  - Handoffs return enough fragments at T3, where T3 \u003e T2.\n  - Now we know local T2 is obsolete.\n  - Later handoffs return enough T2 fragments.\n  - Current code accepts T2 and rebuilds it anyway.\n  \nWhy, because we only check:\n```\nbucket.is_useful(policy) and bucket.matches(local_timestamp, local_etag)\n```","commit_id":"90a57bfe0dd756c458f2c384fb25ed7d79940a4f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"67cb566650258d54b97421efb529dfc9d9ce216d","unresolved":true,"context_lines":[{"line_number":670,"context_line":"                \u0027local etag: %s\u0027,"},{"line_number":671,"context_line":"                _full_path(node, partition, path, policy),"},{"line_number":672,"context_line":"                fi_to_rebuild, local_timestamp.internal, local_etag)"},{"line_number":673,"context_line":"            matching_bucket, node_count \u003d self._search_handoffs("},{"line_number":674,"context_line":"                node, policy, partition, fi_to_rebuild, path, headers,"},{"line_number":675,"context_line":"                ring, pile, buckets, error_responses,"},{"line_number":676,"context_line":"                primary_node_count, max_node_count, concurrency,"}],"source_content_type":"text/x-python","patch_set":3,"id":"f55d816e_14b9860c","line":673,"in_reply_to":"82b5cdca_bb1c190e","updated":"2026-07-24 03:21:33.000000000","message":"good point! it\u0027s a possible edge case. I added changes that a useful, durable T3 bucket now aborts the local-T2 handoff search before T2 can be accepted.","commit_id":"90a57bfe0dd756c458f2c384fb25ed7d79940a4f"},{"author":{"_account_id":6968,"name":"Christian Schwede","email":"cschwede@nvidia.com","username":"cschwede"},"change_message_id":"3d64c32966fdcf6efe959a7e08eb37725715efd6","unresolved":true,"context_lines":[{"line_number":510,"context_line":"            and bucket.timestamp \u003e local_timestamp"},{"line_number":511,"context_line":"            and bucket.durable"},{"line_number":512,"context_line":"            and bucket.is_useful(policy)"},{"line_number":513,"context_line":"            for bucket in buckets.values())"},{"line_number":514,"context_line":""},{"line_number":515,"context_line":"    def _has_local_newer_mismatch(self, policy, buckets,"},{"line_number":516,"context_line":"                                  local_timestamp, local_etag):"}],"source_content_type":"text/x-python","patch_set":4,"id":"3d4c22c1_cb4d54ad","line":513,"updated":"2026-07-28 12:46:36.000000000","message":"If I understand this correctly, the following code would avoid unnecessary work because the reconstructor no longer wasteful iterates if there is some newer, durable version:\n\n```\n        return any (\n            bucket_ts \u003e local_timestamp and bucket.durable\n            for bucket_ts, bucket in buckets.items())\n```\n\nNote: `bucket_ts` is the dict key of `{Timestamp: Responsebucket}`.","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"62c68c62b628e80d0eb5a5aee045796d7e93739e","unresolved":true,"context_lines":[{"line_number":530,"context_line":"                or not local_bucket.useful_responses"},{"line_number":531,"context_line":"                or not local_bucket.matches(local_timestamp, local_etag)):"},{"line_number":532,"context_line":"            # require positive evidence that the local version exists on"},{"line_number":533,"context_line":"            # at least one peer before chasing handoffs"},{"line_number":534,"context_line":"            return False"},{"line_number":535,"context_line":"        if self._has_useful_newer_durable_bucket("},{"line_number":536,"context_line":"                policy, buckets, local_timestamp):"}],"source_content_type":"text/x-python","patch_set":4,"id":"40a666fb_39deced7","line":533,"updated":"2026-07-27 10:01:24.000000000","message":"My agent says tests for these 3 (each different \u0027or\u0027 path) exit paths from the this method are untested.\n\nso that would be nice I guess, but don\u0027t think it\u0027s going to be something I block on.","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"67cb566650258d54b97421efb529dfc9d9ce216d","unresolved":true,"context_lines":[{"line_number":532,"context_line":"            # require positive evidence that the local version exists on"},{"line_number":533,"context_line":"            # at least one peer before chasing handoffs"},{"line_number":534,"context_line":"            return False"},{"line_number":535,"context_line":"        if self._has_useful_newer_durable_bucket("},{"line_number":536,"context_line":"                policy, buckets, local_timestamp):"},{"line_number":537,"context_line":"            return False"},{"line_number":538,"context_line":"        found_older_useful_mismatch \u003d False"}],"source_content_type":"text/x-python","patch_set":4,"id":"f9588d97_e1793154","line":535,"updated":"2026-07-24 03:21:33.000000000","message":"also added the same policy here: durable newer buckets make local obsolete; non-durable newer buckets do not.","commit_id":"bb1f31152d92f00d4e9001235a85d5d883ce380f"}]}
