cdn module provides a sophisticated, enterprise-grade multi-source Content Delivery Network (CDN) management system with automatic fallback, health tracking, circuit breaker patterns, and intelligent source selection. It ensures resilient data fetching even when individual CDN sources experience failures, outages, or degraded performance.
Overview
The CDN system is a mission-critical component of tif1’s data fetching infrastructure, designed to maximize availability, reliability, and performance when retrieving Formula 1 data from remote sources. It implements battle-tested reliability patterns including circuit breaker logic, automatic failover, health monitoring, and priority-based routing to ensure your application remains operational even under adverse network conditions.Why CDN Management Matters
Formula 1 data fetching presents unique challenges:- Data availability: Historical and live session data must be reliably accessible across multiple seasons (2018-2026+)
- Geographic distribution: Users worldwide need fast access regardless of location
- Network resilience: CDN providers can experience outages, rate limiting, or degraded performance
- Bandwidth optimization: Session data can be large (telemetry, lap times, weather data)—minification reduces transfer sizes by 20-40%
- Cost efficiency: Proper CDN selection and fallback minimize redundant requests and bandwidth waste
Core Capabilities
1. Multi-Source Fallback with Automatic Failover
The CDN manager maintains a prioritized list of CDN sources and automatically tries alternative sources when the primary source fails. This ensures high availability even when individual CDN providers experience issues. How it works:- Sources are tried in priority order (lowest priority number first)
- If a source fails, the next available source is tried immediately
- Successful requests reset the failure counter for that source
- Failed sources are temporarily disabled after reaching the failure threshold
- Zero-downtime failover: Automatic switching to backup sources without user intervention
- Transparent recovery: Sources automatically re-enable after successful requests
- Configurable priorities: Define preferred CDN providers based on performance, cost, or geographic location
2. Health Tracking and Circuit Breaker Pattern
Each CDN source is continuously monitored for reliability. The circuit breaker pattern prevents wasting time on consistently failing sources by temporarily disabling them after repeated failures. Circuit breaker states:- Closed (healthy): 0-2 failures—source is available and used normally
- Open (disabled): 3+ failures—source is excluded from
get_sources()until reset - Half-open (recovering): After a successful request, failure count resets to 0
- Default: 3 consecutive failures before disabling
- Configurable via
_max_failuresattribute - Failures are tracked per-source in
_failure_countsdictionary
- Reduced latency: Skip known-bad sources instead of waiting for timeouts
- Prevent cascading failures: Isolate failing sources to protect overall system health
- Automatic recovery: Sources re-enable after successful requests (self-healing)
3. Priority-Based Routing
Sources are assigned priority levels (integer values, lower = higher priority) that determine the order in which they’re tried. This allows you to:- Optimize for performance: Set fastest CDN as priority 1
- Optimize for cost: Set free/unlimited CDN as priority 1, paid CDN as backup
- Optimize for geography: Set regional CDN as priority 1 for users in that region
- Implement tiered fallback: Primary (priority 1) → Regional backup (priority 2) → Global backup (priority 3)
- Sources are sorted by priority (ascending order: 1, 2, 3, …)
- Sources with the same priority maintain their insertion order
- Priority can be set when creating
CDNSourceobjects - Sources are automatically re-sorted when added via
add_source()
4. JSON Minification Support
Optional JSON minification reduces file sizes by 20-40% by removing whitespace and formatting. This significantly improves download speeds and reduces bandwidth costs, especially for large telemetry datasets. How it works:- When
use_minification=True, URLs are transformed:file.json→file.min.json - jsDelivr CDN automatically serves minified versions when available
- Minification is transparent—parsed data is identical to non-minified versions
- Can be enabled globally via config or per-source
- Telemetry data: ~35-40% size reduction (highly structured, repetitive data)
- Lap data: ~25-30% size reduction
- Session metadata: ~20-25% size reduction
- Network transfer time: Proportional to size reduction (40% smaller = 40% faster download)
- Bandwidth-constrained environments: Mobile networks, metered connections
- High-volume applications: Fetching data for multiple sessions/drivers
- Performance-critical applications: Minimizing cold-start latency
- Cost optimization: Reducing CDN bandwidth costs
5. Configurable Custom Sources
Add custom CDN endpoints to support:- Private mirrors: Host your own copy of F1 data for guaranteed availability
- Regional CDNs: Optimize performance for specific geographic regions
- Corporate proxies: Route requests through internal infrastructure
- Development/testing: Point to local servers or staging environments
- Backup sources: Add redundant sources for mission-critical applications
- Programmatic: Use
add_source()method to add sources at runtime - Config file: Define sources in
~/.tif1rcJSON configuration - Environment variable: Set
TIF1_CDNScomma-separated list
6. Singleton Pattern for Global State
The CDN manager uses a singleton pattern to ensure consistent state across your entire application:- Single source of truth: All data fetching operations use the same CDN manager instance
- Shared health tracking: Failure counts and circuit breaker state are global
- Consistent configuration: Configuration changes affect all subsequent requests
- Thread-safe reads: Multiple threads can safely read CDN sources
- Memory efficient: Only one CDN manager instance exists per process
7. Transparent Integration
The CDN system works seamlessly behind the scenes—you typically don’t need to interact with it directly:- Automatic initialization: CDN manager is created on first use
- Zero-configuration default: Works out-of-the-box with jsDelivr CDN
- Session API integration:
Session.load()automatically uses CDN system - Error handling: Network errors are caught and trigger automatic fallback
- Logging: Debug-level logs show which CDN source is being used
Architecture
The CDN system consists of three main components working together:1. CDNSource (Data Class)
Represents a single CDN endpoint with configuration:- Store CDN configuration (URL, priority, settings)
- Format complete URLs for specific resources via
format_url() - Support minification by transforming file paths
2. CDNManager (Orchestrator)
Manages multiple CDN sources and implements fallback logic:- Initialize sources from configuration (file, env vars, defaults)
- Validate source URLs (HTTPS only, block raw.githubusercontent.com)
- Track health via failure counters (circuit breaker pattern)
- Provide available sources via
get_sources()(filters disabled/failed sources) - Implement fallback logic via
try_sources()(tries sources in priority order) - Manage source lifecycle (add, enable, disable, reset)
3. Global Singleton
A singleCDNManager instance shared across the application:
- Ensure consistent CDN state across all data fetching operations
- Provide global access point via
get_cdn_manager()function - Initialize once on first import, reuse for all subsequent calls
Data Flow
Here’s how a typical data fetch flows through the CDN system:When to Use This API
Most users never need to interact with the CDN API directly—it works transparently behind the scenes. However, you should use this API when:Direct Interaction Scenarios
-
Adding custom CDN sources: You have a private mirror, regional CDN, or backup source
-
Monitoring CDN health: You want to track which sources are failing or build health dashboards
-
Debugging network issues: You need to understand which CDN is being used or why requests are failing
-
Optimizing bandwidth: You want to enable minification for faster downloads
-
Testing fallback behavior: You want to verify your application handles CDN failures gracefully
-
Implementing custom retry logic: You’re building a custom data fetching layer
-
Recovering from widespread failures: Network was down, now you want to reset all sources
Configuration Scenarios
- Setting up regional CDNs: Optimize performance for specific geographic regions
- Implementing cost optimization: Use free CDN as primary, paid CDN as backup
- Corporate environments: Route through internal proxies or mirrors
- Development/testing: Point to local servers or staging environments
- High-availability requirements: Add multiple backup sources for mission-critical applications
The default CDN source is jsDelivr (
https://cdn.jsdelivr.net/gh/TracingInsights), which provides:- Excellent global performance: 800+ CDN locations worldwide
- Unlimited bandwidth: No rate limits or bandwidth caps
- Automatic caching: Intelligent cache invalidation and purging
- HTTP/2 and HTTP/3 support: Modern protocols for faster transfers
- Minification support: Automatic
.min.jsonserving - 99.9% uptime SLA: Enterprise-grade reliability
Quick Start
For most use cases, you don’t need to interact with the CDN API directly—it works transparently behind the scenes. However, here are common operations for advanced use cases:Basic Usage (Transparent)
Inspecting CDN Status
Adding Custom CDN Sources
Enabling Minification
Monitoring and Recovery
Configuration via File
Instead of programmatic configuration, you can define CDN sources in~/.tif1rc:
Configuration via Environment Variables
API Reference
Module-Level Functions
get_cdn_manager()
CDNManager object, ensuring consistent CDN state across your entire application.
Why Singleton Pattern?
The singleton pattern is used because:
- Shared health tracking: CDN health monitoring must be consistent across all data fetching operations
- Global configuration: Configuration changes should affect all subsequent requests
- Consistent failure counts: Circuit breaker state must be global to prevent redundant retries
- Memory efficiency: Only one CDN manager instance exists per process
- Thread safety: Single instance simplifies concurrent access patterns
CDNManager: The global singleton instance
- Thread-safe operations:
get_sources(), readingsourceslist, reading_failure_counts - Not thread-safe:
add_source(),mark_failure(),mark_success(),reset()
- Configure all sources during initialization (single-threaded)
- Only read sources during concurrent execution
- Use locks if you need to modify sources from multiple threads
CDNManager Class
TheCDNManager class is the core orchestrator of the multi-source CDN system. It maintains a list of CDN sources, tracks their health, implements fallback logic with circuit breaker patterns, and provides methods for managing sources.
Initialization
The CDN manager is automatically initialized when you callget_cdn_manager() for the first time. During initialization, the following steps occur:
Initialization Sequence:
- Load configuration: Reads CDN sources from config file (
~/.tif1rc) or environment variables (TIF1_CDNS) - Parse source URLs: Splits comma-separated CDN URLs into individual sources
- Validate sources: Ensures all URLs are HTTPS and not blacklisted (e.g.,
raw.githubusercontent.com) - Create CDNSource objects: Wraps each URL in a
CDNSourcewith priority and settings - Assign priorities: Sources are assigned priorities based on their order (1, 2, 3, …)
- Initialize health tracking: Sets up
_failure_countsdictionary with all sources at 0 failures - Sort by priority: Orders sources so highest-priority (lowest number) is tried first
- Fallback to defaults: If no valid sources found, uses jsDelivr as default
- Environment variable:
TIF1_CDNS(comma-separated list of HTTPS URLs) - Config file:
~/.tif1rcin home directory or current directory (ifTIF1_TRUST_CWD_CONFIG=true) - Default:
https://cdn.jsdelivr.net/gh/TracingInsights(jsDelivr CDN)
- URLs must start with
https://(HTTP is rejected for security) - URLs containing
raw.githubusercontent.comare rejected (rate limits) - Invalid URLs are logged as warnings and skipped
- If all URLs are invalid, falls back to default jsDelivr CDN
~/.tif1rc:
Attributes
sources
- Always sorted: Maintained in priority order (1, 2, 3, …)
- Includes all sources: Both
enabled=Trueandenabled=Falsesources - Includes failed sources: Sources that have exceeded failure threshold
- Mutable: Can be modified directly, but prefer using
add_source()for automatic sorting
- Iterate over all sources (including disabled) for health reporting
- Count total configured sources
- Inspect source configuration (URLs, priorities, settings)
- Debug CDN setup
_failure_counts
_max_failures (default: 3), it’s automatically excluded from get_sources() until reset.
Structure:
- Initialized to 0: All sources start with 0 failures (healthy state)
- Incremented on failure:
mark_failure()increments the count - Reset on success:
mark_success()resets to 0 - Circuit breaker threshold: Sources with count >=
_max_failuresare excluded - Persistent across requests: Counts persist for the lifetime of the CDN manager instance
mark_failure(source_name)to incrementmark_success(source_name)to resetreset()to reset all sources
_max_failures
- Closed (healthy):
failure_count < _max_failures→ Source is available - Open (disabled):
failure_count >= _max_failures→ Source is excluded fromget_sources() - Half-open (recovering): After
mark_success(), count resets to 0 → Source becomes available again
- Not too sensitive: Tolerates transient network issues (1-2 temporary failures)
- Not too lenient: Quickly disables consistently failing sources (3 failures = clear pattern)
- Fast recovery: Single successful request resets the counter
Methods
get_sources()
- Disabled sources: Sources with
enabled=False - Failed sources: Sources where
_failure_counts[name] >= _max_failures(circuit breaker open)
list[CDNSource]: Available sources sorted by priority (ascending)- Empty list if all sources are disabled or have exceeded failure threshold
- Sources are sorted by priority: 1, 2, 3, … (lower number = higher priority)
- Sources with the same priority maintain their insertion order (stable sort)
- The first source in the list is tried first by
try_sources()
- Data fetching: Primary method used by
try_sources()to determine which sources to attempt - Health monitoring: Check how many sources are currently available
- Debugging: Understand which sources will be used for the next request
- Load balancing: Implement custom logic based on available sources
add_source()
sources list in priority order, and its failure count is initialized to 0.
This method is useful for:
- Adding private CDN mirrors
- Adding regional CDN endpoints for better performance
- Adding backup sources for increased reliability
- Testing custom CDN configurations
source(CDNSource): The CDN source object to add
- Sources are automatically sorted by priority after insertion
- If a source with the same name already exists, both are kept (consider using unique names)
- The new source is immediately available for use via
get_sources() - Failure count is initialized to 0 (healthy state)
mark_failure()
get_sources() until reset.
This implements a circuit breaker pattern to prevent wasting time on consistently failing sources. The circuit breaker helps:
- Reduce latency by skipping known-bad sources
- Prevent cascading failures
- Allow sources to recover (via
reset()ormark_success())
source_name(str): Name of the CDN source that failed
- Increments failure count by 1
- If count reaches
_max_failures(3), logs a warning - Source is automatically excluded from
get_sources()after threshold - Does not disable the source permanently—can be recovered via
reset()ormark_success()
try_sources() when a CDN request fails. You typically don’t need to call it manually unless implementing custom fetching logic.
Example:
mark_success()
source_name(str): Name of the CDN source that succeeded
- Sets failure count to 0 for the specified source
- Source becomes immediately available via
get_sources()if it was disabled - Called automatically by
try_sources()on successful fetch
try_sources() when a CDN request succeeds. You typically don’t need to call it manually.
Example:
reset()
- After network outage: When your network connection was down and all sources failed
- After CDN maintenance: When you know CDN providers have resolved their issues
- Testing: When you want to test fallback behavior from a clean state
- Manual recovery: When you want to force retry of all sources
- Resets failure count to 0 for every source in
cdn.sources - All sources become immediately available via
get_sources()(ifenabled=True) - Does not modify source configuration (priority, URLs, minification settings)
try_sources()
- Get available sources: Calls
get_sources()to get enabled, healthy sources sorted by priority - Check availability: If no sources available, raises
NetworkErrorimmediately - Try each source (in priority order):
- Format URL via
source.format_url(year, gp, session, path) - Log debug message:
"Trying CDN: {source.name} - {url}" - Call
fetch_func(url)to attempt HTTP request - On success: Call
mark_success(source.name)and return data (done!) - On
DataNotFoundError(404): Re-raise immediately (data doesn’t exist, no point trying other sources) - On other exceptions: Log warning, call
mark_failure(source.name), try next source
- Format URL via
- All sources failed: Raise
NetworkErrorwith details from last exception
year(int): Season year (e.g., 2021, 2022, 2023)gp(str): Grand Prix name, URL-encoded (e.g., “Belgian%20Grand%20Prix”, “Monaco%20Grand%20Prix”)- Important: Must be URL-encoded (spaces as
%20, not+) - Use
urllib.parse.quote()if encoding manually
- Important: Must be URL-encoded (spaces as
session(str): Session name (e.g., “Race”, “Qualifying”, “Practice 1”, “Sprint”)path(str): Resource path relative to session directory (e.g., “drivers.json”, “laps.json”, “telemetry.json”)fetch_func(Callable[[str], Any]): Function that takes a URL string and returns fetched data- Should raise
DataNotFoundErrorfor 404 responses - Should raise other exceptions for network/server errors
- Return type can be any (dict, list, bytes, etc.)
- Should raise
Any: Fetched data from the first successful CDN source (return type depends onfetch_func)
DataNotFoundError: If resource doesn’t exist (404 from any source)- This is re-raised immediately without trying other sources
- Indicates the requested data genuinely doesn’t exist
NetworkError: If all CDN sources fail- Includes URL path and status code from last exception
- Indicates all sources are unavailable or experiencing issues
-
Data not found (404): Permanent error—data doesn’t exist
- Re-raised immediately as
DataNotFoundError - No point trying other CDN sources (they’ll all return 404)
- Does NOT increment failure counter (not a CDN failure)
- Re-raised immediately as
-
Network/server errors: Temporary error—CDN source is failing
- Logged as warning
- Failure counter incremented via
mark_failure() - Next source is tried
- If all sources fail, raises
NetworkError
- Latency: Each failed source adds latency (timeout + retry time). Use reasonable timeouts in
fetch_func. - Circuit breaker: After 3 failures, sources are automatically disabled, reducing latency for subsequent requests.
- Minification: Enable
use_minification=Trueto reduce download time by 20-40%. - Connection pooling: Reuse HTTP sessions in
fetch_funcfor better performance. - Parallel fetching:
try_sources()is sequential. For parallel fetching of multiple resources, call it multiple times concurrently.
try_sources()is thread-safe for concurrent calls- Failure counters are updated atomically (though not with locks)
- In high-concurrency scenarios, consider external synchronization for
mark_failure()/mark_success()calls
CDNSource
Dataclass representing a CDN source configuration.Constructor
name: Human-readable source namebase_url: Base URL for the CDN (must be HTTPS)priority: Priority level (lower number = higher priority, default: 0)enabled: Whether source is currently enabled (default: True)use_minification: Enable JSON minification (appends.minbefore.json, default: False)
Methods
format_url()
year: Season year (e.g., 2021)gp: Grand Prix name, URL-encoded (e.g., “Belgian%20Grand%20Prix”)session: Session name (e.g., “Race”, “Qualifying”)path: Resource path (e.g., “drivers.json”)
- Complete CDN URL string
use_minification=True and path ends with .json, the path is transformed from file.json to file.min.json.
Example:
Configuration
CDN behavior can be configured via the global config:Practical Example: 2021 Belgian Grand Prix
Here’s a complete example showing how the CDN system works when fetching data for the 2021 Belgian Grand Prix Race:Best Practices
Configuration
- Use HTTPS only: HTTP CDN sources are rejected for security
- Enable minification: Reduces bandwidth by 20-40% for large datasets
- Configure via file: Use
~/.tif1rcfor persistent configuration - Set priorities wisely: Lower number = higher priority (1 before 2)
Error Handling
- Distinguish error types: Handle
DataNotFoundError(404) vsNetworkError(all sources failed) - Let CDN manager handle fallback: Don’t implement your own retry logic
- Log failures: Enable debug logging to see which CDN is being used
Performance
- Enable minification: Especially for telemetry data (35-40% size reduction)
- Use connection pooling: Reuse HTTP sessions in fetch functions
- Set reasonable timeouts: Balance between patience and responsiveness
- Monitor circuit breaker: Check failure counts to identify problematic sources
Reliability
- Add backup sources: At least 2-3 sources for production applications
- Use regional CDNs: Optimize for your user’s geographic location
- Implement auto-recovery: Periodically reset sources after network issues
- Monitor health: Track availability and failure rates
Security
- Never use raw.githubusercontent.com: Rate limited and blocked by tif1
- Validate custom CDN URLs: Ensure they’re trusted sources
- Use HTTPS everywhere: HTTP sources are automatically rejected
- Audit CDN sources: Regularly review configured sources
Troubleshooting
All CDN Sources Failing
Symptoms:NetworkError: All CDN sources failed
Solutions:
- Check network connectivity:
ping cdn.jsdelivr.net - Verify CDN URLs are accessible in browser
- Reset all sources:
cdn.reset() - Check firewall/proxy settings
- Enable debug logging to see detailed errors
Data Not Found (404)
Symptoms:DataNotFoundError: Data not found
Cause: Requested data doesn’t exist (not a CDN failure)
Solutions:
- Verify session exists: Check year, GP name, session name
- Check data availability: Some sessions may not have all data types
- Use correct path: Ensure
pathparameter is correct (e.g., “drivers.json”)
Slow Performance
Symptoms: Data fetching is slow Solutions:- Enable minification:
config.set("cdn_use_minification", True) - Add regional CDN: Closer to your geographic location
- Check network speed: Run speed test
- Use connection pooling: Reuse HTTP sessions
- Increase timeout: May be timing out prematurely
Circuit Breaker Stuck Open
Symptoms: Sources remain disabled after network recovery Solution: Reset failure countsRelated APIs
- HTTP Session API: Underlying HTTP client used by CDN system
- Retry API: Retry logic and circuit breaker patterns
- Config API: CDN configuration management
- Exceptions API: NetworkError and DataNotFoundError details