Skip to content

Make user bounding box updates more efficient #8492

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

Draft
wants to merge 18 commits into
base: master
Choose a base branch
from

Conversation

MichaelBuessemeyer
Copy link
Contributor

@MichaelBuessemeyer MichaelBuessemeyer commented Apr 1, 2025

This PR add more update actions for user bounding boxes. This makes it more efficient to update a single bounding box (including adding and deleting). Moreover, the version restore view can display more details on what was actually changed (e.g. color of the bounding box).

URL of deployed dev instance (used for testing):

  • https://___.webknossos.xyz

Steps to test:

  • abc

TODOs:

  • if code is kept: make saga code DRY in volumetracing_saga and skeletontracing_saga
  • use updateUserBoundingBoxVisibility actions for visibility updates
    • frontend
    • backend
  • consider renaming actions (no "action" in name field AND new action name, e.g. updateUserSpecificBoundingBox[Volume|Skeleton])
    • frontend (done: no action in name field)
    • backend

Issues:


(Please delete unneeded items, merge only when none are left open)

Copy link
Contributor

coderabbitai bot commented Apr 1, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@fm3
Copy link
Member

fm3 commented Apr 1, 2025

@MichaelBuessemeyer How would you feel about three new actions, Add/Delete/Update bbox? That way we don’t need an update action for every property.
It’s true that the version restore view will be a little less detailed then, but I’d say that’s a fair price for the reduced code complexity. Maybe @philippotto also has an opinion? TBH I think there’s already an overwhelming amount of update action classes…

@MichaelBuessemeyer
Copy link
Contributor Author

@MichaelBuessemeyer How would you feel about three new actions, Add/Delete/Update bbox? That way we don’t need an update action for every property. It’s true that the version restore view will be a little less detailed then, but I’d say that’s a fair price for the reduced code complexity. Maybe @philippotto also has an opinion? TBH I think there’s already an overwhelming amount of update action classes…

Yes, I agree that there are already a lot of update actions. My idea was to follow how it is done for skeleton update actions. There we also have the update action on such a detailed degree. Moreover, when thinking about the upcoming collab feature, the design doc states:

update actions of segment metadata (and maybe trees, too, for consistency) should be updated per key (so that setting two different keys does not overwrite each other)

I can image the same problem with bounding boxes:

  1. User A renames BBox with Id x
  2. User B re-colors the BBox with Id x
  3. User A saves
  4. User B receives update:

At 4. the frontend now needs to be really smart to first find out by a diff that the name of the bounding box was changed. A simple comparison with the current BBox state of User B is not possible as the diff would also reveal that the color changed (done by User B). But only the name did and only the name should be updated.

This complexity could be saved in case we have an action for each field making things easier implementation wise (at least that's how I see it on first thought 🤔)

Although as the bounding boxes state are saved at the time Users B last successful update was submitted to the backend, there should be a state that can be compared with to find out that actually only the name changed. But I am not sure how complicated such a code would look like compared to a "updateBBoxNameAction" and simply applying it 🤔.

To me more update actions sound more tedious code-wise but should be more straight forward to implement leading to more code lines but less code complexity

@philippotto
Copy link
Member

I'm also in favor of having less update action types. I think we should aim for update actions where not all properties have to be listed. For example, one could have UpdateBoundingBox(name="new name") and UpdateBoundingBox(color="new color"). then, we only have one class for the update, but the sets of changed keys can be different.

I think, we already had an issue for this, but I cannot find it anymore. from what I remember, the above is a bit tricky, because scala cannot distinguish between undefined and simply not listed in a JSON? or something like this? however, we should be able to work around this somehow (e.g., list the keys explicitly that should be set).

@fm3
Copy link
Member

fm3 commented Apr 3, 2025

You are probably referring to #6657 – there we didn’t consider this for update actions but it might just work there too.

@knollengewaechs
Copy link
Contributor

knollengewaechs commented Apr 3, 2025

what timestamp should be put into the updateAction? the moment the first frontend action was fired or the moment when the annotation is saved?

edit: this is done within update_actions.ts with the types AddServerValues, AsServerAction and ServerUpdateAction. No need to add this to the new actions explicitly.

@knollengewaechs
Copy link
Contributor

knollengewaechs commented Apr 3, 2025

however, we should be able to work around this somehow (e.g., list the keys explicitly that should be set).

my initial solution is to call the frontend updateAction with a Partial<UserBoundindBox> and when sending this to the backend, explicitly include the props in the partial as a list. if anyone thinks that this is a bad idea, please let me know!

edit: talked with @MichaelBuessemeyer, seems to be fine

@knollengewaechs knollengewaechs self-assigned this Apr 4, 2025
@knollengewaechs
Copy link
Contributor

knollengewaechs commented Apr 4, 2025

@MichaelBuessemeyer I updated the frontend code, so that new the new updateActions are called. I tested it a bit with the old backend code, and it seems like the right actions are dispatched if the bounding boxes change. Let me know if the code seems buggy in any way!
And as you can tell, I already added some actions for VolumeTracings aswell.

@MichaelBuessemeyer
Copy link
Contributor Author

@MichaelBuessemeyer I updated the frontend code, so that new the new updateActions are called. I tested it a bit with the old backend code, and it seems like the right actions are dispatched if the bounding boxes change.

Nice 👍 awesome. Thanks a lot 🙏
I changed the frontend code a little to not return single elemented lists of user bounding boxes for the add actions. See c680cf2. This was necessary for further testing.

Let me know if the code seems buggy in any way!

Yeah sorry there is a little buggy / unexpected behaviour:
When the bounds of a bbox are changed the changed bounds are not send as a bounding box object with topLeft, width, height, depth but as changes in the min max props. See the screenshot below (taken from the network tab showing a update actions transaction dispatched to the server):
image
Could you please adjust the frontend to always send the whole bounds as an object (topLeft, width, height, depth) in case some of them were updated? Thanks a lot 🙏

Moreover, I noticed that the frontend seems to send "empty" updates: The updatedPropKeys and updatedProps are empty. This is also shown in the screenshot in the first array entries value. Could you please investigate this and try to avoid such empty update?

Moreover, the cherry on top would be that multiple consecutive bounding box updates to the same bounding box would be combined into a single action. Something like this is already done by the frontend before sending the update actions. See compact_save_queue.ts ll. 100ff. But I am unaware how easy this is to implement. So maybe that's a follow up 🤔?

@knollengewaechs
Copy link
Contributor

@MichaelBuessemeyer thanks for the reports! I will work on this now and try to fix the three problems.

@knollengewaechs
Copy link
Contributor

knollengewaechs commented Apr 10, 2025

okay, I adjusted the frontend code so that

  • the whole bounds object is sent
  • empty updates are omitted
  • consecutive updates on the same bbox on the same prop are out into one action. this is especially important for bounds updates when the user uses the dragging option. One problem is that often multiple actions are put into one batch, and then they cant be omitted. at least thats how its done for other types of actions, e.g. when updating segment.
    let me know if you have more suggestions for this!

@knollengewaechs
Copy link
Contributor

let me know if you notice anything else. during my testing, adding, updating and deleting bboxes seems to work fine :)

@MichaelBuessemeyer
Copy link
Contributor Author

For reference: For now blocked. See https://scm.slack.com/archives/C5AKLAV0B/p1744295336264969

case "updateUserBoundingBoxesInVolumeTracing" =>
deserialize[UpdateUserBoundingBoxesVolumeAction](jsonValue)
case "updateUserBoundingBoxVisibilityInVolumeTracing" =>
Copy link
Contributor

Choose a reason for hiding this comment

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

@MichaelBuessemeyer fyi I removed the "in" in the string -> the new old actions have the names "updateUserBoundingBoxVisibilitySkeletonAction" and "updateUserBoundingBoxVisibilityVolumeAction"

Copy link
Member

Choose a reason for hiding this comment

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

Take care not to mix the scala class names vs the "name" field (string above). This is different for most actions. I think the "name" usually does not end on "Action"

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, I was talking about the "name" field. maybe we have to update the names of the actions that are introduced with this PR because they all end on "Action" 😅

Copy link
Contributor

@knollengewaechs knollengewaechs Apr 23, 2025

Choose a reason for hiding this comment

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

I took the freedom to change the actions names because I think it was me who might have introduced this by mistake. @MichaelBuessemeyer feel free to revert this (675ae35) if you disagree

@@ -38,11 +41,29 @@ export type CreateSegmentUpdateAction = ReturnType<typeof createSegmentVolumeAct
export type UpdateSegmentUpdateAction = ReturnType<typeof updateSegmentVolumeAction>;
export type DeleteSegmentUpdateAction = ReturnType<typeof deleteSegmentVolumeAction>;
export type DeleteSegmentDataUpdateAction = ReturnType<typeof deleteSegmentDataVolumeAction>;
type UpdateUserBoundingBoxesInSkeletonTracingUpdateAction = ReturnType<
typeof updateUserBoundingBoxesInSkeletonTracing
export type AddUserBoundingBoxSkeletonAction = ReturnType<
Copy link
Contributor

Choose a reason for hiding this comment

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

add In

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

More efficiently update User Bounding Boxes
4 participants