Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InMemoryBackingStore infinite loop #954

Open
Falven opened this issue Nov 16, 2024 · 0 comments
Open

InMemoryBackingStore infinite loop #954

Falven opened this issue Nov 16, 2024 · 0 comments
Labels
status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience

Comments

@Falven
Copy link

Falven commented Nov 16, 2024

Describe the bug

The InMemoryBackingStore class is experiencing an infinite loop when setting values. This occurs because the set method subscribes a lambda function that calls set again, which in turn triggers the subscription callback, causing set to be called repeatedly.

        if isinstance(value, list):
            # if its a collection, subscribe to the collection's item BackingStores and use
            # the events to flag the collection property is "dirty"
            for item in value:
                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)
                    )

        self.__store[key] = value_to_add
        for sub in list(self.__subscriptions):
            self.__subscriptions[sub](key, old_value, value_to_add)

Because you're invoking the subscription which is calling set which is invoking the subscription.

Expected behavior

The set method should store the value and notify subscribers without causing an infinite loop.

How to reproduce

  1. Create an instance of InMemoryBackingStore.
  2. Set a value that is a BackedModel or a list containing BackedModel instances.
  3. The set method subscribes a lambda function that calls set again.
  4. The subscription callback is triggered, causing set to be called repeatedly.

SDK Version

No response

Latest version known to work for scenario above?

No response

Known Workarounds

Awful, but until an update, unsubscribing and re-subscribing around problematic code.

subscription_ids = []

# Collect all backing stores and sub ids as to not modify while iterating
for role in app.app_roles:
    if isinstance(role, BackedModel) and role.backing_store:
        for (
            sub_id,
            callback,
        ) in role.backing_store._InMemoryBackingStore__subscriptions.items():
            if callback.__name__ == "<lambda>":
                subscription_ids.append((role.backing_store, sub_id))

# Unsubscribe lambdas...
for backing_store, sub_id in subscription_ids:
    backing_store.unsubscribe(sub_id)

# Problematic code
for role in app.app_roles:
    if role.is_enabled != enable:
        role.is_enabled = enable

# Resubscribe lambdas...
for backing_store, sub_id in subscription_ids:
    backing_store.subscribe(
        lambda prop_key, old_val, new_val: role.backing_store.set(
            prop_key, new_val
        ),
        sub_id,
    )

Debug output

Click to expand log ```
</details>


### Configuration

_No response_

### Other information

_No response_
@Falven Falven added status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience labels Nov 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience
Projects
None yet
Development

No branches or pull requests

1 participant