- 新增用户资料、偏好设置、自定义字段管理功能 - 实现评论、反应、相册与智能集合的完整业务逻辑 - 添加离线变更记录与数据同步机制支持冲突解决 - 集成 Redis 缓存配置与用户统计数据聚合 - 创建 8 个业务控制器处理用户交互请求 - 新增 Feign 客户端与故事服务集成 - 补充详细的后端实现与 WebSocket 指南文档 - 更新项目依赖配置支持新增功能模块
6.9 KiB
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:
- CREATED - When a new reaction is added
- UPDATED - When an existing reaction is changed to a different type
- DELETED - When a reaction is removed
Event Payload Structure
{
"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 upLOVE- Heart/loveLAUGH- Laughing faceWOW- Surprised/amazedSAD- Sad face
Frontend Integration
1. Subscribe to Reaction Topic
// 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
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:
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
CREATEDevent for new reactions orUPDATEDevent for changed reactions - removeReaction() - Broadcasts
DELETEDevent 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
- Open two browser windows with the same story/photo
- Add a reaction in window 1
- Verify the reaction appears in window 2 without refresh
- Change the reaction type in window 1
- Verify the change appears in window 2 in real-time
- Remove the reaction in window 1
- 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