ADR Suggestion
Detecting cyclic dependencies easily with pings
#122
Closed
damskii9992
started this conversation in
Ideas
Replies: 1 comment 3 replies
-
Maybe returning a bool and subsequent check in the caller rather than throwing is a better idea? def _validate_dependencies(self, origin=None) -> bool:
if origin == self.unique_name:
write("..error message.")
return False
origin = origin or self.unique_name
for observer in self._observers:
if not observer._validate_dependencies(origin=origin):
return False
return True This way, calling |
Beta Was this translation helpful? Give feedback.
3 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
General
Since parameters can be made dependent after they're created, it is possible to end up in an infinite loop where a dependent parameters update triggers another dependent parameters update which in turn triggers the first parameters update and so on:
In ADR #10 a system for detecting cyclic dependencies were suggested and implemented. In this ADR I propose a simpler yet smarter system, which also properly handles the edge-case described in #10.
Current Implementation
In the current implementation, the cyclic dependencies are discovered through the observer pattern with update_ids:
If an update is triggered by a manual change, such as a value change of an independent parameter, the update gets assigned a unique id.
This unique id is then passed to the observers along with the unique_name of the object that triggered the update;
In the observers _update method, the update id is checked against an internal dictionary for the updating object. If the stored update id for the updating object is different from the new one, set the stored update id to the new one and proceed with the update, and notify its own observers, passing along the update_id, otherwise raise an error warning that a cyclic dependency has been detected:
Proposed implementation
In setting up the dependent parameter, in the
make_dependent_on
method, before any of the parameters values are changed, a ping is sent to all its observers (if any) by calling the_ping_observers
method (implemented in theDescriptorNumber
):Only in case this dependency-traversal doesn't raise an error, is the dependent parameter updated with the dependency expression.
This approach handles the edge-case described in #10, it simplifies the code base by making the
_notify_observers
and_update
methods simpler, and it get rids of two attributes: theupdate_id_iterator
in theglobal_object
and the_dependency_updates
dictionary on Parameter, since the unique_name of the Parameter issuing the ping is now used instead.Beta Was this translation helpful? Give feedback.
All reactions