sojorn/sojorn_docs/reactions-implementation-troubleshooting.md

7 KiB

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:

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:

// 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:

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:

    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:

    # Edit internal/models/post.go
    # Remove omitempty from reaction fields
    git add . && git commit -m "Remove omitempty from reaction JSON fields"
    
  3. Deploy Backend:

    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:
    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:

    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:

    sudo tail -f /var/log/syslog | grep api
    

Frontend Debugging

  1. Add Debug Logging:

    print('DEBUG: Toggle reaction response: $response');
    print('DEBUG: Updated local reaction counts: ${_reactionCountsByPost[postId]}');
    print('DEBUG: Using local state: ${localState}');
    
  2. Check API Response:

    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

# 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

# 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