Refactir
This commit is contained in:
parent
d0a4e6fd8d
commit
1935fc1a1e
342
LOG_FLOW_ANALYSIS.md
Normal file
342
LOG_FLOW_ANALYSIS.md
Normal file
@ -0,0 +1,342 @@
|
|||||||
|
# Log Flow Analysis - Application Startup & Runtime
|
||||||
|
|
||||||
|
**Date**: 2026-01-01
|
||||||
|
**Log Source**: Application startup and initial page load
|
||||||
|
**Analysis Focus**: Flow patterns, errors, and system behavior
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Executive Summary
|
||||||
|
|
||||||
|
**Overall Status**: 🟡 **MOSTLY HEALTHY** with one non-critical error
|
||||||
|
|
||||||
|
**Key Findings**:
|
||||||
|
1. ⚠️ **Syntax Error**: Non-critical error during startup (doesn't block execution)
|
||||||
|
2. ✅ **Session Management**: Working correctly (5 session callbacks during startup)
|
||||||
|
3. ✅ **Notification Service**: Initialized and functioning (100 total, 66 unread)
|
||||||
|
4. ✅ **External Services**: All connecting successfully
|
||||||
|
5. ⚠️ **No Mark-as-Read Activity**: No API calls to mark notifications as read
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Flow Breakdown
|
||||||
|
|
||||||
|
### Phase 1: Application Startup (Lines 1-33)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Next.js starts (1313ms)
|
||||||
|
2. Redis connection established ✅
|
||||||
|
3. Microsoft OAuth configuration loaded ✅
|
||||||
|
4. ⚠️ SyntaxError: Unexpected identifier 'http' (line 29)
|
||||||
|
5. Redis connection warmed up ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observations**:
|
||||||
|
- ✅ Startup is fast (1.3 seconds)
|
||||||
|
- ✅ Redis connection successful
|
||||||
|
- ⚠️ **Syntax Error** appears but doesn't block execution
|
||||||
|
- Error occurs between Redis warmup calls
|
||||||
|
|
||||||
|
**Syntax Error Details**:
|
||||||
|
```
|
||||||
|
⨯ SyntaxError: Unexpected identifier 'http'
|
||||||
|
at Object.Function [as get] (<anonymous>) {
|
||||||
|
digest: '2421336728'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Analysis**:
|
||||||
|
- Error is in a route handler (Function.get)
|
||||||
|
- Likely related to a route file with syntax issue
|
||||||
|
- Doesn't crash the application
|
||||||
|
- May be related to dynamic route generation
|
||||||
|
|
||||||
|
**Recommendation**: Investigate route files for syntax errors, especially those using `http` in identifiers.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: Initial Session Creation (Lines 34-71)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Session callback triggered
|
||||||
|
2. Token validation ✅
|
||||||
|
3. User roles extracted ✅
|
||||||
|
4. Session created successfully ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
**Session Details**:
|
||||||
|
- User ID: `203cbc91-61ab-47a2-95d2-b5e1159327d7`
|
||||||
|
- Email: `a.tmiri@clm.foundation`
|
||||||
|
- Roles: `['expression', 'entrepreneurship', 'admin', 'dataintelligence', 'mediation', 'mentors']`
|
||||||
|
- Tokens: Access token ✅, Refresh token ✅
|
||||||
|
|
||||||
|
**Status**: ✅ **HEALTHY**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3: Rocket.Chat Integration (Lines 72-91)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Rocket.Chat base URL: https://parole.slm-lab.net ✅
|
||||||
|
2. Users list fetched (13 users) ✅
|
||||||
|
3. User found: aminetmiri ✅
|
||||||
|
4. Subscriptions filtered (1 room) ✅
|
||||||
|
5. Messages fetched (5 messages) ✅
|
||||||
|
6. Messages cached ✅
|
||||||
|
7. ⚠️ "No valid session or email found" (line 92)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observations**:
|
||||||
|
- ✅ Rocket.Chat integration working
|
||||||
|
- ✅ User authentication successful
|
||||||
|
- ✅ Messages retrieved and cached
|
||||||
|
- ⚠️ Warning message at line 92 (may be from another service)
|
||||||
|
|
||||||
|
**Status**: ✅ **HEALTHY** (warning is likely from a different service)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 4: Additional Session Callbacks (Lines 93-169)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Session callback #2 (lines 93-130)
|
||||||
|
2. Session callback #3 (lines 132-169)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Pattern**: Multiple session callbacks during initial page load
|
||||||
|
|
||||||
|
**Frequency**: 3 session callbacks in ~40 lines of log
|
||||||
|
|
||||||
|
**Analysis**:
|
||||||
|
- Normal behavior for Next.js with multiple API routes
|
||||||
|
- Each `getServerSession()` call triggers session callback
|
||||||
|
- All callbacks successful ✅
|
||||||
|
|
||||||
|
**Status**: ✅ **NORMAL** (but verbose logging as discussed)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 5: Notification Service Initialization (Lines 170-246)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. Notification service instance created ✅
|
||||||
|
2. Leantime adapter initialized ✅
|
||||||
|
3. Adapter registered ✅
|
||||||
|
4. getNotificationCount called ✅
|
||||||
|
5. Leantime API called ✅
|
||||||
|
6. Response received (200) ✅
|
||||||
|
7. Notifications parsed ✅
|
||||||
|
8. Count calculated: 100 total, 66 unread ✅
|
||||||
|
9. Counts cached ✅
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notification Details**:
|
||||||
|
- **Total**: 100 notifications
|
||||||
|
- **Unread**: 66 notifications
|
||||||
|
- **Source**: Leantime
|
||||||
|
- **Status**: ✅ **WORKING CORRECTLY**
|
||||||
|
|
||||||
|
**Flow**:
|
||||||
|
```
|
||||||
|
[NOTIFICATION_SERVICE] → [LEANTIME_ADAPTER] → Leantime API → Parse → Cache
|
||||||
|
```
|
||||||
|
|
||||||
|
**Status**: ✅ **HEALTHY**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 6: Additional Operations (Lines 247-289)
|
||||||
|
|
||||||
|
```
|
||||||
|
1. IMAP pool status logged
|
||||||
|
2. Session callback #4 (lines 248-285)
|
||||||
|
3. Cached messages used
|
||||||
|
4. IMAP pool status logged again
|
||||||
|
```
|
||||||
|
|
||||||
|
**Observations**:
|
||||||
|
- ✅ IMAP connection pool healthy (0 active, max 20)
|
||||||
|
- ✅ Session callbacks continuing (normal)
|
||||||
|
- ✅ Caching working (messages from cache)
|
||||||
|
|
||||||
|
**Status**: ✅ **HEALTHY**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔴 Issues Identified
|
||||||
|
|
||||||
|
### 1. Syntax Error (Line 29) ⚠️
|
||||||
|
|
||||||
|
**Error**:
|
||||||
|
```
|
||||||
|
⨯ SyntaxError: Unexpected identifier 'http'
|
||||||
|
at Object.Function [as get] (<anonymous>)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Impact**:
|
||||||
|
- ⚠️ **Low**: Doesn't crash application
|
||||||
|
- ⚠️ **Unknown**: May affect specific route
|
||||||
|
- ⚠️ **Non-blocking**: Application continues normally
|
||||||
|
|
||||||
|
**Possible Causes**:
|
||||||
|
1. Route file with syntax error
|
||||||
|
2. Dynamic route generation issue
|
||||||
|
3. Template literal or string interpolation problem
|
||||||
|
4. Environment variable parsing issue
|
||||||
|
|
||||||
|
**Investigation Steps**:
|
||||||
|
1. Search codebase for routes using `http` as identifier
|
||||||
|
2. Check dynamic route files
|
||||||
|
3. Review route handlers for syntax errors
|
||||||
|
4. Check Next.js route generation
|
||||||
|
|
||||||
|
**Priority**: 🟡 **MEDIUM** - Should be fixed but not blocking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. "No valid session or email found" (Line 92) ⚠️
|
||||||
|
|
||||||
|
**Message**: `No valid session or email found`
|
||||||
|
|
||||||
|
**Context**: Appears after Rocket.Chat operations
|
||||||
|
|
||||||
|
**Analysis**:
|
||||||
|
- May be from a different service/route
|
||||||
|
- Doesn't affect Rocket.Chat functionality
|
||||||
|
- Could be from email service or another API route
|
||||||
|
|
||||||
|
**Investigation**: Check which service logs this message
|
||||||
|
|
||||||
|
**Priority**: 🟡 **LOW** - Appears to be a warning, not an error
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 3. No Mark-as-Read Activity ⚠️
|
||||||
|
|
||||||
|
**Observation**: No `[NOTIFICATION_API]` log entries
|
||||||
|
|
||||||
|
**Expected**: Should see logs when user marks notifications as read
|
||||||
|
|
||||||
|
**Possible Reasons**:
|
||||||
|
1. User hasn't tested mark-as-read yet
|
||||||
|
2. API calls not reaching server
|
||||||
|
3. Client-side errors preventing API calls
|
||||||
|
|
||||||
|
**Status**: ⏳ **PENDING TESTING**
|
||||||
|
|
||||||
|
**Action**: Test mark-as-read functionality and check for new log entries
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## ✅ Positive Observations
|
||||||
|
|
||||||
|
### 1. Fast Startup
|
||||||
|
- ✅ Application ready in 1.3 seconds
|
||||||
|
- ✅ All services initialized quickly
|
||||||
|
|
||||||
|
### 2. Session Management
|
||||||
|
- ✅ All session callbacks successful
|
||||||
|
- ✅ Token validation working
|
||||||
|
- ✅ User roles extracted correctly
|
||||||
|
|
||||||
|
### 3. Notification Service
|
||||||
|
- ✅ Service initialized correctly
|
||||||
|
- ✅ Leantime adapter working
|
||||||
|
- ✅ API calls successful
|
||||||
|
- ✅ Caching functioning
|
||||||
|
|
||||||
|
### 4. External Services
|
||||||
|
- ✅ Redis connected
|
||||||
|
- ✅ Rocket.Chat connected
|
||||||
|
- ✅ Leantime API responding
|
||||||
|
- ✅ IMAP pool healthy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📈 Performance Metrics
|
||||||
|
|
||||||
|
| Metric | Value | Status |
|
||||||
|
|--------|-------|--------|
|
||||||
|
| Startup Time | 1313ms | ✅ Good |
|
||||||
|
| Redis Connection | ✅ Success | ✅ Good |
|
||||||
|
| Session Callbacks | 5 during startup | ✅ Normal |
|
||||||
|
| Notification Count | 100 total, 66 unread | ✅ Working |
|
||||||
|
| Rocket.Chat | ✅ Connected | ✅ Good |
|
||||||
|
| IMAP Pool | 0/20 active | ✅ Healthy |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔄 Flow Patterns
|
||||||
|
|
||||||
|
### Session Callback Pattern
|
||||||
|
```
|
||||||
|
Every getServerSession() call → Session callback → Token validation → Session created
|
||||||
|
```
|
||||||
|
|
||||||
|
**Frequency**: 5 times during startup (normal for multi-route page)
|
||||||
|
|
||||||
|
**Recommendation**: Conditional logging (as discussed in impact analysis)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Notification Service Pattern
|
||||||
|
```
|
||||||
|
Service init → Adapter registration → API call → Parse → Cache
|
||||||
|
```
|
||||||
|
|
||||||
|
**Status**: ✅ Working correctly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Recommendations
|
||||||
|
|
||||||
|
### Immediate Actions
|
||||||
|
|
||||||
|
1. **Investigate Syntax Error** 🔴
|
||||||
|
- Search for route files with `http` identifier
|
||||||
|
- Check dynamic routes
|
||||||
|
- Fix syntax error
|
||||||
|
|
||||||
|
2. **Test Mark-as-Read** 🟡
|
||||||
|
- Mark a notification as read
|
||||||
|
- Check logs for `[NOTIFICATION_API]` entries
|
||||||
|
- Verify notification count updates
|
||||||
|
|
||||||
|
3. **Identify "No valid session" Source** 🟡
|
||||||
|
- Find which service logs this message
|
||||||
|
- Determine if it's an error or warning
|
||||||
|
- Fix if necessary
|
||||||
|
|
||||||
|
### Future Improvements
|
||||||
|
|
||||||
|
4. **Implement Conditional Session Logging** (as planned)
|
||||||
|
- Add `DEBUG_SESSION` flag
|
||||||
|
- Reduce production logging
|
||||||
|
- Keep error logging
|
||||||
|
|
||||||
|
5. **Add Error Monitoring**
|
||||||
|
- Track syntax errors
|
||||||
|
- Monitor route handler failures
|
||||||
|
- Alert on critical errors
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Summary
|
||||||
|
|
||||||
|
**Overall Assessment**: 🟢 **HEALTHY** with minor issues
|
||||||
|
|
||||||
|
**Critical Issues**: 0
|
||||||
|
**Warnings**: 2 (syntax error, "no valid session" message)
|
||||||
|
**Working Correctly**: ✅ All core functionality
|
||||||
|
|
||||||
|
**Next Steps**:
|
||||||
|
1. Fix syntax error (investigate route files)
|
||||||
|
2. Test mark-as-read functionality
|
||||||
|
3. Identify source of "no valid session" message
|
||||||
|
4. Proceed with conditional session logging (when ready)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Generated**: 2026-01-01
|
||||||
|
**Status**: Ready for action items
|
||||||
|
|
||||||
194
NOTIFICATION_ISSUES_FIX.md
Normal file
194
NOTIFICATION_ISSUES_FIX.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# Notification Issues - Analysis & Fixes
|
||||||
|
|
||||||
|
**Date**: 2026-01-01
|
||||||
|
**Issues Reported**:
|
||||||
|
1. Count shows 66 messages, but only 10 are displayed
|
||||||
|
2. "Mark all as read" fails
|
||||||
|
3. Count doesn't update after marking as read
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Issue Analysis
|
||||||
|
|
||||||
|
### Issue 1: Count vs Display Discrepancy
|
||||||
|
|
||||||
|
**Symptom**:
|
||||||
|
- Badge shows: **66 unread notifications**
|
||||||
|
- Dropdown shows: **Only 10 notifications**
|
||||||
|
|
||||||
|
**Root Cause**:
|
||||||
|
1. **Count Logic**: `getNotificationCount()` calls `getNotifications(userId, 1, 100)` to count
|
||||||
|
- Gets first 100 notifications from Leantime
|
||||||
|
- Counts unread: 66
|
||||||
|
- This is correct for the first 100 notifications
|
||||||
|
|
||||||
|
2. **Display Logic**: `getNotifications()` is called with `limit: 20` (default)
|
||||||
|
- But only 10 are shown (possibly due to pagination or filtering)
|
||||||
|
- This is a display/pagination issue
|
||||||
|
|
||||||
|
**The Problem**:
|
||||||
|
- If Leantime has more than 100 notifications total, the count will be inaccurate
|
||||||
|
- The count only reflects the first 100 notifications
|
||||||
|
- Display shows fewer notifications than the count
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
- ✅ Added warning log when count reaches 100 (may have more)
|
||||||
|
- ⚠️ Consider using a dedicated count API if Leantime provides one
|
||||||
|
- ⚠️ Consider fetching all notifications for accurate count (may be slow)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Issue 2: Mark All As Read Fails
|
||||||
|
|
||||||
|
**Symptom**:
|
||||||
|
```
|
||||||
|
[NOTIFICATION_API] Mark all as read - Failed { userId: '...', duration: '197ms' }
|
||||||
|
```
|
||||||
|
|
||||||
|
**Root Cause**:
|
||||||
|
- Leantime API call is failing
|
||||||
|
- No detailed error logging to see why
|
||||||
|
|
||||||
|
**Solution Applied**:
|
||||||
|
- ✅ Added comprehensive error logging to `markAllAsRead()`:
|
||||||
|
- Logs user email and Leantime user ID
|
||||||
|
- Logs request body and API URL
|
||||||
|
- Logs response status and body
|
||||||
|
- Logs parsed response with error details
|
||||||
|
- Logs exceptions with stack traces
|
||||||
|
|
||||||
|
**Next Steps**:
|
||||||
|
1. Test mark-all-as-read again
|
||||||
|
2. Check logs for detailed error information
|
||||||
|
3. Verify Leantime API method name is correct
|
||||||
|
4. Check if Leantime API requires different parameters
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Fixes Applied
|
||||||
|
|
||||||
|
### 1. Enhanced Error Logging in `markAllAsRead`
|
||||||
|
|
||||||
|
**File**: `lib/services/notifications/leantime-adapter.ts`
|
||||||
|
|
||||||
|
**Changes**:
|
||||||
|
- Added detailed logging at each step
|
||||||
|
- Logs request details (body, URL)
|
||||||
|
- Logs response details (status, body, parsed data)
|
||||||
|
- Logs errors with full context
|
||||||
|
- Logs success/failure status
|
||||||
|
|
||||||
|
**Expected Log Output**:
|
||||||
|
```
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead called for ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - User email: ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Leantime user ID: ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Request body: {...}
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - API URL: ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Response status: 200
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Response body: {...}
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Parsed response: {...}
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Success: true/false
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 2. Enhanced Count Logging
|
||||||
|
|
||||||
|
**File**: `lib/services/notifications/leantime-adapter.ts`
|
||||||
|
|
||||||
|
**Changes**:
|
||||||
|
- Added warning when count reaches 100 (may have more notifications)
|
||||||
|
- Added read count to logging
|
||||||
|
- Added note about potential inaccuracy
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
### Immediate Testing
|
||||||
|
|
||||||
|
1. **Test Mark All As Read**
|
||||||
|
- Click "Mark all as read"
|
||||||
|
- Check logs for detailed error information
|
||||||
|
- Look for `[LEANTIME_ADAPTER] markAllAsRead` entries
|
||||||
|
|
||||||
|
2. **Verify Count Accuracy**
|
||||||
|
- Check if Leantime has more than 100 notifications
|
||||||
|
- Verify count matches actual unread notifications
|
||||||
|
- Check if count updates after marking as read
|
||||||
|
|
||||||
|
### Potential Issues to Check
|
||||||
|
|
||||||
|
1. **Leantime API Method Name**
|
||||||
|
- Current: `leantime.rpc.Notifications.Notifications.markAllNotificationsAsRead`
|
||||||
|
- Verify this is the correct method name in Leantime API
|
||||||
|
|
||||||
|
2. **Leantime API Parameters**
|
||||||
|
- Current: `{ userId: leantimeUserId }`
|
||||||
|
- May need additional parameters
|
||||||
|
|
||||||
|
3. **Leantime API Response Format**
|
||||||
|
- Check if response format matches expected format
|
||||||
|
- May need to handle different response structures
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📊 Expected Behavior After Fixes
|
||||||
|
|
||||||
|
### Mark All As Read
|
||||||
|
|
||||||
|
**Success Case**:
|
||||||
|
```
|
||||||
|
[NOTIFICATION_API] Mark all as read endpoint called
|
||||||
|
[NOTIFICATION_API] Mark all as read - Processing { userId: '...', timestamp: '...' }
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead called for ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Success: true
|
||||||
|
[NOTIFICATION_API] Mark all as read - Success { userId: '...', duration: 'Xms' }
|
||||||
|
[NOTIFICATION_SERVICE] Invalidated notification caches for user ...
|
||||||
|
```
|
||||||
|
|
||||||
|
**Failure Case** (with detailed error):
|
||||||
|
```
|
||||||
|
[NOTIFICATION_API] Mark all as read endpoint called
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead called for ...
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Response status: 400
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - Response body: {"error": {...}}
|
||||||
|
[LEANTIME_ADAPTER] markAllAsRead - API Error: {...}
|
||||||
|
[NOTIFICATION_API] Mark all as read - Failed { userId: '...', duration: 'Xms' }
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔍 Debugging Checklist
|
||||||
|
|
||||||
|
When testing, check logs for:
|
||||||
|
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - User email:` (should show email)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Leantime user ID:` (should show ID)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Request body:` (should show JSON-RPC request)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Response status:` (should be 200 for success)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Response body:` (should show API response)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Parsed response:` (should show result/error)
|
||||||
|
- [ ] `[LEANTIME_ADAPTER] markAllAsRead - Success:` (should be true/false)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 📝 Summary
|
||||||
|
|
||||||
|
**Fixes Applied**:
|
||||||
|
1. ✅ Enhanced error logging in `markAllAsRead`
|
||||||
|
2. ✅ Enhanced count logging with warnings
|
||||||
|
|
||||||
|
**Next Actions**:
|
||||||
|
1. Test mark-all-as-read functionality
|
||||||
|
2. Review detailed error logs
|
||||||
|
3. Fix Leantime API call based on error details
|
||||||
|
4. Verify count accuracy
|
||||||
|
|
||||||
|
**Status**: ⏳ **AWAITING TESTING** - Enhanced logging will reveal the root cause
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Generated**: 2026-01-01
|
||||||
|
|
||||||
288
Untitled
Normal file
288
Untitled
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
alma@central:~/nextgen/NeahNew$ sudo npm start
|
||||||
|
|
||||||
|
> neah@0.1.0 start
|
||||||
|
> next start
|
||||||
|
|
||||||
|
▲ Next.js 15.3.1
|
||||||
|
- Local: http://localhost:3000
|
||||||
|
- Network: http://172.16.0.102:3000
|
||||||
|
|
||||||
|
✓ Starting...
|
||||||
|
✓ Ready in 1313ms
|
||||||
|
Connecting to Redis using environment variables
|
||||||
|
Microsoft OAuth Configuration: {
|
||||||
|
tenantId: 'cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2',
|
||||||
|
authorizeUrl: 'https://login.microsoftonline.com/cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2/oauth2/v2.0/authorize',
|
||||||
|
tokenUrl: 'https://login.microsoftonline.com/cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2/oauth2/v2.0/token',
|
||||||
|
clientIdFirstChars: 'afaff...',
|
||||||
|
redirectUri: 'https://hub.slm-lab.net/ms'
|
||||||
|
}
|
||||||
|
Microsoft OAuth Configuration: {
|
||||||
|
tenantId: 'cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2',
|
||||||
|
authorizeUrl: 'https://login.microsoftonline.com/cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2/oauth2/v2.0/authorize',
|
||||||
|
tokenUrl: 'https://login.microsoftonline.com/cb4281a9-4a3e-4ff5-9a85-8425dd04e2b2/oauth2/v2.0/token',
|
||||||
|
clientIdFirstChars: 'afaff...',
|
||||||
|
redirectUri: 'https://hub.slm-lab.net/ms'
|
||||||
|
}
|
||||||
|
Successfully connected to Redis
|
||||||
|
Redis connection warmed up
|
||||||
|
⨯ SyntaxError: Unexpected identifier 'http'
|
||||||
|
at Object.Function [as get] (<anonymous>) {
|
||||||
|
digest: '2421336728'
|
||||||
|
}
|
||||||
|
Redis connection warmed up
|
||||||
|
=== SESSION CALLBACK START ===
|
||||||
|
Token error: undefined
|
||||||
|
Has accessToken: true
|
||||||
|
Has refreshToken: true
|
||||||
|
Token role: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Token sub: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Token email: a.tmiri@clm.foundation
|
||||||
|
Token name: Amine TMIRI
|
||||||
|
Token username: aminetmiri
|
||||||
|
User roles for session: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Creating session user object...
|
||||||
|
Setting session tokens...
|
||||||
|
✅ Session created successfully
|
||||||
|
Session user id: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Session user email: a.tmiri@clm.foundation
|
||||||
|
Session user roles: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
=== SESSION CALLBACK END ===
|
||||||
|
Using Rocket.Chat base URL: https://parole.slm-lab.net
|
||||||
|
Users list response: { success: true, count: 13, usersCount: 13 }
|
||||||
|
Found Rocket.Chat user: { username: 'aminetmiri', id: 'a9HwLtHagiRnTWeS5' }
|
||||||
|
Filtered user subscriptions: {
|
||||||
|
userId: 'a9HwLtHagiRnTWeS5',
|
||||||
|
username: 'aminetmiri',
|
||||||
|
totalSubscriptions: 1,
|
||||||
|
subscriptionDetails: [
|
||||||
|
{
|
||||||
|
type: 'd',
|
||||||
|
name: 'Rocket.Cat',
|
||||||
|
rid: 'a9HwLtHagiRnTWeS5rocket.cat',
|
||||||
|
alert: true,
|
||||||
|
unread: 3,
|
||||||
|
userMentions: 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
Messages for room Rocket.Cat: { success: true, count: 5, hasMessages: true }
|
||||||
|
Messages data cached for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
No valid session or email found
|
||||||
|
=== SESSION CALLBACK START ===
|
||||||
|
Token error: undefined
|
||||||
|
Has accessToken: true
|
||||||
|
Has refreshToken: true
|
||||||
|
Token role: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Token sub: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Token email: a.tmiri@clm.foundation
|
||||||
|
Token name: Amine TMIRI
|
||||||
|
Token username: aminetmiri
|
||||||
|
User roles for session: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Creating session user object...
|
||||||
|
Setting session tokens...
|
||||||
|
✅ Session created successfully
|
||||||
|
Session user id: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Session user email: a.tmiri@clm.foundation
|
||||||
|
Session user roles: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
=== SESSION CALLBACK END ===
|
||||||
|
Using cached messages data for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
=== SESSION CALLBACK START ===
|
||||||
|
Token error: undefined
|
||||||
|
Has accessToken: true
|
||||||
|
Has refreshToken: true
|
||||||
|
Token role: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Token sub: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Token email: a.tmiri@clm.foundation
|
||||||
|
Token name: Amine TMIRI
|
||||||
|
Token username: aminetmiri
|
||||||
|
User roles for session: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Creating session user object...
|
||||||
|
Setting session tokens...
|
||||||
|
✅ Session created successfully
|
||||||
|
Session user id: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Session user email: a.tmiri@clm.foundation
|
||||||
|
Session user roles: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
=== SESSION CALLBACK END ===
|
||||||
|
[NOTIFICATION_SERVICE] Creating new notification service instance
|
||||||
|
[NOTIFICATION_SERVICE] Initializing notification service
|
||||||
|
[LEANTIME_ADAPTER] Initialized with API URL and token
|
||||||
|
[NOTIFICATION_SERVICE] Registered notification adapter: leantime
|
||||||
|
[NOTIFICATION_SERVICE] Registered adapters: [ 'leantime' ]
|
||||||
|
[NOTIFICATION_SERVICE] getNotificationCount called for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
[NOTIFICATION_SERVICE] Fetching notification counts for user 203cbc91-61ab-47a2-95d2-b5e1159327d7 from 1 adapters
|
||||||
|
[NOTIFICATION_SERVICE] Available adapters for count: leantime
|
||||||
|
[NOTIFICATION_SERVICE] Checking if adapter leantime is configured for count
|
||||||
|
[NOTIFICATION_SERVICE] Adapter leantime is configured for count: true
|
||||||
|
[NOTIFICATION_SERVICE] Fetching notification count from leantime for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
[LEANTIME_ADAPTER] getNotificationCount called for userId: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
[LEANTIME_ADAPTER] getNotifications called for userId: 203cbc91-61ab-47a2-95d2-b5e1159327d7, page: 1, limit: 100
|
||||||
|
=== SESSION CALLBACK START ===
|
||||||
|
Token error: undefined
|
||||||
|
Has accessToken: true
|
||||||
|
Has refreshToken: true
|
||||||
|
Token role: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Token sub: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Token email: a.tmiri@clm.foundation
|
||||||
|
Token name: Amine TMIRI
|
||||||
|
Token username: aminetmiri
|
||||||
|
User roles for session: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Creating session user object...
|
||||||
|
Setting session tokens...
|
||||||
|
✅ Session created successfully
|
||||||
|
Session user id: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Session user email: a.tmiri@clm.foundation
|
||||||
|
Session user roles: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
=== SESSION CALLBACK END ===
|
||||||
|
[LEANTIME_ADAPTER] Retrieved email from session: a.tmiri@clm.foundation
|
||||||
|
[LEANTIME_ADAPTER] Retrieved Leantime userId for email a.tmiri@clm.foundation: 2
|
||||||
|
[LEANTIME_ADAPTER] Sending request to get all notifications
|
||||||
|
[LEANTIME_ADAPTER] Request body: {"jsonrpc":"2.0","method":"leantime.rpc.Notifications.Notifications.getAllNotifications","params":{"userId":2,"showNewOnly":0,"limitStart":0,"limitEnd":100,"filterOptions":[]},"id":1}
|
||||||
|
[LEANTIME_ADAPTER] Response status: 200
|
||||||
|
[LEANTIME_ADAPTER] Raw response (truncated): {"jsonrpc":"2.0","result":[{"id":2732,"0":2732,"userId":2,"1":2,"read":0,"2":0,"type":"projectUpdate","3":"projectUpdate","module":"tickets","4":"tickets","moduleId":225,"5":225,"datetime":"2025-12-24...
|
||||||
|
[LEANTIME_ADAPTER] Parsed response data: {
|
||||||
|
hasResult: true,
|
||||||
|
resultIsArray: true,
|
||||||
|
resultLength: 100,
|
||||||
|
error: undefined
|
||||||
|
}
|
||||||
|
[LEANTIME_ADAPTER] Transformed notifications count: 100
|
||||||
|
[LEANTIME_ADAPTER] Notification counts: { total: 100, unread: 66 }
|
||||||
|
[NOTIFICATION_SERVICE] Got count from leantime: {
|
||||||
|
total: 100,
|
||||||
|
unread: 66,
|
||||||
|
sources: { leantime: { total: 100, unread: 66 } }
|
||||||
|
}
|
||||||
|
[NOTIFICATION_SERVICE] Adding counts from leantime: total=100, unread=66
|
||||||
|
[NOTIFICATION_SERVICE] Aggregated counts for user 203cbc91-61ab-47a2-95d2-b5e1159327d7: {
|
||||||
|
total: 100,
|
||||||
|
unread: 66,
|
||||||
|
sources: { leantime: { total: 100, unread: 66 } }
|
||||||
|
}
|
||||||
|
[NOTIFICATION_SERVICE] Cached notification counts for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
[IMAP POOL] Size: 0, Active: 0, Connecting: 0, Max: 20
|
||||||
|
=== SESSION CALLBACK START ===
|
||||||
|
Token error: undefined
|
||||||
|
Has accessToken: true
|
||||||
|
Has refreshToken: true
|
||||||
|
Token role: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Token sub: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Token email: a.tmiri@clm.foundation
|
||||||
|
Token name: Amine TMIRI
|
||||||
|
Token username: aminetmiri
|
||||||
|
User roles for session: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
Creating session user object...
|
||||||
|
Setting session tokens...
|
||||||
|
✅ Session created successfully
|
||||||
|
Session user id: 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
Session user email: a.tmiri@clm.foundation
|
||||||
|
Session user roles: [
|
||||||
|
'expression',
|
||||||
|
'entrepreneurship',
|
||||||
|
'admin',
|
||||||
|
'dataintelligence',
|
||||||
|
'mediation',
|
||||||
|
'mentors'
|
||||||
|
]
|
||||||
|
=== SESSION CALLBACK END ===
|
||||||
|
Using cached messages data for user 203cbc91-61ab-47a2-95d2-b5e1159327d7
|
||||||
|
[IMAP POOL] Size: 0, Active: 0, Connecting: 0, Max: 20
|
||||||
|
|
||||||
@ -123,6 +123,8 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Get all notifications and count them
|
// Get all notifications and count them
|
||||||
|
// NOTE: This only gets first 100 notifications. If there are more, the count will be inaccurate.
|
||||||
|
// TODO: Consider using a dedicated count API endpoint if Leantime provides one
|
||||||
const notifications = await this.getNotifications(userId, 1, 100); // Get up to 100 for counting
|
const notifications = await this.getNotifications(userId, 1, 100); // Get up to 100 for counting
|
||||||
|
|
||||||
// Count total and unread
|
// Count total and unread
|
||||||
@ -131,7 +133,9 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
|
|
||||||
console.log('[LEANTIME_ADAPTER] Notification counts:', {
|
console.log('[LEANTIME_ADAPTER] Notification counts:', {
|
||||||
total: totalCount,
|
total: totalCount,
|
||||||
unread: unreadCount
|
unread: unreadCount,
|
||||||
|
read: totalCount - unreadCount,
|
||||||
|
note: totalCount === 100 ? 'WARNING: May have more than 100 notifications total' : 'OK'
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -219,15 +223,17 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
// Get user email and ID
|
// Get user email and ID
|
||||||
const email = await this.getUserEmail();
|
const email = await this.getUserEmail();
|
||||||
if (!email) {
|
if (!email) {
|
||||||
console.error('[LEANTIME_ADAPTER] Could not get user email from session');
|
console.error('[LEANTIME_ADAPTER] markAllAsRead - Could not get user email from session');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - User email: ${email}`);
|
||||||
|
|
||||||
const leantimeUserId = await this.getLeantimeUserId(email);
|
const leantimeUserId = await this.getLeantimeUserId(email);
|
||||||
if (!leantimeUserId) {
|
if (!leantimeUserId) {
|
||||||
console.error('[LEANTIME_ADAPTER] User not found in Leantime:', email);
|
console.error('[LEANTIME_ADAPTER] markAllAsRead - User not found in Leantime:', email);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Leantime user ID: ${leantimeUserId}`);
|
||||||
|
|
||||||
// Make request to Leantime API to mark all notifications as read
|
// Make request to Leantime API to mark all notifications as read
|
||||||
const jsonRpcBody = {
|
const jsonRpcBody = {
|
||||||
@ -239,6 +245,9 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
id: 1
|
id: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Request body:`, JSON.stringify(jsonRpcBody));
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - API URL: ${this.apiUrl}/api/jsonrpc`);
|
||||||
|
|
||||||
const response = await fetch(`${this.apiUrl}/api/jsonrpc`, {
|
const response = await fetch(`${this.apiUrl}/api/jsonrpc`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -248,15 +257,44 @@ export class LeantimeAdapter implements NotificationAdapter {
|
|||||||
body: JSON.stringify(jsonRpcBody)
|
body: JSON.stringify(jsonRpcBody)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Response status: ${response.status}`);
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error(`[LEANTIME_ADAPTER] Failed to mark all notifications as read: ${response.status}`);
|
const errorText = await response.text();
|
||||||
|
console.error(`[LEANTIME_ADAPTER] markAllAsRead - HTTP Error ${response.status}:`, errorText.substring(0, 500));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const responseText = await response.text();
|
||||||
return data.result === true || data.result === "true" || !!data.result;
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Response body:`, responseText.substring(0, 500));
|
||||||
|
|
||||||
|
let data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(responseText);
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error(`[LEANTIME_ADAPTER] markAllAsRead - Failed to parse response:`, parseError);
|
||||||
|
console.error(`[LEANTIME_ADAPTER] markAllAsRead - Raw response:`, responseText);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Parsed response:`, {
|
||||||
|
hasResult: 'result' in data,
|
||||||
|
result: data.result,
|
||||||
|
hasError: 'error' in data,
|
||||||
|
error: data.error
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data.error) {
|
||||||
|
console.error(`[LEANTIME_ADAPTER] markAllAsRead - API Error:`, data.error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const success = data.result === true || data.result === "true" || !!data.result;
|
||||||
|
console.log(`[LEANTIME_ADAPTER] markAllAsRead - Success: ${success}`);
|
||||||
|
return success;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[LEANTIME_ADAPTER] Error marking all notifications as read:', error);
|
console.error('[LEANTIME_ADAPTER] markAllAsRead - Exception:', error);
|
||||||
|
console.error('[LEANTIME_ADAPTER] markAllAsRead - Error stack:', error instanceof Error ? error.stack : 'No stack');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user