Skip to content

SquadImporter

Imports squad rosters (team-by-season player, coach, and staff lists) from the foundry.squads ClickHouse table into the SquadAggregate. Resolves provider IDs to LuckBox canonical IDs, groups rows by team and season, and reconciles each squad declaratively so the read model matches the feed exactly.

This importer is driven automatically by SquadImportTimerService, which polls hourly for AmericanFootball/ESPN. It can also be triggered on demand via the import API.

Importer Details

Property Value
Importer Name Squad
Data Contract SquadImportData
Module LBS.Sport.Integration
Authorization Requires ContentManager role (same as the squad commands it issues)
Commands Generated CreateSquadCommand, SetSquadListCommand (one of each per team/season group)
Event Raised SquadCreated, SquadListAdded (and reconcile events: SquadMemberAdded, SquadMemberRemoved, SquadMemberTierUpdated, SquadMemberJerseyUpdated, SquadMemberPositionUpdated)

Input Contract

Field Type Required Description
Sport Sport Yes The sport to import squads for e.g. AmericanFootball
DataProvider DataProvider Yes The provider feed to read e.g. ESPN

Behaviour

  1. Reads all squad rows from the foundry.squads ClickHouse table for the requested sport and provider
  2. For each row, resolves the canonical LuckBox IDs via IEntityMappingService:
  3. team_provider_id -> canonical TeamId
  4. participant_provider_id -> canonical ParticipantId
  5. season_provider_id (a composite "competitionId/year") -> canonical SeasonId
  6. Skips any row whose team, participant, or season cannot be resolved, logging a warning (a bare year with no competition prefix is treated as unresolvable and skipped)
  7. Maps the row fields onto squad member attributes:
  8. squad_tier -> NflSquadTiers.*
  9. position abbreviation -> Positions.AmericanFootball.* (via MapPosition)
  10. jersey string -> int
  11. Groups the surviving rows by (team_provider_id, season_provider_id) — one group per squad
  12. For each group, emits exactly two commands:
  13. CreateSquadCommand - ensures the SquadAggregate exists for the deterministic SquadId.From(SeasonId, TeamId)
  14. SetSquadListCommand - submits the full resolved roster for declarative reconciliation
  15. SetSquadListCommand reconciles the roster against the current squad state: new members are added, omitted members are removed, and changed members (tier, jersey, position) are updated. The operation is idempotent, so re-running the importer against an unchanged feed produces no further events.

ID Resolution Chain

foundry.squads row (provider IDs)
    -> IEntityMappingService
    -> TeamId          (from team_provider_id)
    -> ParticipantId   (from participant_provider_id)
    -> SeasonId        (from season_provider_id == "competitionId/year")
    -> grouped by (TeamId, SeasonId)
    -> SquadId.From(SeasonId, TeamId)

Rows with any unresolved canonical ID are skipped and logged; a season_provider_id that is a bare year (no competitionId/ prefix) cannot be resolved and is skipped.

File Description
src/Integration/LBS.Sport.Integration/Importers/Squad/SquadImporter.cs Importer implementation
src/Integration/LBS.Sport.Integration/Importers/Squad/SquadImportTimerService.cs Automated hourly polling service (AmericanFootball/ESPN)
src/Domain/LBS.Domain.Sport/Squad/Command/CreateSquadCommand.cs Domain command that creates the squad aggregate
src/Domain/LBS.Domain.Sport/Squad/Command/SetSquadListCommand.cs Domain command that reconciles the full roster
src/Domain/LBS.Domain.Sport/Squad/SquadAggregate.cs Aggregate handler and validation
src/Domain/LBS.Domain.Sport/Squad/SquadContractBuilder.cs Async projection that builds SquadContract