diff --git a/packages/abstractions/kiota_abstractions/store/in_memory_backing_store.py b/packages/abstractions/kiota_abstractions/store/in_memory_backing_store.py index fef8c809..34ece180 100644 --- a/packages/abstractions/kiota_abstractions/store/in_memory_backing_store.py +++ b/packages/abstractions/kiota_abstractions/store/in_memory_backing_store.py @@ -27,6 +27,7 @@ class InMemoryBackingStore(BackingStore[T], Generic[T]): def __init__(self) -> None: + self.__id = str(uuid4()) self.__subscriptions: dict[str, Callable[[str, Any, Any], None]] = {} self.__store: dict[str, tuple[bool, T, Optional[_Collection]]] = {} self.__initialization_completed: bool = False @@ -40,11 +41,13 @@ def is_initialization_completed(self) -> bool: @is_initialization_completed.setter def is_initialization_completed(self, value: bool) -> None: self.__initialization_completed = value - for key, (_, val, collection) in self.__store.items(): + for key in list(self.__store): + _, val, collection = self.__store[key] if isinstance(val, BackedModel): # forward the initialization status to nested BackedModel instances val.backing_store.is_initialization_completed = value self._ensure_collection_size_is_consistent(key, val, collection) + _, val, collection = self.__store[key] self.__store[key] = (not value, val, collection) @property @@ -110,7 +113,8 @@ def set(self, key: str, value: T) -> None: if isinstance(item, BackedModel) and item.backing_store: item.backing_store.is_initialization_completed = True item.backing_store.subscribe( - lambda prop_key, old_val, new_val: self.set(key, value) + lambda prop_key, old_val, new_val: self.set(key, value), + f"{self.__id}:{key}" ) self.__store[key] = value_to_add diff --git a/packages/abstractions/tests/store/test_in_memory_backing_store.py b/packages/abstractions/tests/store/test_in_memory_backing_store.py index dc08615a..60512002 100644 --- a/packages/abstractions/tests/store/test_in_memory_backing_store.py +++ b/packages/abstractions/tests/store/test_in_memory_backing_store.py @@ -228,3 +228,34 @@ def test_subscribers_get_previous_and_new_values(): backing_store.set("name", "Samwel") backing_store.set("name", "Bill") assert changes == [("name", None, "Samwel"), ("name", "Samwel", "Bill")] + +def test_list_items_notify_the_store_once_per_change(): + backing_store = InMemoryBackingStore() + colleague = MockEntity(id="2f8c9b8c-8ea0-46b2-9c6d-660c9b7bf6af") + backing_store.set("colleagues", [colleague]) + backing_store.set("colleagues", [colleague]) + changes = [] + backing_store.subscribe(lambda key, old, new: changes.append(key)) + for new_id in ("first", "second", "third"): + colleague.id = new_id + assert changes == ["colleagues"] * 3 + +def test_list_item_shared_by_two_stores_notifies_both(): + first, second = InMemoryBackingStore(), InMemoryBackingStore() + colleague = MockEntity(id="2f8c9b8c-8ea0-46b2-9c6d-660c9b7bf6af") + first.set("colleagues", [colleague]) + second.set("colleagues", [colleague]) + changes = [] + first.subscribe(lambda key, old, new: changes.append("first")) + second.subscribe(lambda key, old, new: changes.append("second")) + colleague.id = "2fe22fe5-1132-42cf-90f9-1dc17e325a74" + assert changes == ["first", "second"] + +def test_completing_initialization_clears_a_resized_list(): + backing_store = InMemoryBackingStore() + numbers = [1] + backing_store.set("numbers", numbers) + numbers.append(2) + backing_store.is_initialization_completed = True + backing_store.return_only_changed_values = True + assert not backing_store.enumerate_()