Aller au contenu principal

Debugging Runbook - MyTelevision API

Purpose: Guide for diagnosing and resolving common issues in the MyTelevision API.


Table of Contents

  1. Quick Diagnostics
  2. Application Issues
  3. Database Issues
  4. Redis/Cache Issues
  5. Authentication Issues
  6. Performance Issues
  7. Docker/Deployment Issues
  8. API-Specific Issues

Quick Diagnostics

Health Check Commands

# API Health
curl http://localhost:3000/api/v2/health/live
curl http://localhost:3000/api/v2/health/ready

# Database connectivity
npx prisma db pull --force

# Redis connectivity
redis-cli ping

# Docker status
docker-compose ps
docker-compose logs --tail=50 api

Common Environment Issues

# Check environment variables are loaded
node -e "console.log(process.env.DATABASE_URL ? 'DB_URL: Set' : 'DB_URL: MISSING')"
node -e "console.log(process.env.JWT_SECRET ? 'JWT: Set' : 'JWT: MISSING')"
node -e "console.log(process.env.REDIS_PASSWORD ? 'REDIS: Set' : 'REDIS: MISSING')"

# Validate environment
npm run build # Will fail if critical env vars missing

Application Issues

1. Application Won't Start

Symptoms: Error: Cannot find module, EADDRINUSE, startup crashes

Debug Steps:

# 1. Check for port conflicts
netstat -tulpn | grep 3000
# or on Windows:
netstat -ano | findstr :3000

# 2. Verify dependencies
rm -rf node_modules
npm ci

# 3. Regenerate Prisma client
npm run prisma:generate

# 4. Check TypeScript compilation
npm run build

# 5. Run with verbose logging
DEBUG=* npm run start:dev

2. Module Resolution Errors

Symptoms: Cannot resolve @infrastructure/..., path alias errors

Fix:

# Verify tsconfig paths
cat tsconfig.json | grep -A 20 "paths"

# Ensure baseUrl is set
# "baseUrl": "./",
# "paths": {
# "@/*": ["src/*"],
# "@infrastructure/*": ["src/infrastructure/*"],
# ...
# }

# Rebuild
npm run build

3. Validation Pipe Errors

Symptoms: 400 Bad Request with cryptic messages

Debug:

// Add detailed validation error logging
// In main.ts, update ValidationPipe:
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
exceptionFactory: (errors) => {
console.error('Validation errors:', JSON.stringify(errors, null, 2));
return new BadRequestException(errors);
},
}),
);

Database Issues

1. Connection Errors

Symptoms: P1001: Can't reach database server, connection timeout

Debug:

# 1. Verify PostgreSQL is running
docker-compose ps postgres
docker-compose logs postgres --tail=20

# 2. Test connection manually
psql postgresql://mytelevision:mytelevision_secret@localhost:5432/mytelevision

# 3. Check DATABASE_URL format
echo $DATABASE_URL
# Expected: postgresql://user:password@host:port/database?schema=public

# 4. Verify network (Docker)
docker network ls
docker network inspect mytelevision-network

# 5. Check firewall
sudo ufw status

2. Migration Errors

Symptoms: P3006: Migration failed, schema drift

Debug:

# 1. Check migration status
npx prisma migrate status

# 2. Reset database (DEVELOPMENT ONLY!)
npx prisma migrate reset

# 3. Generate migration from schema changes
npx prisma migrate dev --name describe_your_changes

# 4. Apply pending migrations
npx prisma migrate deploy

# 5. If stuck, force resolve
npx prisma migrate resolve --applied "migration_name"

3. Query Performance

Symptoms: Slow API responses, timeout errors

Debug:

# 1. Enable Prisma query logging
# In .env:
# DEBUG=prisma:query

# 2. Check slow queries in PostgreSQL
SELECT query, calls, mean_time, total_time
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;

# 3. Analyze specific query
EXPLAIN ANALYZE SELECT * FROM "Movie" WHERE status = 'PUBLISHED' LIMIT 10;

# 4. Check missing indexes
SELECT relname, seq_scan, idx_scan
FROM pg_stat_user_tables
WHERE seq_scan > idx_scan
ORDER BY seq_scan DESC;

4. Prisma Client Issues

Symptoms: Type errors, outdated client

Fix:

# Regenerate client
npm run prisma:generate

# If types still wrong, clear cache
rm -rf node_modules/.prisma
npm run prisma:generate

# Verify client version matches
npx prisma version

Redis/Cache Issues

1. Connection Errors

Symptoms: ECONNREFUSED, NOAUTH

Debug:

# 1. Verify Redis is running
docker-compose ps redis
docker-compose logs redis --tail=20

# 2. Test connection
redis-cli -a ${REDIS_PASSWORD} ping

# 3. Check connection details
redis-cli -a ${REDIS_PASSWORD} INFO server

# 4. Verify password matches
echo $REDIS_PASSWORD

2. Cache Inconsistency

Symptoms: Stale data, cache not updating

Debug:

# 1. Check specific cache key
redis-cli -a ${REDIS_PASSWORD} GET "cache:movies:list:page1"

# 2. Check TTL
redis-cli -a ${REDIS_PASSWORD} TTL "cache:movies:list:page1"

# 3. Clear specific cache pattern
redis-cli -a ${REDIS_PASSWORD} KEYS "cache:movies:*" | xargs redis-cli -a ${REDIS_PASSWORD} DEL

# 4. Clear all cache (careful!)
redis-cli -a ${REDIS_PASSWORD} FLUSHDB

3. Memory Issues

Symptoms: Redis OOM, eviction warnings

Debug:

# 1. Check memory usage
redis-cli -a ${REDIS_PASSWORD} INFO memory

# 2. Find large keys
redis-cli -a ${REDIS_PASSWORD} --bigkeys

# 3. Check eviction policy
redis-cli -a ${REDIS_PASSWORD} CONFIG GET maxmemory-policy

# 4. Set memory limit
redis-cli -a ${REDIS_PASSWORD} CONFIG SET maxmemory 256mb
redis-cli -a ${REDIS_PASSWORD} CONFIG SET maxmemory-policy allkeys-lru

Authentication Issues

1. JWT Errors

Symptoms: invalid token, jwt expired, jwt malformed

Debug:

# 1. Decode JWT (without verification)
# Install: npm install -g jwt-cli
jwt decode <TOKEN>

# 2. Check token structure
echo "<TOKEN>" | cut -d'.' -f2 | base64 -d 2>/dev/null | jq

# 3. Verify JWT_SECRET is set
node -e "console.log('JWT_SECRET:', process.env.JWT_SECRET?.substring(0,10) + '...')"

# 4. Check token expiration
# In the decoded payload, check "exp" field
# Convert: date -d @<exp_timestamp>

2. Session Not Found

Symptoms: 401 after login, session invalidated

Debug:

# 1. Check session exists in Redis
redis-cli -a ${REDIS_PASSWORD} KEYS "session:*"

# 2. Check session in database
SELECT * FROM "UserSession" WHERE "userId" = '<USER_ID>' ORDER BY "createdAt" DESC LIMIT 5;
SELECT * FROM "AccountSession" WHERE "accountId" = '<ACCOUNT_ID>' ORDER BY "createdAt" DESC LIMIT 5;

# 3. Verify token hash matches
# The stored token is hashed with SHA256
node -e "const crypto = require('crypto'); console.log(crypto.createHash('sha256').update('<TOKEN>').digest('hex'))"

3. Rate Limiting Issues

Symptoms: 429 Too Many Requests

Debug:

# 1. Check rate limit counters
redis-cli -a ${REDIS_PASSWORD} KEYS "throttle:*"

# 2. Get specific counter
redis-cli -a ${REDIS_PASSWORD} GET "throttle:short:<IP>"

# 3. Check TTL
redis-cli -a ${REDIS_PASSWORD} TTL "throttle:short:<IP>"

# 4. Clear rate limit for IP (testing only)
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:short:<IP>"
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:medium:<IP>"
redis-cli -a ${REDIS_PASSWORD} DEL "throttle:long:<IP>"

Performance Issues

1. Slow API Responses

Debug:

# 1. Profile endpoint
time curl -w "@curl-format.txt" -o /dev/null http://localhost:3000/api/v2/movies

# curl-format.txt contents:
# time_namelookup: %{time_namelookup}\n
# time_connect: %{time_connect}\n
# time_appconnect: %{time_appconnect}\n
# time_pretransfer: %{time_pretransfer}\n
# time_redirect: %{time_redirect}\n
# time_starttransfer: %{time_starttransfer}\n
# ----------\n
# time_total: %{time_total}\n

# 2. Check Node.js memory
node -e "console.log(process.memoryUsage())"

# 3. Profile CPU usage
node --prof dist/main.js
# Then analyze:
node --prof-process isolate-*.log > profile.txt

2. Memory Leaks

Debug:

# 1. Take heap snapshot
node --inspect dist/main.js
# Connect Chrome DevTools: chrome://inspect

# 2. Monitor memory over time
while true; do
curl -s http://localhost:3000/api/v2/health/live | jq '.memory'
sleep 60
done

# 3. Check for event listener leaks
node -e "require('events').defaultMaxListeners = 10; process.on('warning', (w) => console.warn(w));"

3. Database Connection Pool Exhaustion

Symptoms: Connection timeout after prolonged use

Debug:

-- Check active connections
SELECT count(*) FROM pg_stat_activity WHERE datname = 'mytelevision';

-- See what's using connections
SELECT pid, usename, application_name, client_addr, state, query
FROM pg_stat_activity
WHERE datname = 'mytelevision';

-- Kill idle connections (careful!)
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'mytelevision'
AND state = 'idle'
AND query_start < NOW() - INTERVAL '10 minutes';

Docker/Deployment Issues

1. Container Won't Start

Debug:

# 1. Check container logs
docker-compose logs api --tail=100

# 2. Check container status
docker-compose ps
docker inspect mytelevision-api

# 3. Check resource limits
docker stats mytelevision-api

# 4. Shell into container
docker exec -it mytelevision-api /bin/sh

# 5. Rebuild from scratch
docker-compose down -v
docker-compose build --no-cache
docker-compose up -d

2. Network Issues

Debug:

# 1. Check network
docker network inspect mytelevision-network

# 2. Test inter-container connectivity
docker exec mytelevision-api ping postgres
docker exec mytelevision-api ping redis

# 3. Check DNS resolution
docker exec mytelevision-api nslookup postgres

3. Volume/Data Persistence

Debug:

# 1. List volumes
docker volume ls | grep mytelevision

# 2. Inspect volume
docker volume inspect mytelevision-api_postgres_data

# 3. Backup volume
docker run --rm -v mytelevision-api_postgres_data:/data -v $(pwd):/backup alpine tar cvf /backup/postgres_backup.tar /data

# 4. Check volume mount
docker inspect mytelevision-postgres | jq '.[0].Mounts'

API-Specific Issues

1. Streaming Token Issues

Symptoms: Invalid stream token, expired token

Debug:

# 1. Generate test stream token
curl -X POST http://localhost:3000/api/v2/streaming/token \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"mediaType": "MOVIE", "contentId": "123"}'

# 2. Verify token
curl -X POST http://localhost:3000/api/v2/streaming/verify \
-H "X-Stream-Token: <STREAM_TOKEN>"

# 3. Check signing secret
node -e "console.log('STREAMING_SIGNING_SECRET:', process.env.STREAMING_SIGNING_SECRET?.substring(0,10) + '...')"

2. TMDb Integration

Symptoms: Movie autofill not working

Debug:

# 1. Test TMDb API directly
curl "https://api.themoviedb.org/3/movie/550?api_key=${TMDB_API_KEY}&language=fr-FR"

# 2. Check API key
node -e "console.log('TMDB_API_KEY:', process.env.TMDB_API_KEY ? 'Set' : 'MISSING')"

# 3. Test search
curl "https://api.themoviedb.org/3/search/movie?api_key=${TMDB_API_KEY}&query=Matrix"

3. i18n/Localization

Symptoms: Wrong language returned

Debug:

# 1. Test with Accept-Language header
curl -H "Accept-Language: en-US" http://localhost:3000/api/v2/movies/1

# 2. Test with query parameter
curl "http://localhost:3000/api/v2/movies/1?lang=en_US"

# 3. Check response header
curl -I http://localhost:3000/api/v2/movies/1 | grep Content-Language

# 4. Verify translation files exist
ls -la src/resources/i18n/

Useful Commands Reference

# Restart everything
docker-compose restart

# View real-time logs
docker-compose logs -f api

# Check disk space
df -h

# Check memory
free -m

# Kill stuck process
pkill -f "node dist/main"

# Prisma studio (GUI)
npx prisma studio

# Generate types
npm run prisma:generate

# Run specific test
npm test -- --testPathPattern="auth"

# Check for outdated packages
npm outdated

# Security audit
npm audit