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

[CHIA-2041] Simplify action scopes and add support for nesting #19013

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Quexington
Copy link
Contributor

@Quexington Quexington commented Dec 10, 2024

(hide whitespace to review)

This PR tries to drastically simplify the action scope primitive and remove the sqlite dependency. The motivation behind this was to support nested scopes, but that's not really why this had to happen, it was moreso discovered along the way.

Reviewing the test changes as a diff makes sense, but it might make sense to just review the new action_scope.py file manually since the diff is really a conceptual one rather than a line-by-line one.

The idea now is, instead of using serialization into a sqlite DB as a protection against unexpected edits, we just pay more attention to the references we're handing out. The process basically goes as follows when you want to "check out" the mutable object that is held at the top level:

  1. create a deepcopy of the top level object
  2. store the current top level object in a new location
  3. replace the top level object with the new copy and hand it to the caller
  4. If the operation with the copy finishes successfully, edit (not replace) the old object
  5. Whether or not the old operation is successful, put the old object back into the top level spot

There's also an additional change that was made along the way which is somewhat unrelated but is actually a feature improvement on action scopes. They now require a lock acquisition function (like DBWrapper.writer) when being constructed and will acquire that lock when opening the scope and release it when closing the scope. This should enforce consistent usage of the idea behind WalletStateManager.lock (to prevent concurrent actions) and eliminate any need for it.

@Quexington Quexington added the Added Required label for PR that categorizes merge commit message as "Added" for changelog label Dec 10, 2024
@Quexington Quexington changed the title Add support for nested action scopes [CHIA-2041] Add support for nested action scopes Dec 10, 2024
@Quexington Quexington requested a review from altendky December 10, 2024 17:39
@Quexington Quexington marked this pull request as ready for review December 10, 2024 17:39
@Quexington Quexington requested a review from a team as a code owner December 10, 2024 17:39
@Quexington Quexington marked this pull request as draft December 11, 2024 17:35
@Quexington Quexington changed the title [CHIA-2041] Add support for nested action scopes [CHIA-2041] Simplify action scopes and add support for nesting Dec 13, 2024
@Quexington Quexington marked this pull request as ready for review December 13, 2024 20:24
@@ -99,10 +30,9 @@ class ActionScope(Generic[_T_SideEffects, _T_Config]):
from interfering with each other.
"""

_resource_manager: ResourceManager
_side_effects_format: type[_T_SideEffects]
_lock: Callable[..., contextlib.AbstractAsyncContextManager[Any]]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unused.

Depending on the intended usage this comment may not apply but generally when you take a callable it's not useful to have ... for parameters since you can't fill that and rather it needs to satisfy a specific parameter list like [].

Assuming it is supposed to be used, and noting that the tests are not failing, I wonder if there's a missing test that should be written around the exclusivity.


await self._resource_manager.save_resource(interface.side_effects)
self._callback = interface.callback
new_interface = copy.deepcopy(self._active_interface)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deepcopy() is pretty implicit so let's chat about this some.

yield self._active_interface
self._active_interface._callbacks_allowed = previous_interface._callbacks_allowed
for field, value in self._active_interface.__dict__.items():
previous_interface.__dict__[field] = value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this trying to avoid a setattr()? Not all attributes are in .__dict__ necessarily. At least https://docs.python.org/3.12/reference/datamodel.html#slots.

Comment on lines +83 to +86
for field, value in self._active_interface.__dict__.items():
previous_interface.__dict__[field] = value
finally:
self._active_interface = previous_interface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need three copies? Previous, new, being-updated-from-previous? Or, a maybe a we-are-damaged marker that blocks further usage in case the local actions here fail and the caller consumes the failue and keeps on going.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Added Required label for PR that categorizes merge commit message as "Added" for changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants