Skip to content

Commit 3ec8f5e

Browse files
tvaron3Copilot
andcommitted
perf(cosmos): add PKRange namedtuple for compact partition key range storage
Convert raw service response dicts to PKRange namedtuples in both full refresh (_build_routing_map_from_ranges) and incremental update (process_fetched_ranges) paths. PKRange retains only 4 fields (id, minInclusive, maxExclusive, parents) and supports dict-style access for backward compatibility. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8b03fa2 commit 3ec8f5e

4 files changed

Lines changed: 63 additions & 4 deletions

File tree

sdk/cosmos/azure-cosmos/azure/cosmos/_routing/_routing_map_provider_common.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,11 @@ def process_fetched_ranges(
209209
next_unresolved.append(r)
210210
continue
211211

212-
range_tuples.append((r, range_info))
212+
range_tuples.append((PKRange(
213+
id=r[PartitionKeyRange.Id],
214+
minInclusive=r[PartitionKeyRange.MinInclusive],
215+
maxExclusive=r[PartitionKeyRange.MaxExclusive],
216+
parents=r.get(PartitionKeyRange.Parents)), range_info))
213217
known_range_info_by_id[r[PartitionKeyRange.Id]] = range_info
214218
progress_made = True
215219

sdk/cosmos/azure-cosmos/azure/cosmos/_routing/collection_routing_map.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
from typing import Optional, Union
2828

2929
from azure.cosmos._routing import routing_range
30-
from azure.cosmos._routing.routing_range import PartitionKeyRange
30+
from azure.cosmos._routing.routing_range import PartitionKeyRange, PKRange
3131

3232
# pylint: disable=line-too-long
3333
class CollectionRoutingMap(object):
@@ -288,7 +288,13 @@ def _build_routing_map_from_ranges(
288288
if PartitionKeyRange.Parents in r and r[PartitionKeyRange.Parents]:
289289
gone_range_ids.update(r[PartitionKeyRange.Parents])
290290

291-
filtered_ranges = [r for r in ranges if r[PartitionKeyRange.Id] not in gone_range_ids]
291+
filtered_ranges = [
292+
PKRange(id=r[PartitionKeyRange.Id],
293+
minInclusive=r[PartitionKeyRange.MinInclusive],
294+
maxExclusive=r[PartitionKeyRange.MaxExclusive],
295+
parents=r.get(PartitionKeyRange.Parents))
296+
for r in ranges if r[PartitionKeyRange.Id] not in gone_range_ids
297+
]
292298
range_tuples = [(r, True) for r in filtered_ranges]
293299

294300
routing_map = CollectionRoutingMap.CompleteRoutingMap(

sdk/cosmos/azure-cosmos/azure/cosmos/_routing/routing_range.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,31 @@
2727
import json
2828

2929

30+
from collections import namedtuple
31+
32+
_PKRangeBase = namedtuple('PKRange', ['id', 'minInclusive', 'maxExclusive', 'parents'])
33+
34+
35+
class PKRange(_PKRangeBase):
36+
"""Compact partition key range with dict-compatible access."""
37+
__slots__ = ()
38+
39+
def __getitem__(self, key):
40+
try:
41+
return getattr(self, key)
42+
except AttributeError:
43+
raise KeyError(key)
44+
45+
def get(self, key, default=None):
46+
return getattr(self, key, default)
47+
48+
def __contains__(self, key):
49+
return key in self._fields
50+
51+
def items(self):
52+
return zip(self._fields, self)
53+
54+
3055
class PartitionKeyRange(object):
3156
"""Partition Key Range Constants"""
3257

sdk/cosmos/azure-cosmos/tests/routing/test_shared_pk_range_cache.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
import pytest
88

9-
from azure.cosmos._routing.routing_range import Range
9+
from azure.cosmos._routing.routing_range import Range, PKRange
1010
from azure.cosmos._routing.collection_routing_map import CollectionRoutingMap
1111
from azure.cosmos._routing.routing_map_provider import (
1212
PartitionKeyRangeCache,
@@ -74,6 +74,30 @@ def test_clear_cache_does_not_affect_other_endpoints(self):
7474
self.assertNotIn("coll1", cache1._collection_routing_map_by_item)
7575
self.assertIn("coll2", cache2._collection_routing_map_by_item)
7676

77+
78+
def test_pkrange_dict_access(self):
79+
"""PKRange supports dict-style [key] access."""
80+
pkr = PKRange(id="1", minInclusive="00", maxExclusive="FF", parents=["0"])
81+
self.assertEqual(pkr["id"], "1")
82+
self.assertEqual(pkr["minInclusive"], "00")
83+
self.assertEqual(pkr.get("parents"), ["0"])
84+
self.assertEqual(pkr.get("_rid", "default"), "default")
85+
self.assertIn("id", pkr)
86+
self.assertNotIn("_rid", pkr)
87+
88+
def test_pkrange_in_collection_routing_map(self):
89+
"""CollectionRoutingMap works with PKRange namedtuples."""
90+
pk_ranges = [
91+
PKRange(id="0", minInclusive="", maxExclusive="80", parents=None),
92+
PKRange(id="1", minInclusive="80", maxExclusive="FF", parents=None),
93+
]
94+
crm = CollectionRoutingMap.CompleteRoutingMap(
95+
[(r, True) for r in pk_ranges], "test"
96+
)
97+
self.assertIsNotNone(crm)
98+
overlapping = crm.get_overlapping_ranges(Range("", "FF", True, False))
99+
self.assertEqual(len(overlapping), 2)
100+
77101
def test_range_has_slots(self):
78102
r = Range("00", "FF", True, False)
79103
self.assertFalse(hasattr(r, "__dict__"))

0 commit comments

Comments
 (0)