166 lines
4.5 KiB
Markdown
166 lines
4.5 KiB
Markdown
|
|
# Comments WebSocket Notifications Guide
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The comments feature now supports real-time WebSocket notifications. When a comment is created, updated, or deleted, all subscribers to the entity's comment topic will receive instant updates.
|
||
|
|
|
||
|
|
## WebSocket Topic Format
|
||
|
|
|
||
|
|
```
|
||
|
|
/topic/comments/{entityType}/{entityId}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Examples:
|
||
|
|
- Story comments: `/topic/comments/STORY/story123`
|
||
|
|
- Photo comments: `/topic/comments/PHOTO/photo456`
|
||
|
|
|
||
|
|
## Event Types
|
||
|
|
|
||
|
|
The system broadcasts three types of comment events:
|
||
|
|
|
||
|
|
1. **CREATED** - When a new comment is added
|
||
|
|
2. **UPDATED** - When an existing comment is edited
|
||
|
|
3. **DELETED** - When a comment is removed
|
||
|
|
|
||
|
|
## Event Payload Structure
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"eventType": "CREATED|UPDATED|DELETED",
|
||
|
|
"comment": {
|
||
|
|
"instanceId": "comment123",
|
||
|
|
"entityType": "STORY",
|
||
|
|
"entityId": "story456",
|
||
|
|
"userId": "user123",
|
||
|
|
"userName": "John Doe",
|
||
|
|
"userAvatarUrl": "https://...",
|
||
|
|
"content": "This is a comment",
|
||
|
|
"createTime": "2024-01-01T12:00:00",
|
||
|
|
"updateTime": "2024-01-01T12:00:00",
|
||
|
|
"isEdited": false,
|
||
|
|
"canEdit": true,
|
||
|
|
"canDelete": true
|
||
|
|
},
|
||
|
|
"commentId": "comment123",
|
||
|
|
"entityType": "STORY",
|
||
|
|
"entityId": "story456",
|
||
|
|
"timestamp": "2024-01-01T12:00:00"
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
**Note:** For `DELETED` events, the `comment` field will be `null`, and only `commentId` will be populated.
|
||
|
|
|
||
|
|
## Frontend Integration
|
||
|
|
|
||
|
|
### 1. Subscribe to Comment Topic
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Subscribe when viewing an entity (story or photo)
|
||
|
|
const subscription = stompClient.subscribe(
|
||
|
|
`/topic/comments/${entityType}/${entityId}`,
|
||
|
|
(message) => {
|
||
|
|
const event = JSON.parse(message.body);
|
||
|
|
handleCommentEvent(event);
|
||
|
|
}
|
||
|
|
);
|
||
|
|
|
||
|
|
// Unsubscribe when leaving the page
|
||
|
|
subscription.unsubscribe();
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Handle Comment Events
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
function handleCommentEvent(event: CommentEventDto) {
|
||
|
|
switch (event.eventType) {
|
||
|
|
case 'CREATED':
|
||
|
|
// Add new comment to the list
|
||
|
|
addCommentToList(event.comment);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 'UPDATED':
|
||
|
|
// Update existing comment in the list
|
||
|
|
updateCommentInList(event.comment);
|
||
|
|
break;
|
||
|
|
|
||
|
|
case 'DELETED':
|
||
|
|
// Remove comment from the list
|
||
|
|
removeCommentFromList(event.commentId);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Backend Implementation Details
|
||
|
|
|
||
|
|
### Service Layer
|
||
|
|
|
||
|
|
The `CommentServiceImpl` automatically broadcasts WebSocket events after successful database operations:
|
||
|
|
|
||
|
|
- **createComment()** - Broadcasts `CREATED` event with full comment data
|
||
|
|
- **updateComment()** - Broadcasts `UPDATED` event with updated comment data
|
||
|
|
- **deleteComment()** - Broadcasts `DELETED` event with comment ID only
|
||
|
|
|
||
|
|
### Error Handling
|
||
|
|
|
||
|
|
WebSocket broadcasting failures are caught and logged but do not affect the main comment operation. This ensures that:
|
||
|
|
- Comments are always saved to the database
|
||
|
|
- WebSocket issues don't break the API
|
||
|
|
- Errors are logged for monitoring
|
||
|
|
|
||
|
|
### Transaction Safety
|
||
|
|
|
||
|
|
All comment operations are wrapped in `@Transactional` annotations, ensuring:
|
||
|
|
- Database changes are committed before WebSocket broadcast
|
||
|
|
- Rollback doesn't trigger WebSocket events
|
||
|
|
- Consistency between database and real-time updates
|
||
|
|
|
||
|
|
## Testing
|
||
|
|
|
||
|
|
### Unit Tests
|
||
|
|
|
||
|
|
The `CommentWebSocketTest` class verifies:
|
||
|
|
- WebSocket events are broadcast for all operations
|
||
|
|
- Topic format is correct
|
||
|
|
- Event payload contains expected data
|
||
|
|
- WebSocket failures don't break main operations
|
||
|
|
|
||
|
|
### Manual Testing
|
||
|
|
|
||
|
|
1. Open two browser windows with the same story/photo
|
||
|
|
2. Add a comment in window 1
|
||
|
|
3. Verify the comment appears in window 2 without refresh
|
||
|
|
4. Edit/delete the comment in window 1
|
||
|
|
5. Verify changes appear in window 2 in real-time
|
||
|
|
|
||
|
|
## Performance Considerations
|
||
|
|
|
||
|
|
- **Topic-based broadcasting**: Only users viewing the specific entity receive updates
|
||
|
|
- **Lightweight payloads**: Events contain only necessary data
|
||
|
|
- **Non-blocking**: WebSocket operations don't slow down API responses
|
||
|
|
- **Graceful degradation**: System works without WebSocket (polling fallback)
|
||
|
|
|
||
|
|
## Security
|
||
|
|
|
||
|
|
- WebSocket connections require authentication
|
||
|
|
- Users can subscribe to any public entity's comment topic
|
||
|
|
- Private entities should implement additional authorization checks
|
||
|
|
- Comment content is validated before broadcasting
|
||
|
|
|
||
|
|
## Monitoring
|
||
|
|
|
||
|
|
Key metrics to monitor:
|
||
|
|
- WebSocket connection count
|
||
|
|
- Message delivery success rate
|
||
|
|
- Broadcast latency
|
||
|
|
- Failed broadcast attempts (check logs)
|
||
|
|
|
||
|
|
## Future Enhancements
|
||
|
|
|
||
|
|
Potential improvements:
|
||
|
|
- Personal notification queue for entity owners
|
||
|
|
- Comment mention notifications (@username)
|
||
|
|
- Typing indicators
|
||
|
|
- Read receipts
|
||
|
|
- Comment reaction notifications
|