Store: add persistent dependency registry and notify hook#2
Store: add persistent dependency registry and notify hook#2sejalpunwatkar wants to merge 4 commits intoBigDataAnalyticsGroup:mainfrom
Conversation
tests/store/test_store.py
Outdated
| store.put(af1) | ||
| store.put(af2) | ||
|
|
||
| store.register_dependency(af1.uuid, af2.uuid) |
There was a problem hiding this comment.
so this is basically a dependency mechanism independent from observable/observers, this means it is up to the user to additonally register those dependencies? That sounds error-prone to me.
In general, this unit test is very short.
store/store.py
Outdated
| def _get_registry(self): | ||
| return self.sqlite_dict[self._registry_key] | ||
|
|
||
| def register_dependency(self, key: int, af_id: int): |
There was a problem hiding this comment.
please make sure to follow the contribution guideline
| ) | ||
|
|
||
| # dependency registry (persistent) | ||
| self._registry_key = "__dependency_registry__" |
There was a problem hiding this comment.
what is the purpose of this string?
tests/store/test_store.py
Outdated
| try: | ||
| store.put(af1) | ||
| except TypeError: | ||
| pass |
There was a problem hiding this comment.
You are suppressing a possible exception here? Why?
- Implement __dependency_registry__ in Store for persistent AF relationships. - Integrate _notify into Store.put for automated, cross-session updates. - Standardize on string keys for SqliteDict to ensure ID consistency. - Add lifecycle unit test with class-level mock for notification verification.
|
Hi @jensdittrich ,
|
|
@jensdittrich I've updated the code to address your feedback, including the automated notifications and expanded tests. Please take a look whenever you have a moment! |
|
I am currently returnign from EDBT, I will take a look at your code next week. |
|
Thank you for the update. I hope the conference was successful and look forward to your feedback next week. In the meantime, I’ll continue reviewing the FQL operators and the group_by logic to see where I can best assist with the next steps. |
|
sorry for the delay, I was travelling please use the inline comments for discussions where possible, like that we can discuss each issue in a separate thred, I will follow up there now... |
store/store.py
Outdated
| """Store an AttributeFunction in the persistent store. | ||
| @param af: The AttributeFunction to store. | ||
| """ | ||
| uuid_str = str(af.uuid) |
There was a problem hiding this comment.
still no typehint, I would expect
uuid_str: str = ...
or
uuid: str = ...
| return self.sqlite_dict.get(self._registry_key, {}) | ||
|
|
||
| def register_dependency(self, key: int, af_id: int): | ||
| def register_dependency(self, parent_uuid: uuid.UUID, child_uuid: uuid.UUID): |
There was a problem hiding this comment.
so the idea here is to have a separte dependency registry, i.e. all subscriptions are additionally subscribed here, correct?
Is this supposed to be redundant to the data keptin the AFs? Why not store it with the AFs directly?
There was a problem hiding this comment.
Yes, the idea is to maintain a separate persistent dependency registry that mirrors the subscription relationships.
The reason for not storing dependencies directly within the AttributeFunctions is to keep the dependency mechanism at the Store level and independent of the in-memory state of AFs. This ensures that:
Dependencies persist even when AFs are not loaded in memory
Notifications can be triggered correctly after reloading the store
The internal structure of AttributeFunction does not need to be modified for persistence concerns
So the registry is not meant to be redundant, but rather a persistence layer that enables subscriptions to work transparently across sessions.
store/store.py
Outdated
| registry = self._get_registry() | ||
|
|
||
| key = str(key) | ||
| p_uuid_str = str(parent_uuid) |
There was a problem hiding this comment.
same typhint comment as above, fix globally
| dependent_af.update() | ||
| parent_af = self.get(parent_uuid) | ||
|
|
||
| for dependent_id in registry[p_uuid_str]: |
store/store.py
Outdated
| # trigger recomputation / update | ||
| if hasattr(dependent_af, "update"): | ||
| dependent_af.update() | ||
| parent_af = self.get(parent_uuid) |
tests/store/test_store.py
Outdated
| WAS_UPDATED = False | ||
|
|
||
| def global_update_mock(self, other=None, *args, **kwargs): | ||
| """Picklable global mock that accepts the 'other' argument.""" |
There was a problem hiding this comment.
from this comment I do not understand the purpose of this, extend the explanation
There was a problem hiding this comment.
why do you need a global variable here?
There was a problem hiding this comment.
I’ve extended the docstring to clarify the purpose of the mock. It explains why a global flag is used to detect the internal update() call and why the function is defined at module level to remain picklable.
tests/store/test_store.py
Outdated
| store.put(child_af) | ||
| store.put(parent_af) | ||
|
|
||
| store.put(parent_af) |
There was a problem hiding this comment.
why are you putting it twice?, see 249
tests/store/test_store.py
Outdated
| Test persistent dependency mechanism in Store. | ||
|
|
||
| This test covers: | ||
| 1. Registering a dependency between two AttributeFunctions (AFs) |
There was a problem hiding this comment.
this is again phrased separate fro mthe subscription mechanism
I would expect the test to create AFs with subscriptions and then check through the store whether notificaitons work through dependencies even in the present of data being not available in main memory
So dependencies can be a way to enable subscriptions to work through the store. But the dependency mechanism should be invisible to the user.
Summary
This PR introduces a persistent dependency mechanism for AttributeFunctions within the Store, enabling a foundation for observer-style updates across sessions.
What’s implemented
register_dependency(key, dependent_id)to track relationships between AttributeFunctionsStore.put()to trigger notifications for dependent AttributeFunctionsDesign decisions
update()methods to maintain compatibility with current implementationsTests
Scope
This PR focuses on establishing a persistent observer foundation. It does not enforce or redefine observer/update behavior, leaving room for future API design and refinement.