-
Notifications
You must be signed in to change notification settings - Fork 24
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
Annotation Locking Mechanism #6819
Conversation
@MichaelBuessemeyer I think the route is already usable, should be possible to start developing the front-end part :) TODO backend:
|
@@ -59,6 +59,7 @@ webKnossos { | |||
cache { | |||
user.timeout = 3 minutes | |||
} | |||
annotation.mutex.expiryTime = 2 minutes |
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.
@fm3 As this is a setting that might be changed, I think it would be a good idea to expose it to the frontend. Thus the frontend can adjust to the timeout duration so it requests the mutex in time.
If that setting is not designed to be changed, ignore my post 📰
@fm3 I don't know whether that's needed :)
|
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.
Great stuff 👍 The code looks very good. I only left some nitpicks/edge cases.
Kudos for writing the tests 💯 Didn't review those yet, though. I'll test after the feedback is addressed :)
if (isInitialRequest && canEdit) { | ||
// Only set allow update to true in case the first try to get the mutex succeeded. | ||
yield* put(setAnnotationAllowUpdateAction(true)); | ||
} else { | ||
yield* put(setAnnotationAllowUpdateAction(false)); | ||
} |
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 (isInitialRequest && canEdit) { | |
// Only set allow update to true in case the first try to get the mutex succeeded. | |
yield* put(setAnnotationAllowUpdateAction(true)); | |
} else { | |
yield* put(setAnnotationAllowUpdateAction(false)); | |
} | |
// Only set allow update to true in case the first try to get the mutex succeeded. | |
yield* put(setAnnotationAllowUpdateAction(isInitialRequest && canEdit)); |
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.
while my suggestion should be equal to the current code, I just noticed during testing that the logic itself is faulty. at the moment, on each iteration that is not the first, the boolean will be false and thus disabling the "is allowed" property. thus, I cannot edit my own annotation even when I got the mutex.
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.
at the moment, on each iteration that is not the first, the boolean will be false and thus disabling the "is allowed" property. thus, I cannot edit my own annotation even when I got the mutex.
Ah, I see what the problem is. Sorry, that I missed that. I did not test manually for long enough for this to happen 😅 .
The code now remembers whether the mutex could be acquired from the beginning. Now the code only sets the "is allowed" to false, if the mutex could wasn't acquired from the beginning or canEdit
sent by the server is false. This should be the correct logic right?
The new logic should now be:
=> Keep allowUpdate
true in case the mutex was acquired initially and the server sends back canEdit = true
=> once the server sends canEdit = false
allowUpdate
will never be set to true again until the user reloads the page.
=> If the mutex wasn't acquired initially, the allowUpdate
will always be false until the user reloads the page.
This should cover all cases now, right? And blocking all updates from the annotation once the mutex was lost only a single time should be correct, right? Because there could be another potential user that had the mutex in the meantime and made some small changes to the annotation.
another thing I just noticed: If I'm the owner of an annotation, but don't have the mutex currently, I cannot disable the "may others edit" property (because the annotation is read-only for me). one could argue that this is fine, because the owner shouldn't disturb another user that is currently working on it, but I feel like this can be annoying if a user decides that they want to regain full control. @fm3 @MichaelBuessemeyer do you have thoughts on that (regardless of implementation)? |
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.
see my one comment. I think, the logic is a bit broken now so that the mutex cannot be kept. I wonder why the tests didn't catch that?
Co-authored-by: Philipp Otto <[email protected]>
- fix logic bug - always disable updating when the mutex acquiring results in an exception - add test covering case where the mutex can be acquired after some requests
That was due to the tests not testing the case where the mutex was acquired correctly multiple times in a row. They only tested for one successful request and then another failing one (with |
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.
Works excellent now 👍 Only left one renaming suggestion..
UX-wise one thing caught my attention: If I'm viewing my own shared annotation, but don't have the mutex, the navbar switches to the read-only mode which is fine per se. However, (apart from the toast which can be closed), the UI doesn't tell me anything about this state. The "Copy to my account" even suggests that this annotation isn't mine (even though it is). Do you think the navbar could be tweaked a bit in that state? I think, you could check for annotation.owner == activeUser && isReadOnly
. In that case, the copy-button could simply say "Duplicate" and an antd tag could be next to the avatar saying "Locked by ..." (with a tooltip which explains a bit more).
return; | ||
} | ||
const othersMayEdit = yield* select((state) => state.tracing.othersMayEdit); | ||
const ONE_MINUTE = 1000 * 60; |
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'd rather give this variable a semantic meaning (e.g., acquireMutexInterval).
@philippotto Thanks for the suggestions. Using a tag as a component doesn't seem very visually appealing to me, as it does not fit into the style of the navbar. But I cannot think of another component that could be used here instead :/ I additionally added a tooltip to the tag that uses the same message as the toast. Visually it looks like this now: Another thing I noticed is that these messages frequently pop up: And this is an example image of the renaming of the "copy to my account" button: I'll fix the tests now 😅 |
Awesome!
I prefer the second version, too, and think it looks alright 👍
Hm, yeah, you're probably right. Maybe adapt the saga to not display the warnings if the "others may edit" setting is true (in that case one has either locked the annotation --> no problem. OR: someone else has locked it --> navbar already shows what's up).
👍 |
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.
Awesome, lets ship it :)
trailingNavItems.push( | ||
<AnnotationLockedByUserTag blockedByUser={blockedByUser} activeUser={activeUser} />, |
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.
Looks like I forgot to add a unique key attribute here 🙈
…d-v4.24 * 'master' of github.com:scalableminds/webknossos: Implement http range requests for HttpsSeekableByteChannel (#6869) new GH action for adding issues to project board Fix links in Changelog (#6881) adds dedicated explore method for zarr datasets with a datasource-properties.json (#6879) Release 23.03.0 (#6880) Fix superUser being wrongly marked as organization owners (#6876) Followups for OME-TIFF export (#6874) Fix reload-precomputed-mesh functionality (#6875) Adds OME-TIFF export (#6838) Add evolutions 99,100 to migration guide (#6871) Add link to imprint and privacy to help menu (#6870) Annotation Locking Mechanism (#6819)
…come_header_UI * 'master' of github.com:scalableminds/webknossos: (34 commits) Slim down view mode dropdown by using icons (#6900) Logging on password reset/change (#6901) When merging volume tracings, also merge segment lists (#6882) avoid spinner when switching tabs in dashboard (#6894) Upgrade Antd to v4.24 (#6865) Support n5 end-chunks with chunksize differing from metadata chunksize (#6890) Implement http range requests for HttpsSeekableByteChannel (#6869) new GH action for adding issues to project board Fix links in Changelog (#6881) adds dedicated explore method for zarr datasets with a datasource-properties.json (#6879) Release 23.03.0 (#6880) Fix superUser being wrongly marked as organization owners (#6876) Followups for OME-TIFF export (#6874) Fix reload-precomputed-mesh functionality (#6875) Adds OME-TIFF export (#6838) Add evolutions 99,100 to migration guide (#6871) Add link to imprint and privacy to help menu (#6870) Annotation Locking Mechanism (#6819) Update deprecated antd <Menu> (#6860) Add functions to get and set segment colors to the frontend API (#6853) ...
new route
POST /api/annotations/<annotationId>/acquireMutex
(no body) will, for othersMayEdit annotations, return json body with two fields: canEdit: bool, blockedByUser: user (optional, only set if blocked. Uses compact version of user json, just like in user/owner in annotation json)URL of deployed dev instance (used for testing):
Steps to test:
othersMayEdit
. This should not be possible, as sample user2 currently has the mutex.othersMayEdit
setting again.#Issues: