- 
                Notifications
    
You must be signed in to change notification settings  - Fork 20
 
feat(comment-replies): add single threading on comments #108
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
base: master
Are you sure you want to change the base?
Conversation
14ed33c    to
    d7b6bd0      
    Compare
  
    d7b6bd0    to
    fbe0ed4      
    Compare
  
    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 Zach, this looks great and I agree with the 1-level limit, this makes it much simpler. The API routes are also nicely laid out, I don't think there's any better way of doing this.
        
          
                rfcs/rdm-0108-threaded-comments.md
              
                Outdated
          
        
      | 
               | 
          ||
| ### **Search index design** | ||
| 
               | 
          ||
| Children are indexed inline with their parent for efficient retrieval and display. The search mappings include: | 
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.
Apologies if I misunderstand: won't this mean that child comments are retrieved twice, once for the search query and once for the systemfield calculation? Or will we filter for only null parent_ids during the search query and then just fill in the children with the systemfield?
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.
During the search query, the children are already indexed. During the systemfield calculation, they are retrieved and then cached locally for subsequent queries. The children actually are not indexed as independent events in the proposed implementation.
| When a comment is deleted, the system handles threading carefully: | ||
| 
               | 
          ||
| **Deleting a child comment:** | ||
| - The child is converted to a `LogEvent` with "comment deleted" payload | 
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.
Would it not be clearer maybe if we kept it as a CommentEvent? And we could remove the content, but add a field to the payload_schema marking it as deleted, so we can render some text in the UI, e.g. "This comment was deleted", with some formatting to clearly differentiate it from regular comment content. And maybe also the time at which it was deleted.
GitHub uses a sort of similar approach: palkerecsenyi/discussiontest#1 (comment). Although this is confusing because it just removes the comment content without showing a message to clarify that it was deleted.
| 
               | 
          ||
| # Convert to LogEvent | ||
| event.type = LogEventType | ||
| event["payload"] = {"event": "comment_deleted", "content": "deleted a comment"} | 
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.
Does this get i18n-ised when being rendered or is it always in English?
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.
in the code we translate it, I forgot it in the RFC 🙃
| - Multiple `children` (replies) - but those children **cannot have children** themselves | ||
| - A computed `children` field that includes full metadata of all child events | ||
| 
               | 
          ||
| **Threading depth is limited to exactly 1 level** to keep discussions simple and readable. Attempting to reply to a reply results in a validation error. | 
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.
Attempting to reply to a reply results in a validation error.
you mean in the REST API, right? UI shouldn't display this option in a first place, maybe worth mentioning
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.
Yes, exactly. This refers to the REST API
        
          
                rfcs/rdm-0108-threaded-comments.md
              
                Outdated
          
        
      | Threading is implemented via a **dedicated REST API endpoint** rather than accepting `parent_id` in the request body. This design: | ||
| - Makes the API more explicit and RESTful | ||
| - Prevents users from manipulating `parent_id` in request bodies | ||
| - Clearly separates top-level comments from replies | ||
| - Ensures `parent_id` comes from the trusted URL path, not user input | 
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 part is not super clear to me, especially how URL path is more trusted than having parent_id in the payload? I understand it will be validated either way, not sure we need dedicated endpoint. Unless I am missing some context.
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 experimented with having one a new param in the payload for parent_id in the same route as creating a comment. In that solution, you needed to ensure that the parent_id passed down was validated to disallow multiple levels of nested replies e.g
if incoming_event.parent_id:
   event_parent = _get_event(incoming_event.parent_id)
   if event_parent.parent_id:
     raise()
The specific reply endpoint just accepts the message in the payload.
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 experimented with having one a new param in the payload for
parent_idin the same route as creating a comment. In that solution, you needed to ensure that theparent_idpassed down was validated to disallow multiple levels of nested replies e.gif incoming_event.parent_id: event_parent = _get_event(incoming_event.parent_id) if event_parent.parent_id: raise()The specific reply endpoint just accepts the message in the payload.
Sorry, the validation of the parent_id is always needed. And indeed, is the validation code that ensures the parent_id not the fact that is coming from the URL. Having a dedicated endpoint seems cleaner in the REST API and simplified a bit how the logic of indexing the parent-child events.
        
          
                rfcs/rdm-0108-threaded-comments.md
              
                Outdated
          
        
      | - The parent is converted to a `LogEvent` | ||
| - All children are recursively converted to `LogEvents` | 
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.
wouldn't it be less complex if we keep the same CommentEvent but marked as deleted?
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 was the case in the past. We will evaluate if it makes sense to change this to actually a CommentEvent or display them differently in the UI
        
          
                rfcs/rdm-0108-threaded-comments.md
              
                Outdated
          
        
      | **Key insights**: | ||
| 
               | 
          ||
| 1. **Separate methods**: `create()` for top-level, `reply()` for threaded - clear separation of concerns | ||
| 2. **URL-based parent_id**: Parent comes from URL path, not request body (prevents manipulation) | 
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 am not convinced about "prevents manipulation" part... You can do POST to /comment/234/reply and /comment/254, nothing prevents you to do that, unless I am missing some other detail or misunderstanding the thought behind this.
How are you planning to prevent replies to random comments (especially in request which user shouldn't have access to)?
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 permission is being checked on the request level i.e full URL is /requests/<request_id>/comments/<comment_id>/reply. There is no POST action on /requests/<request_id>/comments/<comment_id>, what is your concern?
| 
               | 
          ||
| ## Unresolved questions | ||
| 
               | 
          ||
| 1. **Notification strategy**: Should replies trigger different notifications than top-level comments? Should users be notified when someone replies to their comment specifically? | 
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.
could it be opt in/opt out, like "follow the thread"?
| 
               | 
          ||
| 1. **Notification strategy**: Should replies trigger different notifications than top-level comments? Should users be notified when someone replies to their comment specifically? | ||
| 
               | 
          ||
| 2. **Search and filtering**: How should search work across threaded comments? Should searching return top-level comments with matching children highlighted, or individual matching children? | 
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 saw in some solutions both the whole thread and the child comment were highlighted on search, with an effect of narrowing focus from "big picture" to single comment
340c6ee    to
    609db6d      
    Compare
  
    609db6d    to
    5b7188c      
    Compare
  
    
closes #107