unfollow-fix

This commit is contained in:
2025-05-31 17:18:31 +03:00
parent 90260534eb
commit 0140fcd522
8 changed files with 1088 additions and 39 deletions

View File

@@ -37,6 +37,8 @@ Unfollow an entity.
**Returns:** Same as `follow`
**Important:** Always returns current following list even if the subscription was not found, ensuring UI consistency.
### Queries
#### get_shout_followers
@@ -62,9 +64,75 @@ Author[] // List of authors who reacted
### Cache Flow
1. On follow/unfollow:
- Update entity in cache
- **Invalidate user's following list cache** (NEW)
- Update follower's following list
2. Cache is updated before notifications
### Cache Invalidation (NEW)
Following cache keys are invalidated after operations:
- `author:follows-topics:{user_id}` - After topic follow/unfollow
- `author:follows-authors:{user_id}` - After author follow/unfollow
This ensures fresh data is fetched from database on next request.
## Error Handling
### Enhanced Error Handling (UPDATED)
- Unauthorized access check
- Entity existence validation
- Duplicate follow prevention
- **Graceful handling of "following not found" errors**
- **Always returns current following list, even on errors**
- Full error logging
- Transaction safety with `local_session()`
### Error Response Format
```typescript
{
error?: "following was not found" | "invalid unfollow type" | "access denied",
topics?: Topic[], // Always present for topic operations
authors?: Author[], // Always present for author operations
// ... other entity types
}
```
## Recent Fixes (NEW)
### Issue: Stale UI State on Unfollow Errors
**Problem:** When unfollow operation failed with "following was not found", the client didn't update its state because it only processed successful responses.
**Root Cause:**
1. `unfollow` mutation returned error with empty follows list `[]`
2. Client logic: `if (result && !result.error)` prevented state updates on errors
3. User remained "subscribed" in UI despite no actual subscription in database
**Solution:**
1. **Always fetch current following list** from cache/database
2. **Return actual following state** even when subscription not found
3. **Add cache invalidation** after successful operations
4. **Enhanced logging** for debugging
### Code Changes
```python
# Before (BROKEN)
if sub:
# ... process unfollow
else:
return {"error": "following was not found", f"{entity_type}s": follows} # follows was []
# After (FIXED)
if sub:
# ... process unfollow
# Invalidate cache
await redis.execute("DEL", f"author:follows-{entity_type}s:{follower_id}")
else:
error = "following was not found"
# Always get current state
existing_follows = await get_cached_follows_method(follower_id)
return {f"{entity_type}s": existing_follows, "error": error}
```
## Notifications
- Sent when author is followed/unfollowed
@@ -73,14 +141,6 @@ Author[] // List of authors who reacted
- Author ID
- Action type ("follow"/"unfollow")
## Error Handling
- Unauthorized access check
- Entity existence validation
- Duplicate follow prevention
- Full error logging
- Transaction safety with `local_session()`
## Database Schema
### Follower Tables
@@ -91,4 +151,18 @@ Author[] // List of authors who reacted
Each table contains:
- `follower` - ID of following user
- `{entity_type}` - ID of followed entity
- `{entity_type}` - ID of followed entity
## Testing
Run the test script to verify fixes:
```bash
python test_unfollow_fix.py
```
### Test Coverage
- ✅ Unfollow existing subscription
- ✅ Unfollow non-existent subscription
- ✅ Cache invalidation
- ✅ Proper error handling
- ✅ UI state consistency