-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Enforce Editor Lock for Write, Append, and Upload Operations in DataNode #2122
base: develop
Are you sure you want to change the base?
Conversation
Hey, @FlorianJacta and @bobbyshermi |
if self.id not in in_memory_storage: | ||
in_memory_storage[self.id] = [] | ||
|
||
in_memory_storage[self.id].append(data) # Append new data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the previous data of the data node has no append
method.
In other words, what if in_memory_storage[self.id]
has no append
method?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I added a if instance condition to resolve that. Please review it and let me know if any changes required.
@bobbyshermi Did you review it sir? |
@bobbyshermi @FlorianJacta @jrobinAV |
@bobbyshermi @jrobinAV @FlorianJacta Please inform me if this issue is open or closed? |
|
@PrakharJain1509 The issue is still open, yes, and your PR is in the review process. Thank you for your patience. We will get back to you very soon. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your contribution! The changes look good to me, but tests are failing. Please help take a look and fix it 😃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a high-quality PR. Thank you very much.
Please have a look at the various comments.
Can you also create a new test file, tests/core/data/test_file_datanode_mixin.py,
and test the upload changes you made? The test functions should look like the ones you already created for the write and append functions.
Thx,
@@ -442,9 +444,16 @@ def write(self, data, job_id: Optional[JobId] = None, **kwargs: Dict[str, Any]): | |||
""" | |||
from ._data_manager_factory import _DataManagerFactory | |||
|
|||
if self.edit_in_progress and editor_id and self.editor_id != editor_id: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, this covers the case where the data node is already locked by a different editor than the one attempting to write it. We also need to check that the self.editor_expiration_date
(if it exists) is not past.
@@ -745,3 +745,33 @@ def test_change_data_node_name(self): | |||
# This new syntax will be the only one allowed: https://github.com/Avaiga/taipy-core/issues/806 | |||
dn.properties["name"] = "baz" | |||
assert dn.name == "baz" | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we are missing a few test cases here:
- An editor
editor_id_1
locked the data node, but the expiration date passed. Another "manual" editor,editor_id_2,
should succeed in writing the data node. - An editor
editor_id_1
locked the data node, but the expiration date passed. Another "manual" editor,editor_id_2,
should succeed in appending the data node. - The orchestrator locks the data node. A "manual" editor should fail to write the data node.
- The orchestrator locks the data node. The Orchestrator should succeed in writing the data node.
The orchestrator locks the data node. A "manual" editor should fail to append it.
raise DataNodeIsBeingEdited(self.id, self.editor_id) | ||
|
||
if not editor_id and self.edit_in_progress: | ||
print("Orchestrator writing without editor_id") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This covers the case where the Orchestrator attempts to write a data node locked by an editor. We can eventually add an info log using the _logger
attribute, but we don't want any print in the production code. Please remove it.
self._write(data) | ||
self.track_edit(job_id=job_id, **kwargs) | ||
self.unlock_edit() | ||
self.last_edit_date = datetime.now() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last_edit_date
setting is already done in the track_edit
method called right after. Please revert this line.
|
||
if self._editor_expiration_date and datetime.now() > self._editor_expiration_date: | ||
self.unlock_edit() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see what case we want to cover here. For me, the next condition already covers this case. Can you elaborate? Otherwise, we should revert it.
|
||
self.track_edit(timestamp=datetime.now()) # type: ignore[attr-defined] | ||
self._write(data) | ||
self.track_edit(job_id=job_id, editor_id=editor_id, **kwargs) # type: ignore[attr-defined] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.track_edit(job_id=job_id, editor_id=editor_id, **kwargs) # type: ignore[attr-defined] | |
self.track_edit(timestamp=datetime.now(), editor_id=editor_id, **kwargs) # type: ignore[attr-defined] |
|
||
self.track_edit(timestamp=datetime.now()) # type: ignore[attr-defined] | ||
self._write(data) | ||
self.track_edit(job_id=job_id, editor_id=editor_id, **kwargs) # type: ignore[attr-defined] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THere is no possible job_id. This cannot be called by the orchestrator.
if self.edit_in_progress and self.editor_id != editor_id: | ||
raise DataNodeIsBeingEdited(self.id, self.editor_id) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of raising an exception, you should build a specific Reason
and add it to the reason_collection
, as it is done below in the code for instance. You can re-use the DataNodeEditInProgress
reason class.
I would also move this code after the creation of the reason_collection variable:
reason_collection = ReasonCollection()
|
||
def _append(self, data): | ||
"""Append data to the existing data in the in-memory storage.""" | ||
if self.id not in in_memory_storage: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.id must not be None. you can remove it from the condition.
if not isinstance(in_memory_storage[self.id], list): | ||
in_memory_storage[self.id] = [in_memory_storage[self.id]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If in_memory_storage[self.id]
is not a list, a NotImplementedError
should be raised.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments should be resolved first.
Sure, Give me some time, Will do so in some days. |
@PrakharJain1509 FYI, this PR is slightly related to your changes. |
PR Description
Title: Enforce Editor Lock for Write, Append, and Upload Operations in DataNode
Summary
This PR addresses the issue #2017 where a
DataNode
could be modified by other editors despite being locked by one. It ensures that once aDataNode
is locked with aneditor_id
, no other editor can perform write, append, or upload operations until the lock is released.Changes Implemented
write()
,append()
, and_upload()
methods:DataNodeIsBeingEdited
exception when a different editor attempts to modify the lockedDataNode
.editor_id
even during an active lock.test_data_node.py
to validate the new behavior.Acceptance Criteria Met
editor_id
.This PR ensures consistent locking behavior across all relevant operations in line with the documentation and expected usage.