)]}'
{"/PATCHSET_LEVEL":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"fd45b9dcec976becf36b8ba9ba64e2f73c8a2ab5","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":1,"id":"8ef8f244_a6e7cfea","updated":"2022-11-03 21:35:36.000000000","message":"I think this could converge with the approach to minimise the serialised form in https://review.opendev.org/c/openstack/swift/+/852203","commit_id":"2d0e9a3fe7455458cd7f70c7295e15be7cd3c4c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"055265e9522a9ee7179fdc597311c3585807688b","unresolved":false,"context_lines":[],"source_content_type":"","patch_set":5,"id":"98163d3f_0ef40135","updated":"2022-11-28 03:38:53.000000000","message":"OK starting to grok what is happening.\n\nAnd so shardranges are a type of Namespace, because they map namespaces just like we will in memcache. I like it.\n\nStill attempting to load what the plan is in my head. Is there a design doc? Don\u0027t mind either way, but just means I\u0027ll ask questions inline ;) ","commit_id":"ad9549b5ff824d792783e60df14214a0dc36d56d"}],"swift/common/utils.py":[{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"2da2097e024ae3348605bf91df6ee8d93e6e0e9b","unresolved":true,"context_lines":[{"line_number":5264,"context_line":"            raise ValueError(\u0027invalid name: %s\u0027 % name)"},{"line_number":5265,"context_line":""},{"line_number":5266,"context_line":""},{"line_number":5267,"context_line":"class Namespace(object):"},{"line_number":5268,"context_line":"    @functools.total_ordering"},{"line_number":5269,"context_line":"    class MaxBound(ShardRangeOuterBound):"},{"line_number":5270,"context_line":"        # singleton for maximum bound"}],"source_content_type":"text/x-python","patch_set":1,"id":"574dbd16_ad0190ee","line":5267,"updated":"2022-11-24 18:19:14.000000000","message":"This class is extracted from ShardRange.\n\nIIRC there\u0027s places where we abuse ShardRange when we only need something as basic as a Namespace, so this could prove a useful extraction in itself.","commit_id":"2d0e9a3fe7455458cd7f70c7295e15be7cd3c4c4"},{"author":{"_account_id":34930,"name":"Jianjian Huo","email":"jhuo@nvidia.com","username":"jhuo"},"change_message_id":"aea6edb55a5ab7457c2316859a6cb8175ae5e2f6","unresolved":true,"context_lines":[{"line_number":5264,"context_line":"            raise ValueError(\u0027invalid name: %s\u0027 % name)"},{"line_number":5265,"context_line":""},{"line_number":5266,"context_line":""},{"line_number":5267,"context_line":"class Namespace(object):"},{"line_number":5268,"context_line":"    @functools.total_ordering"},{"line_number":5269,"context_line":"    class MaxBound(ShardRangeOuterBound):"},{"line_number":5270,"context_line":"        # singleton for maximum bound"}],"source_content_type":"text/x-python","patch_set":1,"id":"699d58f1_adaa7f0a","line":5267,"in_reply_to":"574dbd16_ad0190ee","updated":"2023-01-19 03:31:46.000000000","message":"In this patch, when it store cache blobs, serialize() calls \"__iter__\" which contains both lower and upper. Is it still a concern which shard range namespaces may contain gap? maybe that\u0027s why you still kept upper?","commit_id":"2d0e9a3fe7455458cd7f70c7295e15be7cd3c4c4"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"6d0ac9cd540d717e48fe4d8f833fcb5647238f70","unresolved":true,"context_lines":[{"line_number":5264,"context_line":"            raise ValueError(\u0027invalid name: %s\u0027 % name)"},{"line_number":5265,"context_line":""},{"line_number":5266,"context_line":""},{"line_number":5267,"context_line":"class Namespace(object):"},{"line_number":5268,"context_line":"    @functools.total_ordering"},{"line_number":5269,"context_line":"    class MaxBound(ShardRangeOuterBound):"},{"line_number":5270,"context_line":"        # singleton for maximum bound"}],"source_content_type":"text/x-python","patch_set":1,"id":"7a8da5fa_e09cbecf","line":5267,"in_reply_to":"699d58f1_adaa7f0a","updated":"2023-01-19 11:24:42.000000000","message":"I accepted Tim\u0027s argument that if there is a gap then we have to send the update somewhere, so sending to the adjacent range is OK.\n\nThe lower, upper and name are both written out for the containing NamespaceMap range, but only the lower and name are written for each contained namespace - see the _serialize method and test_store_in_memcache in test_utils.py:\n\n        self.assertEqual({\u0027leaf\u0027: False,\n                          \u0027lower\u0027: \u0027\u0027,\n                          \u0027name\u0027: \u0027shard-updating-v2/a/c/\u0027,\n                          \u0027items\u0027: [[\u0027\u0027, \u0027shard-updating-v2/a/c/[0]\u0027],\n                                    [\u0027d\u0027, \u0027shard-updating-v2/a/c/[1]\u0027]],\n                          \u0027upper\u0027: \u0027\u0027},\n                         fake_memcache.store[\u0027shard-updating-v2/a/c/\u0027])\n        self.assertEqual({\u0027leaf\u0027: True,\n                          \u0027lower\u0027: \u0027\u0027,\n                          \u0027name\u0027: \u0027shard-updating-v2/a/c/[0]\u0027,\n                          \u0027items\u0027: [[\u0027\u0027, \u0027range-0\u0027],\n                                    [\u0027b\u0027, \u0027range-1\u0027]],\n                          \u0027upper\u0027: \u0027d\u0027},\n                         fake_memcache.store[\u0027shard-updating-v2/a/c/[0]\u0027])\n        self.assertEqual({\u0027leaf\u0027: True,\n                          \u0027lower\u0027: \u0027d\u0027,\n                          \u0027name\u0027: \u0027shard-updating-v2/a/c/[1]\u0027,\n                          \u0027items\u0027: [[\u0027d\u0027, \u0027range-2\u0027],\n                                    [u\u0027\\N{SNOWMAN}\u0027, \u0027range-3\u0027]],\n                          \u0027upper\u0027: \u0027\u0027},\n                         fake_memcache.store[\u0027shard-updating-v2/a/c/[1]\u0027])","commit_id":"2d0e9a3fe7455458cd7f70c7295e15be7cd3c4c4"},{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"055265e9522a9ee7179fdc597311c3585807688b","unresolved":true,"context_lines":[{"line_number":5516,"context_line":"            leaves.append([lower, leaf.name])"},{"line_number":5517,"context_line":"            index +\u003d 1"},{"line_number":5518,"context_line":"        self.items \u003d leaves"},{"line_number":5519,"context_line":"        self.leaf \u003d False"},{"line_number":5520,"context_line":""},{"line_number":5521,"context_line":"    def store_in_memcache(self, timeout, max_items_per_leaf\u003d0):"},{"line_number":5522,"context_line":"        if self.memcache is None:"}],"source_content_type":"text/x-python","patch_set":5,"id":"46bb272c_4e79e9c2","line":5519,"updated":"2022-11-28 03:38:53.000000000","message":"OK, so when we say we deepen this into a tree, it remains a very flat tree, like the shard ranges? or at every leaf, can we build it up with new namespaces and then turn and then deepen that?\n\n  t0:  shards-updating-v2/a/c/ -|- [0]\n                                |- [1] \n                                |- [2]\n                             \n  t1:  shards-updating-v2/a/c/ -|- [0]\n                                |- [1] -|-[3]\n                                |       |-[4]\n                                |- [2]\n\nSo when we have thousands of potentual leaves, we are sharding them out the tree?\n\nJust attempting to load up the plan in my head.","commit_id":"ad9549b5ff824d792783e60df14214a0dc36d56d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3511cc698871a59fd8dfd37f478f04c136f82d56","unresolved":true,"context_lines":[{"line_number":5516,"context_line":"            leaves.append([lower, leaf.name])"},{"line_number":5517,"context_line":"            index +\u003d 1"},{"line_number":5518,"context_line":"        self.items \u003d leaves"},{"line_number":5519,"context_line":"        self.leaf \u003d False"},{"line_number":5520,"context_line":""},{"line_number":5521,"context_line":"    def store_in_memcache(self, timeout, max_items_per_leaf\u003d0):"},{"line_number":5522,"context_line":"        if self.memcache is None:"}],"source_content_type":"text/x-python","patch_set":5,"id":"cee2b01b_114fbe9c","line":5519,"in_reply_to":"46bb272c_4e79e9c2","updated":"2022-11-28 11:08:34.000000000","message":"Currently just one level of depth in the tree. I have resisted making deepen() recursive: more levels means more memcache calls, and I figure that one level makes a big difference to the blob sizes. For example, if we use 500 shard ranges per blob, then containers with ~5000 shard ranges (so maybe 5 billion objects) have a 10x reduction in blob size (and that\u0027s without the added benefit of more compact serialisation), and that\u0027s with just 10 items in the top level. We\u0027d need to grow to 250000 shard ranges before getting 500 items at the top level, at which point we might want to think about adding another level to the tree.\n\nSo if we did the extra work and testing to write recursion into deepen(), I\u0027m not sure we\u0027d use it (unless we wanted really small blobs).\n\nAt the same time I tried to allow for more levels in the future e.g. by naming the leaves using [n] suffix so the next layer can be names with [n][m] suffixes etc. In fact, I think the recursion could be added right now ... BUT its more work, more tests, more review.","commit_id":"ad9549b5ff824d792783e60df14214a0dc36d56d"}],"test/unit/common/test_utils.py":[{"author":{"_account_id":7233,"name":"Matthew Oliver","email":"matt@oliver.net.au","username":"mattoliverau"},"change_message_id":"055265e9522a9ee7179fdc597311c3585807688b","unresolved":true,"context_lines":[{"line_number":8326,"context_line":"        self.assertEqual(1, len(fake_memcache.calls))"},{"line_number":8327,"context_line":"        self.assertTrue(ns_map.leaf)"},{"line_number":8328,"context_line":""},{"line_number":8329,"context_line":"        # now we load only the leaf map to get \u0027a\u0027"},{"line_number":8330,"context_line":"        fake_memcache.clear_calls()"},{"line_number":8331,"context_line":"        self.assertEqual(namespaces[0], ns_map.get(\u0027a\u0027))"},{"line_number":8332,"context_line":"        self.assertFalse(fake_memcache.calls)"}],"source_content_type":"text/x-python","patch_set":5,"id":"b75a95ef_5387f542","line":8329,"range":{"start_line":8329,"start_character":10,"end_line":8329,"end_character":50},"updated":"2022-11-28 03:38:53.000000000","message":"What was loaded was the leaf, so it\u0027s only checking the items. So this seems like a copy error from the previous test.","commit_id":"ad9549b5ff824d792783e60df14214a0dc36d56d"},{"author":{"_account_id":7847,"name":"Alistair Coles","email":"alistairncoles@gmail.com","username":"acoles"},"change_message_id":"3511cc698871a59fd8dfd37f478f04c136f82d56","unresolved":false,"context_lines":[{"line_number":8326,"context_line":"        self.assertEqual(1, len(fake_memcache.calls))"},{"line_number":8327,"context_line":"        self.assertTrue(ns_map.leaf)"},{"line_number":8328,"context_line":""},{"line_number":8329,"context_line":"        # now we load only the leaf map to get \u0027a\u0027"},{"line_number":8330,"context_line":"        fake_memcache.clear_calls()"},{"line_number":8331,"context_line":"        self.assertEqual(namespaces[0], ns_map.get(\u0027a\u0027))"},{"line_number":8332,"context_line":"        self.assertFalse(fake_memcache.calls)"}],"source_content_type":"text/x-python","patch_set":5,"id":"3623dbb9_dfee5ee9","line":8329,"range":{"start_line":8329,"start_character":10,"end_line":8329,"end_character":50},"in_reply_to":"b75a95ef_5387f542","updated":"2022-11-28 11:08:34.000000000","message":"Ack - yep that\u0027s a mistake","commit_id":"ad9549b5ff824d792783e60df14214a0dc36d56d"}]}
