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

immutables._map.MapMutation is not iterable / does not implement items() #55

Open
atzannes opened this issue Jan 26, 2021 · 3 comments
Open

Comments

@atzannes
Copy link

I am wondering if this is by design or because it hasn't been useful up till now.

My use-case is implementing a middleware type of cache. The cache subscribes to some external data that gets updated and tracks it, and it allows clients to get an immutable view of the cache. The cache can be a nested immutables.Map dictionary. What works is to call mutate and finish for each new piece of data that comes in (N times each if the updated key is at depth N), but this can be too slow when the cache receives a large batch of updates. Using a profiler, I see my code spending ~35% of the time processing the incoming data to be added to the cache and ~65% of the time in the mutate/finish calls.

What I would like to implement is a lazy-finish protocol that calls mutate on updates as needed but not finish. Instead, we traverse the cache and make any needed finish calls when the client requests a view into the cache. What is preventing me from realizing this implementation (I think) is that the immutables._map.MapMutation objects that are returned by the un-finished mutate calls, are not iterable and they don't implement items(), but I need to finish the inner MapMutation objects before I finish the outer ones.

As a nasty hack, I can finish() an outer MapMutation to get its keys and use them to find and recurse into any inner MapMutation values to finish those, before I call finish() a second time on the outer MapMutation to really finish it this time.

@1st1
Copy link
Member

1st1 commented Feb 10, 2021

I am wondering if this is by design or because it hasn't been useful up till now.

It's by design to keep everything simple. Mutation objects have the same internal structure as immutable objects, and enjoy the same iterator implementation. And that implementation assumes that the underlying tree is static and cannot change while iterating. That said, it's certainly possible to add the necessary code to error out the iteration if there was a mutation during it -- feel free to open a PR for that.

@atzannes
Copy link
Author

I'll try to take a cut at this next month when I have a bit more time. Just to make sure I understood correctly, you are referring to the RuntimeError: dictionary changed size during iteration error, right? (As opposed to mutations that only modify values.)

@atzannes
Copy link
Author

Great, thank you for the feedback. I will certainly keep this as a future weekend project. Unfortunately, the need is not pressing to justify spending work time on it, and life just got busy, so it won't be soon, but I am not dropping the ball (just yet)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants