// Sol ISR (Incremental Static Regeneration) Types
//
// Provides trait-based cache abstraction for ISR implementation.
// Supports multiple backends: MemoryCache (dev), KVCache (production).
// ============================================================================
// Cache Entry
// ============================================================================
///|
/// ISR cache entry containing rendered HTML and metadata
pub struct CacheEntry {
/// Rendered HTML content
html : String
/// Generation timestamp (Unix timestamp in milliseconds)
generated_at : Int64
/// Revalidation interval in seconds
revalidate : Int
}
///|
/// Create a new cache entry
pub fn CacheEntry::new(
html : String,
generated_at : Int64,
revalidate : Int,
) -> CacheEntry {
{ html, generated_at, revalidate }
}
// ============================================================================
// Cache Status
// ============================================================================
///|
/// Cache status for SWR (Stale-While-Revalidate) pattern
pub enum CacheStatus {
/// Cache is fresh, serve directly
Fresh
/// Cache is stale, serve and revalidate in background
Stale
/// Cache miss, generate and cache
Miss
}
// ============================================================================
// ISRCache Trait
// ============================================================================
///|
/// ISR cache storage abstraction
/// Implement this trait for different backends (Memory, KV, Redis, etc.)
pub(open) trait ISRCache {
/// Get cache entry by key
get(Self, String) -> CacheEntry?
/// Put cache entry
put(Self, String, CacheEntry) -> Unit
/// Delete cache entry
delete(Self, String) -> Unit
/// Schedule background task for SWR revalidation
/// In memory: executes immediately
/// In Workers: uses waitUntil for background execution
schedule_revalidation(Self, async () -> Unit) -> Unit
}
// ============================================================================
// ISR Config
// ============================================================================
///|
/// ISR configuration
pub struct ISRConfig {
/// Enable ISR
enabled : Bool
/// Default revalidation interval in seconds
default_revalidate : Int
}
///|
/// Default ISR configuration
pub fn ISRConfig::default() -> ISRConfig {
{ enabled: true, default_revalidate: 60 }
}
// ============================================================================
// Cache Strategy (CDN + App layer)
// ============================================================================
///|
/// CDN cache strategy for ISR pages.
/// Controls how CDN-level caching (e.g., Cloudflare async SWR) interacts
/// with app-level ISR caching.
pub(all) enum CDNCacheStrategy {
/// CDN handles SWR entirely via Cache-Control headers.
/// App-level ISR is bypassed. Simplest option.
/// Sets: `Cache-Control: s-maxage={revalidate}, stale-while-revalidate={grace}`
CdnSwr(Int) // grace period in seconds
/// Two-layer cache: CDN with short TTL + app-level ISR with longer TTL.
/// CDN miss falls through to app ISR which serves from KV/memory.
/// Sets: `Cache-Control: s-maxage={cdn_ttl}, stale-while-revalidate={cdn_grace}`
Hybrid(Int, Int) // cdn_ttl, cdn_grace
/// App-level ISR only. CDN caching disabled (`private, no-store`).
/// All requests reach the app. Full control over cache invalidation.
AppIsr
}
///|
/// Generate Cache-Control header value for a given strategy and revalidate interval.
pub fn CDNCacheStrategy::cache_control(
self : CDNCacheStrategy,
revalidate : Int,
) -> String {
match self {
CdnSwr(grace) =>
"s-maxage=" +
revalidate.to_string() +
", stale-while-revalidate=" +
grace.to_string()
Hybrid(cdn_ttl, cdn_grace) =>
"s-maxage=" +
cdn_ttl.to_string() +
", stale-while-revalidate=" +
cdn_grace.to_string()
AppIsr => "private, no-store"
}
}
///|
/// Get the X-Sol-CDN-Cache header value describing this strategy.
pub fn CDNCacheStrategy::header_value(self : CDNCacheStrategy) -> String {
match self {
CdnSwr(_) => "cdn-swr"
Hybrid(_, _) => "hybrid"
AppIsr => "app-isr"
}
}