Advertisement
Advertisement
Advertisement
Advertisement
Advertisement
Navigation
Getting Started
Subscriptions
Ai Features
User Guide
Timeline Feature
Documentation & Guides
Riot API Timeline Data Integration
Overview
The Riot API Timeline Data Integration feature provides a robust internal data pipeline for fetching, processing, and storing League of Legends match timeline data. This data is used internally by RiftSurge's AI analysis features to provide deep insights into player performance and gameplay patterns.
Architecture
Core Components
1. Models - Eloquent models for timeline data storage
2. Services - Business logic for data processing and API interactions
3. Jobs - Asynchronous processing of timeline data
4. Events & Listeners - Automatic triggering of timeline fetching
5. Storage - Flexible file storage using Laravel Storage facade
Data Flow
ScrimGame Completed → Event → Listener → FetchTimelineDataJob → ProcessTimelineDataJob → Database Storage
Models
MatchTimeline
- Purpose: Main timeline record for each match
- Key Fields:
match_id
,riot_match_id
,status
,raw_file_path
,processed_at
- Relationships: Has many
TimelineFrame
TimelineFrame
- Purpose: Individual frames within a match timeline
- Key Fields:
timestamp
,game_time
- Relationships: Belongs to
MatchTimeline
, has manyTimelineParticipantFrame
andTimelineEvent
TimelineParticipantFrame
- Purpose: Participant-specific data for each frame
- Key Fields:
participant_id
,current_gold
,total_gold
,level
,xp
,minions_killed
,position_x
,position_y
TimelineEvent
- Purpose: Events that occur during the match
- Key Fields:
event_type
,timestamp
,participant_id
,victim_id
,killer_id
,position_x
,position_y
TimelineSummary
- Purpose: Aggregated statistics for each participant
- Key Fields:
participant_id
,total_gold_earned
,kills
,deaths
,assists
,cs_at_10
,cs_at_15
Services
TimelineDataService
- Purpose: Main service for accessing processed timeline data
- Key Methods:
getTimelineData(string $matchId): ?array
- Get complete timeline datagetTimelineDataBatch(array $matchIds): array
- Batch retrievalgetTimelineDataByTimeRange(string $matchId, int $startTime, int $endTime): ?array
getTimelineSummary(string $matchId): ?array
RiotApiTimelineService
- Purpose: Handles Riot API interactions for timeline data
- Key Methods:
fetchTimelineDataWithRetry(string $region, string $matchId): ?array
validateTimelineData(array $timelineData): bool
extractTimelineMetadata(array $timelineData): array
RiotApiStatusService
- Purpose: Monitors Riot API health and error rates
- Key Methods:
trackApiError(): void
isApiDown(): bool
getApiStatus(): string
shouldShowApiDownMessage(): bool
TimelineStorageService
- Purpose: Manages raw timeline data file storage
- Key Methods:
storeTimelineData(string $matchId, array $timelineData): string
getTimelineData(string $filePath): ?array
cleanupOldFiles(int $daysOld = 30): int
TimelineDataValidator
- Purpose: Comprehensive validation of timeline data structure
- Key Methods:
isValid(array $timelineData, string $matchId = '', string $region = ''): bool
getValidationSummary(array $timelineData, string $matchId, string $region): array
Jobs
FetchTimelineDataJob
- Purpose: Fetches raw timeline data from Riot API
- Queue:
riot
- Process: API call → validation → storage → dispatch ProcessTimelineDataJob
ProcessTimelineDataJob
- Purpose: Processes raw timeline data into database
- Queue:
riot
- Process: Read raw data → parse frames/events → store in database
RetryTimelineProcessingJob
- Purpose: Retries failed timeline processing
- Queue:
riot
- Process: Reset failed timelines → dispatch ProcessTimelineDataJob
Events & Listeners
ScrimGameCompleted Event
- Trigger: When a ScrimGame's
completed_at
field is set - Purpose: Signal that a scrim game has finished
TriggerTimelineFetching Listener
- Purpose: Automatically fetch timeline data when scrim games complete
- Process: Check for Riot game ID → create MatchTimeline → dispatch FetchTimelineDataJob
Configuration
Services Configuration (config/services.php
)
'riot' => [
'api_key' => env('RIOT_API_KEY'),
'base_url' => env('RIOT_API_BASE_URL', 'https://americas.api.riotgames.com'),
'timeout' => env('RIOT_API_TIMEOUT', 30),
'retry_attempts' => env('RIOT_API_RETRY_ATTEMPTS', 3),
'retry_delay' => env('RIOT_API_RETRY_DELAY', 1000),
'rate_limits' => [
'personal' => [
'requests_per_second' => 20,
'requests_per_two_minutes' => 100,
],
'application' => [
'requests_per_second' => 500,
'requests_per_two_minutes' => 30000,
],
],
'error_threshold' => env('RIOT_API_ERROR_THRESHOLD', 50),
'error_window_minutes' => env('RIOT_API_ERROR_WINDOW', 30),
'timeline' => [
'disk' => env('RIOT_TIMELINE_DISK', 'local'),
'cleanup_days' => env('RIOT_TIMELINE_CLEANUP_DAYS', 30),
],
],
Timeline Configuration (config/timeline.php
)
return [
'cache' => [
'timeline_data_ttl' => env('TIMELINE_DATA_CACHE_TTL', 3600),
'timeline_stats_ttl' => env('TIMELINE_STATS_CACHE_TTL', 600),
],
'query' => [
'max_frames_limit' => env('TIMELINE_MAX_FRAMES_LIMIT', 1000),
],
];
Queue Configuration (config/queue.php
)
'riot' => [
'driver' => 'redis',
'connection' => env('REDIS_QUEUE_CONNECTION', 'default'),
'queue' => 'riot',
'retry_after' => (int) env('RIOT_QUEUE_RETRY_AFTER', 300),
'block_for' => null,
'after_commit' => false,
],
Horizon Configuration (config/horizon.php
)
'supervisor-riot' => [
'connection' => 'redis',
'queue' => ['riot'],
'balance' => 'auto',
'autoScalingStrategy' => 'time',
'maxProcesses' => 2, // Local: 2, Production: 10
'maxTime' => 0,
'maxJobs' => 0,
'memory' => 256,
'tries' => 3,
'timeout' => 300, // 5 minutes for Riot API calls
'nice' => 0,
],
Environment Variables
Riot API Configuration
RIOT_API_KEY=your_riot_api_key_here
RIOT_API_BASE_URL=https://americas.api.riotgames.com
RIOT_API_TIMEOUT=30
RIOT_API_RETRY_ATTEMPTS=3
RIOT_API_RETRY_DELAY=1000
Error Monitoring
RIOT_API_ERROR_THRESHOLD=50
RIOT_API_ERROR_WINDOW=30
Timeline Storage
RIOT_TIMELINE_DISK=local # local, s3, etc.
RIOT_TIMELINE_CLEANUP_DAYS=30
Timeline Caching
TIMELINE_DATA_CACHE_TTL=3600
TIMELINE_STATS_CACHE_TTL=600
TIMELINE_MAX_FRAMES_LIMIT=1000
Queue Configuration
RIOT_QUEUE_RETRY_AFTER=300
Usage Examples
Fetching Timeline Data
use App\Services\TimelineDataService;
$timelineService = app(TimelineDataService::class);
// Get complete timeline data
$timelineData = $timelineService->getTimelineData('NA1_1234567890');
// Get timeline data for specific time range
$timeRangeData = $timelineService->getTimelineDataByTimeRange(
'NA1_1234567890',
60000, // 1 minute
300000 // 5 minutes
);
// Get timeline summary
$summary = $timelineService->getTimelineSummary('NA1_1234567890');
// Batch retrieval
$batchData = $timelineService->getTimelineDataBatch([
'NA1_1234567890',
'NA1_1234567891',
'NA1_1234567892'
]);
Manual Timeline Fetching
use App\Jobs\FetchTimelineDataJob;
use App\Models\MatchTimeline;
// Create a new timeline record
$matchTimeline = MatchTimeline::create([
'match_id' => 'NA1_1234567890',
'riot_match_id' => 'NA1_1234567890',
'status' => 'pending',
]);
// Dispatch the fetch job
FetchTimelineDataJob::dispatch(
$matchTimeline->id,
'na1', // region
'NA1_1234567890' // match ID
);
API Status Monitoring
use App\Services\RiotApiStatusService;
$statusService = app(RiotApiStatusService::class);
// Check if API is down
if ($statusService->isApiDown()) {
echo "Riot API is currently down";
}
// Get detailed status
$status = $statusService->getDetailedStatus();
echo "Status: " . $status['status'];
echo "Error Count: " . $status['error_count'];
echo "Error Rate: " . $status['error_rate'] . "%";
Error Handling
Custom Exceptions
RiotApiException
- Purpose: Riot API specific errors
- Properties:
statusCode
,endpoint
,response
- Usage: Thrown when Riot API returns client/server errors
TimelineProcessingException
- Purpose: Timeline processing errors
- Properties:
matchId
,stage
,context
- Usage: Thrown during timeline data processing failures
Error Recovery
1. API Failures: Automatic retry with exponential backoff
2. Rate Limiting: Respects Retry-After
headers
3. Data Validation: Comprehensive validation before processing
4. Job Failures: Automatic retry via RetryTimelineProcessingJob
Monitoring
Laravel Horizon
- Queue Monitoring: Real-time queue status and job processing
- Failed Jobs: Automatic retry and failure tracking
- Performance Metrics: Job processing times and throughput
Laravel Nightwatch
- Application Monitoring: Overall application health
- Error Tracking: Exception monitoring and alerting
- Performance Monitoring: Response times and resource usage
Logging
- Structured Logging: All timeline operations are logged with context
- Error Tracking: API errors and processing failures
- Performance Logging: Processing times and data volumes
Testing
Test Coverage
- Unit Tests: All services, models, and jobs
- Integration Tests: End-to-end workflow testing
- Performance Tests: Large data processing and concurrent operations
Running Tests
Run all timeline tests
php artisan test --filter="Timeline"
Run specific test files
php artisan test tests/Feature/TimelineIntegrationTest.php
php artisan test tests/Feature/TimelineProcessingPerformanceTest.php
Run unit tests
php artisan test tests/Feature/Unit/Services/TimelineDataServiceTest.php
Deployment
Prerequisites
1. Redis: Required for queue processing
2. Database: PostgreSQL/MySQL for timeline data storage
3. Storage: Local filesystem or S3 for raw timeline files
4. Riot API Key: Valid API key with appropriate permissions
Deployment Steps
1. Environment Setup: Configure all required environment variables
2. Database Migration: Run timeline table migrations
3. Queue Workers: Start Horizon or queue workers
4. Storage Configuration: Ensure storage disk is properly configured
5. Monitoring Setup: Configure Horizon and Nightwatch
Production Considerations
- Queue Workers: Use Horizon for production queue management
- Storage: Use S3 or similar for raw timeline file storage
- Monitoring: Set up alerts for API failures and processing issues
- Scaling: Adjust Horizon worker counts based on load
Troubleshooting
Common Issues
Timeline Data Not Processing
1. Check queue workers are running
2. Verify Riot API key is valid
3. Check for failed jobs in Horizon
4. Review logs for error messages
API Rate Limiting
1. Check current API usage
2. Verify rate limit configuration
3. Monitor Retry-After
headers
4. Consider upgrading API tier
Storage Issues
1. Verify storage disk configuration
2. Check disk space availability
3. Ensure proper permissions
4. Test file operations manually
Debug Commands
Check queue status
php artisan horizon:status
View failed jobs
php artisan queue:failed
Test API connectivity
php artisan tinker
>> app(\App\Services\RiotApiTimelineService::class)->fetchTimelineDataWithRetry('na1', 'test-match-id')
Check timeline data
php artisan tinker
>> app(\App\Services\TimelineDataService::class)->getTimelineData('test-match-id')
Performance Optimization
Caching
- Timeline Data: Cached for 1 hour by default
- Statistics: Cached for 10 minutes
- API Status: Cached for 5 minutes
Database Optimization
- Indexes: Optimized for time-series queries
- Eager Loading: Prevents N+1 query problems
- Batch Processing: Efficient bulk operations
Queue Optimization
- Dedicated Queue: Separate
riot
queue for API calls - Retry Logic: Exponential backoff for failed requests
- Rate Limiting: Respects Riot API limits
Security Considerations
API Key Management
- Environment Variables: Never hardcode API keys
- Rotation: Regular API key rotation
- Permissions: Minimal required permissions
Data Privacy
- Internal Use Only: Timeline data is not exposed externally
- Access Control: Internal service access only
- Data Retention: Configurable cleanup policies
Input Validation
- Comprehensive Validation: All timeline data is validated
- Sanitization: Proper data sanitization
- Error Handling: Secure error messages
Future Enhancements
Potential Improvements
1. Real-time Processing: WebSocket integration for live updates
2. Advanced Analytics: Machine learning integration
3. Data Export: Export timeline data for external analysis
4. Performance Metrics: Advanced performance tracking
5. Multi-region Support: Enhanced region handling
Scalability Considerations
1. Horizontal Scaling: Multiple queue workers
2. Database Sharding: Partition timeline data by region/date
3. CDN Integration: Faster timeline data delivery
4. Caching Layers: Multi-level caching strategy
Advertisement