)]}'
{"/COMMIT_MSG":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5ce1ee01620163a62b6d5c1f77f599167f889392","unresolved":true,"context_lines":[{"line_number":4,"context_line":"Commit:     Christian Schwede \u003ccschwede@mailbox.org\u003e"},{"line_number":5,"context_line":"CommitDate: 2026-07-24 18:02:18 +0200"},{"line_number":6,"context_line":""},{"line_number":7,"context_line":"obj: order replication/reconstructor jobs by ring-history severity"},{"line_number":8,"context_line":""},{"line_number":9,"context_line":"After rebalancing moved parts are below full durability until the"},{"line_number":10,"context_line":"replicator or reconstructor reach them. The shuffle in collect_jobs"}],"source_content_type":"text/x-gerrit-commit-message","patch_set":2,"id":"92364ee0_3537530c","line":7,"updated":"2026-08-31 22:25:07.000000000","message":"I think \"severity\" might be a better anchoring interface name that a generic \"tiers\"","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"}],"/PATCHSET_LEVEL":[{"author":{"_account_id":38496,"name":"Andressa Cabistani","display_name":"Andressa","email":"acabistani@gmail.com","username":"andressadotpy","status":"I\u0027m a Software Engineer at Red Hat and I love Open Source and connect with people! Feel free to DM through IRC, I\u0027ll be delighted to chat"},"change_message_id":"d0054934ef4610f5156fb31d2e812e193b2b91e1","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"c65cc2ad_564c5432","updated":"2026-07-28 14:54:11.000000000","message":"I asked Claude to implement a few end2end tests so I could check all patches working together and after 27/27 checks passed I feel pretty comfortable in saying that this looks good to me. The code duplication mentioned in another review is real but small so it\u0027s not a blocker.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5ce1ee01620163a62b6d5c1f77f599167f889392","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":2,"id":"615975c9_44615dc1","updated":"2026-08-31 22:25:07.000000000","message":"i haven\u0027t looked at this implementation onto itself - i\u0027ve only come here through evaluation of the ring interface added some patches ago that\u0027s only just consumed here","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"}],"swift/obj/reconstructor.py":[{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5ce1ee01620163a62b6d5c1f77f599167f889392","unresolved":true,"context_lines":[{"line_number":1317,"context_line":"        policy2devices \u003d self.get_policy2devices()"},{"line_number":1318,"context_line":"        all_parts \u003d []"},{"line_number":1319,"context_line":""},{"line_number":1320,"context_line":"        for policy, local_devices in policy2devices.items():"},{"line_number":1321,"context_line":"            # Skip replication if next_part_power is set. In this case"},{"line_number":1322,"context_line":"            # every object is hard-linked twice, but the replicator"},{"line_number":1323,"context_line":"            # can\u0027t detect them and would create a second copy of the"}],"source_content_type":"text/x-python","patch_set":2,"id":"1f81eecc_d457a36b","line":1320,"updated":"2026-08-31 22:25:07.000000000","message":"wow, i\u0027m realizing this all_parts list is every part from every device - it could easily be over 1M items, so naive re-sorting is non-trivial.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"ba9a2bc07524aab11056a617ad95b15cc221b0a4","unresolved":false,"context_lines":[{"line_number":1401,"context_line":"                    all_parts.append(part_info)"},{"line_number":1402,"context_line":"        # Most-churned partitions first; random tiebreak keeps the load"},{"line_number":1403,"context_line":"        # spread the old flat shuffle gave us."},{"line_number":1404,"context_line":"        all_parts.sort(key\u003dlambda part_info: ("},{"line_number":1405,"context_line":"            -self._history_severity(part_info), random.random()))"},{"line_number":1406,"context_line":"        return all_parts"},{"line_number":1407,"context_line":""},{"line_number":1408,"context_line":"    def _history_severity(self, part_info):"}],"source_content_type":"text/x-python","patch_set":2,"id":"8406bec9_5f50e199","line":1405,"range":{"start_line":1404,"start_character":8,"end_line":1405,"end_character":65},"updated":"2026-07-27 18:52:19.000000000","message":"Great approach actually; technically if we just kept the old shuffle and sorted afterward we should get the same result I believe, but this is clean :)","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5ce1ee01620163a62b6d5c1f77f599167f889392","unresolved":true,"context_lines":[{"line_number":1401,"context_line":"                    all_parts.append(part_info)"},{"line_number":1402,"context_line":"        # Most-churned partitions first; random tiebreak keeps the load"},{"line_number":1403,"context_line":"        # spread the old flat shuffle gave us."},{"line_number":1404,"context_line":"        all_parts.sort(key\u003dlambda part_info: ("},{"line_number":1405,"context_line":"            -self._history_severity(part_info), random.random()))"},{"line_number":1406,"context_line":"        return all_parts"},{"line_number":1407,"context_line":""},{"line_number":1408,"context_line":"    def _history_severity(self, part_info):"}],"source_content_type":"text/x-python","patch_set":2,"id":"0f5b6ea2_490babb8","line":1405,"range":{"start_line":1404,"start_character":8,"end_line":1405,"end_character":65},"in_reply_to":"8406bec9_5f50e199","updated":"2026-08-31 22:25:07.000000000","message":"I think `severity(part) \u003d count of replica rows with live history` is actually doing something different from our primary goal.\n\nThe BIG pain point in cycle-based reconstructor is rebalance - what we want is for a handoff partitions to revert to the new primary before their primary counter-parts rebuild it.  This is currently achived by turning ALL reconstructors into \"priority-rebalance-mode\" (aka handoffs_only)\n\nIf this change were using ring history to solve this problem it wouldn\u0027t be making \"most moved parts the biggest priority\" - but rather making moved revert jobs a higher priority while making moved sync jobs a LOWER priority.\n\nThe big pain with `handoffs_only` is how it disables sync jobs for parts who have had a replica that has failed - I think history should allow us to develop a new `handoffs_and_rebuilds_only` mode that explicitly filter recently moved sync jobs\n\nI don\u0027t think we can make any new history based prioritization \"on by default\" - it\u0027s all basically going to be experimental and operator managed/monitored until we gain enough experience to make the whole job prioritization system away from simple cycle-based scheduling or else we\u0027ll run into contentous high-priority work getting blocked behind a long queue of low value jobs.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"ba9a2bc07524aab11056a617ad95b15cc221b0a4","unresolved":true,"context_lines":[{"line_number":1405,"context_line":"            -self._history_severity(part_info), random.random()))"},{"line_number":1406,"context_line":"        return all_parts"},{"line_number":1407,"context_line":""},{"line_number":1408,"context_line":"    def _history_severity(self, part_info):"},{"line_number":1409,"context_line":"        \"\"\""},{"line_number":1410,"context_line":"        Count this partition\u0027s replica rows that diverge from the ring"},{"line_number":1411,"context_line":"        history; 0 for rings without history."}],"source_content_type":"text/x-python","patch_set":2,"id":"ebb5a5f7_0a535cfa","line":1408,"range":{"start_line":1408,"start_character":0,"end_line":1408,"end_character":43},"updated":"2026-07-27 18:52:19.000000000","message":"At some point will there be a difference in tier-based prioritization for the reconstructor vs replicator (like, `urgent` is treated differently by the reconstructor vs replicatr) ? if not then I think we could deduplicate a bit and make this a shared func in the Ring class.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"9b643cd8371cdaf5353962d926e8f7b8feb5eccf","unresolved":false,"context_lines":[{"line_number":1405,"context_line":"            -self._history_severity(part_info), random.random()))"},{"line_number":1406,"context_line":"        return all_parts"},{"line_number":1407,"context_line":""},{"line_number":1408,"context_line":"    def _history_severity(self, part_info):"},{"line_number":1409,"context_line":"        \"\"\""},{"line_number":1410,"context_line":"        Count this partition\u0027s replica rows that diverge from the ring"},{"line_number":1411,"context_line":"        history; 0 for rings without history."}],"source_content_type":"text/x-python","patch_set":2,"id":"85b1f276_43b7e1f3","line":1408,"range":{"start_line":1408,"start_character":0,"end_line":1408,"end_character":43},"in_reply_to":"ebb5a5f7_0a535cfa","updated":"2026-09-16 09:57:30.000000000","message":"Done","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":1179,"name":"Clay Gerrard","email":"clay.gerrard@gmail.com","username":"clay-gerrard"},"change_message_id":"5ce1ee01620163a62b6d5c1f77f599167f889392","unresolved":true,"context_lines":[{"line_number":1411,"context_line":"        history; 0 for rings without history."},{"line_number":1412,"context_line":"        \"\"\""},{"line_number":1413,"context_line":"        get_part_tiers \u003d getattr(part_info[\u0027policy\u0027].object_ring,"},{"line_number":1414,"context_line":"                                 \u0027get_part_tiers\u0027, None)"},{"line_number":1415,"context_line":"        if get_part_tiers is None:"},{"line_number":1416,"context_line":"            return 0"},{"line_number":1417,"context_line":"        return sum(1 for _, tier in get_part_tiers(part_info[\u0027partition\u0027])"}],"source_content_type":"text/x-python","patch_set":2,"id":"9062b760_491e19b3","line":1414,"updated":"2026-08-31 22:25:07.000000000","message":"`getattr` - I don\u0027t understand - the *method* doesn\u0027t exist if you have old rings?\n\nN.B. how \"tier\" is not *severity* classifer - and has nothing to do with builder tiers.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"9b643cd8371cdaf5353962d926e8f7b8feb5eccf","unresolved":true,"context_lines":[{"line_number":1407,"context_line":"                    }"},{"line_number":1408,"context_line":"                    all_parts.append(part_info)"},{"line_number":1409,"context_line":"        if self.use_ring_history:"},{"line_number":1410,"context_line":"            all_parts.sort(key\u003dlambda part_info: ("},{"line_number":1411,"context_line":"                -self._history_rank(part_info), random.random()))"},{"line_number":1412,"context_line":"        else:"},{"line_number":1413,"context_line":"            random.shuffle(all_parts)"},{"line_number":1414,"context_line":"        return all_parts"}],"source_content_type":"text/x-python","patch_set":5,"id":"eeee5e9b_0b9359f2","line":1411,"range":{"start_line":1410,"start_character":0,"end_line":1411,"end_character":65},"updated":"2026-09-16 09:57:30.000000000","message":"reviewbot + my agent mention some concerns about how far ring_history scales given there can be a bunch of partition-device entries. This is nice and n log n, though there\u0027s an o(n) alternative... bit long but I think it\u0027d be reasonable to split this into a helper func shared by the reconstructor + replicator\n\n```\nurgent, neutral, deferred \u003d [], [], []\n\nfor job in jobs:\n    rank \u003d self._history_rank(job)\n    if rank \u003e 0:\n        urgent.append(job)\n    elif rank \u003c 0:\n        deferred.append(job)\n    else:\n        neutral.append(job)\n\nfor ranked_jobs in (urgent, neutral, deferred):\n    random.shuffle(ranked_jobs)\n\njobs \u003d urgent + neutral + deferred\n```\n\ni think at one point in standup you mentioned benchmarks looking good but i 4got whether that was about ring history or feature/threaded","commit_id":"9e4c1532308391c169b2c8e904bde779c3862fe4"}],"swift/obj/replicator.py":[{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"ba9a2bc07524aab11056a617ad95b15cc221b0a4","unresolved":true,"context_lines":[{"line_number":968,"context_line":"        self.job_count \u003d len(jobs)"},{"line_number":969,"context_line":"        return jobs"},{"line_number":970,"context_line":""},{"line_number":971,"context_line":"    def _history_severity(self, job):"},{"line_number":972,"context_line":"        \"\"\""},{"line_number":973,"context_line":"        Count this partition\u0027s replica rows that diverge from the ring"},{"line_number":974,"context_line":"        history; 0 for rings without history."}],"source_content_type":"text/x-python","patch_set":2,"id":"f9b958c9_31b4f3f6","line":971,"range":{"start_line":971,"start_character":0,"end_line":971,"end_character":37},"updated":"2026-07-27 18:52:19.000000000","message":"At some point will there be a difference in tier-based prioritization for the reconstructor vs replicator (like, `urgent` is treated differently by the reconstructor vs replicatr) ? if not then I think we could deduplicate a bit and make this a shared func in the Ring class.","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"},{"author":{"_account_id":38368,"name":"Christian Ohanaja","display_name":"Christian Ohanaja","email":"cohanaja@nvidia.com","username":"cohanaja"},"change_message_id":"9b643cd8371cdaf5353962d926e8f7b8feb5eccf","unresolved":false,"context_lines":[{"line_number":968,"context_line":"        self.job_count \u003d len(jobs)"},{"line_number":969,"context_line":"        return jobs"},{"line_number":970,"context_line":""},{"line_number":971,"context_line":"    def _history_severity(self, job):"},{"line_number":972,"context_line":"        \"\"\""},{"line_number":973,"context_line":"        Count this partition\u0027s replica rows that diverge from the ring"},{"line_number":974,"context_line":"        history; 0 for rings without history."}],"source_content_type":"text/x-python","patch_set":2,"id":"1fc3aab2_4083e62f","line":971,"range":{"start_line":971,"start_character":0,"end_line":971,"end_character":37},"in_reply_to":"f9b958c9_31b4f3f6","updated":"2026-09-16 09:57:30.000000000","message":"Done","commit_id":"26fd0834b6c9c26695acaf8698a3229264195485"}]}
