-
Notifications
You must be signed in to change notification settings - Fork 10
Data Integration Architecture
This document outlines the data integration stack inside the TV client: HTTP communication, repository contracts, DTO-to-domain mapping, caching strategies, dependency injection, and the error-handling patterns that keep autoplay features resilient. Use it alongside the TV App overview for cross-feature context and the navigation guide for UI flows.
The TV application follows a clean three-tier design built on Kotlin Multiplatform. Remote data access, domain logic, and presentation stay isolated so each feature module (Stories, Photos, Events) can evolve independently. The stack emphasizes:
- A shared HTTP layer powered by a tuned Ktor client.
- Repositories that expose type-safe models while hiding transport concerns.
- Mappers that normalize DTOs and enrich them with derived business fields.
- Functional error propagation using
Either/sealed results instead of unchecked exceptions. - Multi-level caching (in-memory, disk, snapshot payloads) for offline safety.
- Dependency injection via modular Koin definitions.
| Tier | Responsibilities | Typical Artifacts |
|---|---|---|
| Data | Remote APIs, DTOs, mappers, caches | Ktor clients, repository implementations |
| Domain | Business contracts, aggregators, feature services | Repository interfaces, data providers, validation rules |
| Presentation | Autoplay components, feature controllers, UI state machines | Feature components, intent/state models |
End-to-End Flow
- Autoplay feature requests content from a domain-facing provider.
- Provider coordinates one or more repositories (Stories, Photos, Events).
- Repositories call API clients, map DTOs into domain models, and enrich data.
- Domain models flow into Compose state, with caching + retry along the path.
Each feature module contains a self-contained data stack:
| Component | Purpose |
|---|---|
| API Client | Performs HTTP calls with typed requests |
| DTO | Mirrors backend payloads for serialization |
| Mapper | Converts DTOs to stable domain models |
| Repository | Applies caching, error handling, exposure |
- Repository interfaces define contracts the presentation tier consumes.
- Domain models describe business entities shared across features (e.g., stories, teammates, events, photos).
- Data providers (like the Stories provider) coordinate multiple repositories, merge records, and emit payloads plus warnings.
- Feature controllers depend only on domain interfaces.
- Autoplay component requests data via providers, observes flows, and manages UI state transitions.
- Error states surface as banners or diagnostics cards without leaking transport details.
| Setting | Value / Behavior | Purpose |
|---|---|---|
| Timeouts | 40s request/connect/socket | Stable playback on unreliable signage networks |
| Content Negotiation | JSON via Kotlinx Serialization (lenient mode) | Automatic parsing + forward compatibility |
| Authentication | Optional bearer token header | Secures staging/production API calls |
| Logging | Full request/response logging in debug builds | Traceability during QA |
| Retry Hooks | Backoff-aware interceptors | Handles transient gateway errors |
- DTOs mirror backend contracts exactly (field names, optionality, nested payloads).
- Annotated with Kotlinx Serialization for multiplatform compatibility.
- Versioned per feature so schema changes do not cascade globally.
| Aspect | Approach | Benefit |
|---|---|---|
| Null Safety | Default values (empty strings, placeholders) | Prevents runtime crashes |
| Type Conversion | Parse ISO dates, numeric types, booleans | Domain layer uses strong types |
| Data Enrichment | Merge multiple DTOs (e.g., teammate + XP data) | Rich story cards without UI logic |
| Validation | Filter invalid/incomplete records early | Keeps autoplay feeds clean |
| Endpoint | Method | Purpose | Auth |
|---|---|---|---|
/api/v1/events |
GET | Leader ID and calendar events | Bearer |
/api/v1/teammates |
GET | Employee roster for celebrations | Bearer |
/api/v1/duolingo/users |
GET | XP leaderboard, streak data | Bearer |
/api/v1/sport |
GET | Sport/activity stats for signage | Bearer |
/api/v1/photos |
GET | Synology-backed photo carousel assets | Bearer |
Server-side services pre-aggregate upstream systems so the TV client receives a stable contract tailored for signage.
- Stories provider chunks roster fetches (100 items per call), runs external source lookups in parallel, merges by email/username, and emits payloads with warning metadata.
- Events and Photos providers follow similar patterns: pull upstream data, hydrate domain models, then expose flows consumed by autoplay features.
- Warnings allow partial renders when one source fails; only full outages halt a feature.
| Cache Type | Configuration | Purpose |
|---|---|---|
| Memory Cache | ~30% of available memory | Instant redraws for looping slides |
| Disk Cache | 30 MB | Offline access between refresh cycles |
| Crossfade | 100 ms | Smooth transitions during autoplay |
- Photos: Persists last successful album snapshot so slideshows continue offline.
- Stories: Stores celebration payloads alongside warning list to avoid duplicate merges.
- Events: Keeps next rotation locally with timestamps to expire stale promos.
- Core module registers HTTP client, serializers, base repositories.
- Feature modules add their API clients, mappers, repositories, and data providers.
- Components use dependency injection helpers to obtain services, improving testability.
- Scope-aware definitions ensure long-lived singletons (HTTP client, caches) coexist with short-lived feature controllers.