Skip to content

Latest commit

 

History

History
185 lines (152 loc) · 7.28 KB

File metadata and controls

185 lines (152 loc) · 7.28 KB

Recommendations Typed API Contract Implementation

Overview

This implementation introduces explicit DTOs for track and artist recommendations with explanation metadata, replacing the previous implicit any-shaped payloads. The changes make the recommendation API contract strongly typed and provide clients with clear information about why items were recommended.

Changes Made

1. Created DTO File

File: backend/src/recommendations/dto/recommendation-response.dto.ts

Created comprehensive DTOs with Swagger/OpenAPI decorators:

  • RecommendationExplanationDto - Explanation metadata for recommendations

    • source: Type of recommendation (popular, collaborative, content-based)
    • reason: Human-readable explanation
    • confidence: Confidence score (0-100)
  • TrackRecommendationDto - Individual track recommendation

    • All track fields (id, title, audioUrl, coverArtUrl, genre, artistId, artistName, score)
    • explanation: Embedded explanation metadata
  • ArtistRecommendationDto - Individual artist recommendation

    • All artist fields (id, artistName, genre, score, trackCount)
    • explanation: Embedded explanation metadata
  • TrackRecommendationsResponseDto - Wrapper for track recommendations list

    • recommendations: Array of track recommendations
    • total: Count of recommendations
    • generatedAt: ISO timestamp
  • ArtistRecommendationsResponseDto - Wrapper for artist recommendations list

    • recommendations: Array of artist recommendations
    • total: Count of recommendations
    • generatedAt: ISO timestamp

2. Updated Service

File: backend/src/recommendations/recommendations.service.ts

Key Changes:

  • Changed return types from any[] to typed DTOs
  • Added buildExplanation() method to generate explanation metadata based on source type
  • Added buildArtistRecommendation() to construct artist recommendations with explanations
  • Added buildTrackRecommendationsResponse() to wrap track recommendations
  • Added buildArtistRecommendationsResponse() to wrap artist recommendations
  • Updated mapTrackRow() to include explanation metadata
  • All internal methods now return strongly typed DTOs

Explanation Logic:

  • Popular: "Trending track popular among all users"
  • Collaborative: "Recommended because users with similar taste also enjoyed this track"
  • Content-based: "Matches your preferred genres and listening patterns"
  • Confidence calculated as min(round((score / 100) * 100), 100)

3. Updated Controller

File: backend/src/recommendations/recommendations.controller.ts

Key Changes:

  • Added explicit return types to all endpoints
  • Added @ApiResponse decorators with DTO types for Swagger documentation
  • getTrackRecommendations() returns TrackRecommendationsResponseDto
  • getArtistRecommendations() returns ArtistRecommendationsResponseDto

4. Updated Cache Service

File: backend/src/recommendations/recommendation-cache.service.ts

Key Changes:

  • Replaced generic CacheEntry with typed CacheEntry<T>
  • Separated caches: trackCache and artistCache with proper typing
  • Updated method signatures to use TrackRecommendationDto[] and ArtistRecommendationDto[]
  • Maintained backward compatibility with existing cache invalidation logic

5. Updated Tests

File: backend/src/recommendations/recommendations.service.spec.ts

Key Changes:

  • Updated all test cases to validate typed response structure
  • Added tests for explanation metadata fields
  • Validates response shape (recommendations, total, generatedAt)
  • Tests for each recommendation source type (popular, collaborative, content-based)
  • Added cache service mock to test suite

6. Created Controller Tests

File: backend/src/recommendations/recommendations.controller.spec.ts

New Test Coverage:

  • Validates controller returns properly typed responses
  • Tests response shape matches DTO contract
  • Validates explanation fields are present and properly typed
  • Tests all recommendation source types
  • Validates confidence is within valid range (0-100)
  • Tests default limit behavior

API Contract Examples

Track Recommendations Response

{
  "recommendations": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "title": "Midnight Dreams",
      "audioUrl": "https://storage.example.com/tracks/audio.mp3",
      "coverArtUrl": "https://storage.example.com/covers/image.jpg",
      "genre": "Afrobeats",
      "artistId": "660e8400-e29b-41d4-a716-446655440001",
      "artistName": "John Doe",
      "score": 42,
      "explanation": {
        "source": "collaborative",
        "reason": "Recommended because users with similar taste also enjoyed this track",
        "confidence": 85
      }
    }
  ],
  "total": 1,
  "generatedAt": "2024-01-15T10:30:00Z"
}

Artist Recommendations Response

{
  "recommendations": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "artistName": "Jane Smith",
      "genre": "Afrobeats",
      "score": 156,
      "trackCount": 5,
      "explanation": {
        "source": "content-based",
        "reason": "Matches your preferred genres and listening patterns",
        "confidence": 100
      }
    }
  ],
  "total": 1,
  "generatedAt": "2024-01-15T10:30:00Z"
}

Benefits

  1. Type Safety: Eliminates implicit any types, providing compile-time type checking
  2. API Documentation: Swagger/OpenAPI automatically generates accurate API documentation
  3. Client Clarity: Clients can understand why recommendations were made
  4. Future Ranking Work: Explanation metadata provides foundation for ranking improvements
  5. Maintainability: Explicit contracts make refactoring safer
  6. Testing: Strongly typed responses are easier to test and validate

Backward Compatibility

The changes maintain the existing scoring logic and recommendation algorithms. The only breaking change is the response structure, which now includes:

  • Wrapper objects with recommendations, total, and generatedAt fields
  • explanation object within each recommendation instead of flat source field

Clients will need to update their response parsing to handle the new structure.

Acceptance Criteria Met

✅ Controller responses use DTOs
✅ Recommendation payloads are strongly typed
✅ Clients can tell why an item was recommended (via explanation metadata)
✅ Unit tests validate response shape and explanation fields
✅ Controller tests validate typed responses
✅ Current scoring logic preserved
✅ Source information exposed (popular, collaborative, content-based)

Files Modified

  1. backend/src/recommendations/recommendations.service.ts
  2. backend/src/recommendations/recommendations.controller.ts
  3. backend/src/recommendations/recommendation-cache.service.ts
  4. backend/src/recommendations/recommendations.service.spec.ts

Files Created

  1. backend/src/recommendations/dto/recommendation-response.dto.ts
  2. backend/src/recommendations/recommendations.controller.spec.ts

Next Steps

To complete the integration:

  1. Install dependencies: npm install (in backend directory)
  2. Run tests: npm test to validate all changes
  3. Update API documentation: The Swagger docs will automatically reflect the new types
  4. Update client applications to handle the new response structure
  5. Consider adding integration tests for the full recommendation flow