sojorn/sojorn_docs/reactions-implementation-troubleshooting.md

224 lines
7 KiB
Markdown

# Reactions Feature Implementation & Troubleshooting
## Overview
This document covers the complete implementation and troubleshooting of the reactions feature in the Sojorn application, including both backend (Go) and frontend (Flutter) components.
## Problem Statement
The reactions feature had multiple issues:
1. **Backend 500 errors** when toggling reactions
2. **Frontend not showing reactions** on initial load (showing `null`)
3. **UI not updating immediately** after toggling reactions
4. **Need to refresh page** to see reaction changes
## Backend Issues & Solutions
### Issue 1: pgx.ErrNoRows vs sql.ErrNoRows
**Problem**: The Go backend was using `sql.ErrNoRows` to check for no rows in database queries, but pgx returns `pgx.ErrNoRows`.
**Error**:
```
ERR DEBUG: Failed to check existing reaction - unexpected error error="no rows in result set"
```
**Solution**: Update error handling in `internal/repository/post_repository.go`:
```go
import (
"github.com/jackc/pgx/v5" // Add this import
)
// Change from:
} else if err != sql.ErrNoRows {
// To:
} else if err != pgx.ErrNoRows {
```
### Issue 2: JSON Serialization Omitting Empty Fields
**Problem**: The `Post` model had `omitempty` tags on reaction fields, causing them to be omitted from JSON responses when empty.
**Solution**: Remove `omitempty` from reaction JSON tags in `internal/models/post.go`:
```go
// Before:
Reactions map[string]int `json:"reactions,omitempty"`
MyReactions []string `json:"my_reactions,omitempty"`
ReactionUsers map[string][]string `json:"reaction_users,omitempty"`
// After:
Reactions map[string]int `json:"reactions"`
MyReactions []string `json:"my_reactions"`
ReactionUsers map[string][]string `json:"reaction_users"`
```
## Frontend Issues & Solutions
### Issue 1: UI Not Updating Immediately
**Problem**: The `_reactionCountsFor` and `_myReactionsFor` methods prioritized `post.reactions` over local state, but after toggle reactions, local state had updated data while `post.reactions` still had old data.
**Solution**: Change priority to prefer local state for immediate updates in `lib/screens/post/threaded_conversation_screen.dart`:
```dart
Map<String, int> _reactionCountsFor(Post post) {
// Prefer local state for immediate updates after toggle reactions
final localState = _reactionCountsByPost[post.id];
if (localState != null) {
return localState;
}
// Fall back to post model if no local state
return post.reactions ?? {};
}
Set<String> _myReactionsFor(Post post) {
// Prefer local state for immediate updates after toggle reactions
final localState = _myReactionsByPost[post.id];
if (localState != null) {
return localState;
}
// Fall back to post model if no local state
return post.myReactions?.toSet() ?? <String>{};
}
```
## Implementation Steps
### Backend Implementation
1. **Fix Error Handling**:
```bash
cd go-backend
# Edit internal/repository/post_repository.go
# Add pgx import and change error handling
git add . && git commit -m "Fix ToggleReaction error handling - use pgx.ErrNoRows"
```
2. **Fix JSON Serialization**:
```bash
# Edit internal/models/post.go
# Remove omitempty from reaction fields
git add . && git commit -m "Remove omitempty from reaction JSON fields"
```
3. **Deploy Backend**:
```bash
cd /opt/sojorn/go-backend
git pull origin ThreadRestoration
sudo systemctl stop sojorn-api
go build -o ../bin/api ./cmd/api
sudo systemctl start sojorn-api
```
### Frontend Implementation
1. **Fix UI Update Priority**:
```bash
cd sojorn_app
# Edit lib/screens/post/threaded_conversation_screen.dart
# Update _reactionCountsFor and _myReactionsFor methods
git add . && git commit -m "Fix reaction UI updates - prioritize local state"
```
## Debugging Techniques
### Backend Debugging
1. **Add Debug Logging**:
```go
log.Info().Str("postID", postID).Str("userID", userID).Msg("DEBUG: No existing reaction found (expected)")
log.Error().Err(err).Str("postID", postID).Str("userID", userID).Msg("DEBUG: Failed to check existing reaction - unexpected error")
```
2. **Monitor Logs**:
```bash
sudo tail -f /var/log/syslog | grep api
```
### Frontend Debugging
1. **Add Debug Logging**:
```dart
print('DEBUG: Toggle reaction response: $response');
print('DEBUG: Updated local reaction counts: ${_reactionCountsByPost[postId]}');
print('DEBUG: Using local state: ${localState}');
```
2. **Check API Response**:
```dart
final response = await api.toggleReaction(postId, emoji);
print('DEBUG: API response: $response');
```
## Testing Checklist
### Backend Tests
- [ ] Toggle reaction returns 200 (not 500)
- [ ] Reaction is saved to database
- [ ] API response includes updated counts and user reactions
- [ ] Empty reaction fields return `{}` and `[]` instead of `null`
### Frontend Tests
- [ ] Reactions show on initial load
- [ ] Toggle reaction updates UI immediately
- [ ] No refresh needed to see changes
- [ ] Selected emoji shows as selected
- [ ] Reaction count updates correctly
## Common Issues & Solutions
### Issue: "no rows in result set" Error
**Cause**: Using `sql.ErrNoRows` instead of `pgx.ErrNoRows`
**Fix**: Update error handling to use `pgx.ErrNoRows`
### Issue: Frontend Shows `null` for Reactions
**Cause**: `omitempty` in JSON tags omits empty fields
**Fix**: Remove `omitempty` from reaction field JSON tags
### Issue: UI Not Updating After Toggle
**Cause**: UI prioritizes old post data over updated local state
**Fix**: Change priority to prefer local state for immediate updates
### Issue: Need to Refresh to See Changes
**Cause**: Same as above - UI not using updated local state
**Fix**: Same solution - prioritize local state
## Key Files Modified
### Backend
- `internal/repository/post_repository.go` - Error handling fix
- `internal/models/post.go` - JSON serialization fix
### Frontend
- `lib/screens/post/threaded_conversation_screen.dart` - UI update priority fix
## Verification Commands
### Backend Verification
```bash
# Check if service is running
sudo systemctl status sojorn-api
# Check logs for errors
sudo tail -f /var/log/syslog | grep api
# Test API endpoint
curl -X POST "http://194.238.28.122:8080/api/v1/posts/{post-id}/reactions/toggle" \
-H "Authorization: Bearer {jwt-token}" \
-H "Content-Type: application/json" \
-d '{"emoji": "❤️"}'
```
### Frontend Verification
```bash
# Check Flutter logs
flutter run --verbose
# Look for debug messages
grep "DEBUG:" flutter_logs.txt
```
## Success Criteria
**Backend**: Toggle reactions return 200, no 500 errors
**Frontend**: Reactions show immediately, no refresh needed
**UI**: Selected emojis display correctly
**Data**: Empty reactions show as empty, not null
## Future Improvements
1. **Optimistic Updates**: Implement proper optimistic UI updates
2. **Error Handling**: Better error messages for failed reactions
3. **Performance**: Cache reaction data to reduce API calls
4. **Real-time**: WebSocket updates for live reaction changes