# Reactions WebSocket Notifications Guide ## Overview The reactions feature now supports real-time WebSocket notifications. When a reaction is created, updated, or deleted, all subscribers to the entity's reaction topic will receive instant updates. ## WebSocket Topic Format ``` /topic/reactions/{entityType}/{entityId} ``` ### Examples: - Story reactions: `/topic/reactions/STORY_ITEM/story123` - Photo reactions: `/topic/reactions/PHOTO/photo456` ## Event Types The system broadcasts three types of reaction events: 1. **CREATED** - When a new reaction is added 2. **UPDATED** - When an existing reaction is changed to a different type 3. **DELETED** - When a reaction is removed ## Event Payload Structure ```json { "eventType": "CREATED|UPDATED|DELETED", "reaction": { "entityType": "STORY_ITEM", "entityId": "story456", "userId": "user123", "userName": "John Doe", "userAvatarUrl": "https://...", "reactionType": "LIKE", "createTime": "2024-01-01T12:00:00" }, "userId": "user123", "entityType": "STORY_ITEM", "entityId": "story456", "timestamp": "2024-01-01T12:00:00" } ``` **Note:** For `DELETED` events, the `reaction` field will be `null`, and only `userId` will be populated to identify whose reaction was removed. ## Reaction Types The system supports five reaction types: - `LIKE` - Like/thumbs up - `LOVE` - Heart/love - `LAUGH` - Laughing face - `WOW` - Surprised/amazed - `SAD` - Sad face ## Frontend Integration ### 1. Subscribe to Reaction Topic ```typescript // Subscribe when viewing an entity (story or photo) const subscription = stompClient.subscribe( `/topic/reactions/${entityType}/${entityId}`, (message) => { const event = JSON.parse(message.body); handleReactionEvent(event); } ); // Unsubscribe when leaving the page subscription.unsubscribe(); ``` ### 2. Handle Reaction Events ```typescript function handleReactionEvent(event: ReactionEventDto) { switch (event.eventType) { case 'CREATED': // Add new reaction to the summary addReactionToSummary(event.reaction); break; case 'UPDATED': // Update existing reaction in the summary updateReactionInSummary(event.reaction); break; case 'DELETED': // Remove reaction from the summary removeReactionFromSummary(event.userId, event.entityType, event.entityId); break; } } ``` ### 3. Update Reaction Counts When receiving events, update the reaction counts and user lists: ```typescript function addReactionToSummary(reaction: ReactionDto) { // Increment count for the reaction type counts[reaction.reactionType]++; // If it's the current user's reaction, update userReaction if (reaction.userId === currentUserId) { userReaction = reaction.reactionType; } // Add to recent reactions list recentReactions.unshift(reaction); if (recentReactions.length > 10) { recentReactions.pop(); } } function updateReactionInSummary(reaction: ReactionDto) { // Find and update the old reaction const oldReaction = recentReactions.find(r => r.userId === reaction.userId); if (oldReaction) { // Decrement old type count counts[oldReaction.reactionType]--; // Increment new type count counts[reaction.reactionType]++; // Update the reaction in the list Object.assign(oldReaction, reaction); } // If it's the current user's reaction, update userReaction if (reaction.userId === currentUserId) { userReaction = reaction.reactionType; } } function removeReactionFromSummary(userId: string, entityType: string, entityId: string) { // Find the reaction to remove const reactionIndex = recentReactions.findIndex(r => r.userId === userId); if (reactionIndex !== -1) { const reaction = recentReactions[reactionIndex]; // Decrement count counts[reaction.reactionType]--; // Remove from list recentReactions.splice(reactionIndex, 1); } // If it's the current user's reaction, clear userReaction if (userId === currentUserId) { userReaction = null; } } ``` ## Backend Implementation Details ### Service Layer The `ReactionServiceImpl` automatically broadcasts WebSocket events after successful database operations: - **addOrUpdateReaction()** - Broadcasts `CREATED` event for new reactions or `UPDATED` event for changed reactions - **removeReaction()** - Broadcasts `DELETED` event with user ID only ### Error Handling WebSocket broadcasting failures are caught and logged but do not affect the main reaction operation. This ensures that: - Reactions are always saved to the database - WebSocket issues don't break the API - Errors are logged for monitoring ### Transaction Safety All reaction 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 Create tests to verify: - WebSocket events are broadcast for all operations - Topic format is correct (`/topic/reactions/{entityType}/{entityId}`) - 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 reaction in window 1 3. Verify the reaction appears in window 2 without refresh 4. Change the reaction type in window 1 5. Verify the change appears in window 2 in real-time 6. Remove the reaction in window 1 7. Verify the removal appears 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 reaction topic - Private entities should implement additional authorization checks - Reaction types are validated before broadcasting ## Monitoring Key metrics to monitor: - WebSocket connection count - Message delivery success rate - Broadcast latency - Failed broadcast attempts (check logs) ## Comparison with Comments Reactions WebSocket implementation follows the same pattern as Comments: | Feature | Comments | Reactions | |---------|----------|-----------| | Topic Format | `/topic/comments/{type}/{id}` | `/topic/reactions/{type}/{id}` | | Event Types | CREATED, UPDATED, DELETED | CREATED, UPDATED, DELETED | | Event DTO | CommentEventDto | ReactionEventDto | | Service Integration | CommentServiceImpl | ReactionServiceImpl | | Error Handling | Non-blocking, logged | Non-blocking, logged | | Transaction Safety | @Transactional | @Transactional | ## Future Enhancements Potential improvements: - Personal notification queue for entity owners - Reaction analytics (trending reactions) - Reaction animations in real-time - Bulk reaction updates for performance - Reaction history tracking