On this page
Developer guide

Recommendation

src/Recommendation/ generates music recommendations using multiple algorithms and stores them for retrieval. It does not own the entities it recommends (artists, genres) — those live in Catalog. This context is purely about computing, persisting, and serving recommendation scores.

Domain Models

Aggregate Root: Recommendation

Property Description
score Numeric relevance score from the source algorithm
sourceType Type of entity that generated the recommendation
sourceId ID of the source entity
targetUser User who receives the recommendation
recommendationType Which algorithm produced this recommendation

Value Objects

Type Kind Description
RecommendationType Enum Classifies the originating algorithm (collaborative, content-based, genre, database relation)

Domain Services

Each domain service implements one recommendation algorithm:

Service Algorithm Description
CollaborativeFilteringCalculator User-based collaborative filtering Finds users with similar taste and recommends what they liked
ContentSimilarityCalculator Content-based similarity Matches entities with overlapping attributes
DatabaseRelationCalculator Relationship-based Uses existing database relations (e.g., same artist, same genre)
GenreSimilarityCalculator Genre overlap scoring Scores entities by shared genre membership

Commands & Handlers

Command Handler Purpose
SaveRecommendationCommand SaveRecommendationHandler Persist a single computed recommendation
GenerateRecommendationsCommand GenerateRecommendationsHandler Run recommendation generation (dispatched by the console command, the admin action and the scheduler)
DeleteRecommendationCommand DeleteRecommendationHandler Remove one recommendation by UUID
DeleteRecommendationsBySourceCommand DeleteRecommendationsBySourceHandler Remove all recommendations originating from a source entity

Scheduled Generation

GenerateRecommendationsCommand implements the Scheduler's SchedulableCommandInterface, with the scheduler parameters mode (full or incremental) and automatic. The initial migration seeds an active scheduled job, Generate recommendations, that dispatches it daily at 04:00 UTC with {"mode":"incremental","automatic":true}.

The handler reads the system setting recommendations.auto_generate (off by default, contributed by RecommendationSettingDefinitions) when a command with automatic: true arrives. While the setting is off, the handler logs at info level and returns skipped: recommendations.auto_generate is off, which the scheduler records as the job's last result. Commands without automatic, from app:recommendation:generate, the admin action or a schedule an administrator creates, always generate. An unknown mode throws instead of falling back to incremental.

The command has no transport route, so the handler runs in the dispatching process: the scheduler worker for scheduled runs. There the CPU process pool is not running, and the handler generates synchronously. An incremental run loads the songs updated in the last seven days; a full run loads every song. Both load every user's listening history, so a full run on a large library can exhaust the scheduler worker's memory or time, which is why the seeded job is incremental.

Queries & Query Handlers

Query Purpose
GetRecommendationQuery Fetch a single recommendation by UUID
GetRecommendationsForUserQuery All recommendations for the authenticated user
GetRecommendationsBySourceQuery Recommendations generated by a specific source entity
GetTargetingRecommendationsQuery Recommendations targeting a specific entity type and ID

Ports

Port Purpose
RecommendationInsightsPortInterface Read access to recommendation insights
RecommendationJobPortInterface Recommendation job lifecycle operations

API Endpoints

All endpoints live under RecommendationController with the /api/recommendations prefix.

Method Path Purpose
GET /api/recommendations List recommendations for the current user (cursor-paginated)
GET /api/recommendations/source/{sourceType}/{sourceId} Recommendations by source entity
GET /api/recommendations/targeting/{targetType}/{targetId} Recommendations targeting a specific entity
POST /api/recommendations Create a recommendation
DELETE /api/recommendations/{uuid} Delete a single recommendation
DELETE /api/recommendations/source/{sourceType}/{sourceId} Delete all recommendations for a source

Cross-Context Relationships

Direction Context Details
Depends on Shared Uuid, PublicId
Depends on Catalog Artist and genre references (read-only)
Depends on Scheduler GenerateRecommendationsCommand is schedulable through the Scheduler Schedulable Contract Deptrac layer
Depends on Shared SystemSettingsPortInterface for recommendations.auto_generate
Depended on by — No contexts depend on Recommendation directly

Infrastructure

Component Type Purpose
RecommendationEntity Doctrine entity ORM entity mapped to the recommendations table
RecommendationRepository Doctrine repository Implements the domain repository interface