Documentation
¶
Overview ¶
Package cachepreload provides cache preloading when folders are opened.
Index ¶
- Constants
- func GenerateCacheKey(method, path, query, encoding string) string
- func GenerateCacheKeyWithHX(method, path, query, htmx, hxTarget, encoding string) string
- func MakeInternalRequest(ctx context.Context, cfg InternalRequestConfig, path string) error
- func MakeInternalRequestWithVariant(ctx context.Context, cfg InternalRequestConfig, path string, hxTarget string, ...) error
- func PutPreloadTask(task *PreloadTask)
- type FolderPreloadTask
- type InternalRequestConfig
- type PreloadConfig
- type PreloadManager
- func (pm *PreloadManager) Configure(cfg PreloadConfig)
- func (pm *PreloadManager) GetMetrics() PreloadMetricsSnapshot
- func (pm *PreloadManager) GetScheduler() *scheduler.Scheduler
- func (pm *PreloadManager) IsEnabled() bool
- func (pm *PreloadManager) ScheduleFolderPreload(ctx context.Context, folderID int64, sessionID string, acceptEncoding string)
- func (pm *PreloadManager) SetEnabled(enabled bool)
- func (pm *PreloadManager) SetOnSetEnabled(fn func(bool))
- func (pm *PreloadManager) Shutdown()
- type PreloadMetrics
- func (m *PreloadMetrics) RecordCancelled()
- func (m *PreloadMetrics) RecordFailure(path string, err error, duration time.Duration)
- func (m *PreloadMetrics) RecordSkipped(reason string)
- func (m *PreloadMetrics) RecordSuccess(path string, duration time.Duration)
- func (m *PreloadMetrics) Summary() string
- type PreloadMetricsSnapshot
- type PreloadService
- type PreloadTask
- type SessionTracker
- type TaskTracker
Constants ¶
const InternalPreloadHeader = "X-SFPG-Internal-Preload"
InternalPreloadHeader is set on internal preload requests so handlers can skip scheduling another preload (avoiding cascading preloads).
Variables ¶
This section is empty.
Functions ¶
func GenerateCacheKey ¶
GenerateCacheKey creates a cache key matching the HTTP cache middleware pattern. This ensures preloaded entries are found by real requests.
The key format matches http_cache_middleware.go:
METHOD:/path?query|HX=false|HXTarget=|encoding
Parameters:
- method: HTTP method (GET)
- path: URL path (e.g., /gallery/23)
- query: Full query string (e.g., v=20260201-01)
- encoding: Accept-Encoding value (default: "identity")
func GenerateCacheKeyWithHX ¶
GenerateCacheKeyWithHX creates a cache key matching the HTTP cache middleware pattern for a specific HX-Request / HX-Target / Accept-Encoding variant. Use this for preloading so stored entries match real browser requests (e.g. HX=true, HXTarget=box_info, gzip).
func MakeInternalRequest ¶
func MakeInternalRequest(ctx context.Context, cfg InternalRequestConfig, path string) error
MakeInternalRequest makes an internal HTTP request to warm the cache. The request goes through the full middleware chain to ensure proper cache entries.
IMPORTANT: Does NOT set HX-Request header - this ensures full-page cache entries are created (partials have Cache-Control: no-store and won't be cached).
func MakeInternalRequestWithVariant ¶
func MakeInternalRequestWithVariant(ctx context.Context, cfg InternalRequestConfig, path string, hxTarget string, encoding string) error
MakeInternalRequestWithVariant makes an internal HTTP request with optional HX variant and Accept-Encoding so the stored cache key matches real browser requests. When hxTarget is non-empty, sets HX-Request: true and HX-Target: hxTarget; when empty, does not set HX headers (full-page style). encoding is always set on Accept-Encoding.
func PutPreloadTask ¶
func PutPreloadTask(task *PreloadTask)
PutPreloadTask returns a PreloadTask to the pool.
Types ¶
type FolderPreloadTask ¶
type FolderPreloadTask struct {
FolderID int64
SessionID string
ETagVersion string
PreferredEncoding string // from triggering request's Accept-Encoding (normalized)
CacheableRoutes []string
DBRoPool *dbconnpool.DbSQLConnPool
TaskTracker *TaskTracker
Scheduler *scheduler.Scheduler
RequestConfig InternalRequestConfig
Metrics *PreloadMetrics
GetQueries func(*dbconnpool.CpConn) interfaces.HandlerQueries
}
FolderPreloadTask checks a folder's contents and schedules individual preload tasks. It respects CacheableRoutes and uses TaskTracker for deduplication. PreferredEncoding is the normalized Accept-Encoding from the request that triggered this preload; HTMX-variant preloads use it so cache keys match that client.
type InternalRequestConfig ¶
type InternalRequestConfig struct {
// Handler is the HTTP handler wrapped with full middleware chain
// (cache middleware, compression middleware, etc.)
Handler http.Handler
// ETagVersion for cache key query string
ETagVersion string
}
InternalRequestConfig holds dependencies for making internal HTTP requests.
type PreloadConfig ¶
type PreloadConfig struct {
TaskTracker *TaskTracker
SessionTracker *SessionTracker
DBRoPool *dbconnpool.DbSQLConnPool
GetQueries func(*dbconnpool.CpConn) interfaces.HandlerQueries
GetHandler func() http.Handler // Lazy: full middleware chain
GetETagVersion func() string
Metrics *PreloadMetrics
}
PreloadConfig holds dependencies for ScheduleFolderPreload.
type PreloadManager ¶
type PreloadManager struct {
// contains filtered or unexported fields
}
PreloadManager manages the cache preload scheduler lifecycle with dynamic enable/disable support. It implements PreloadService and can replace the scheduler instance when toggling.
func NewPreloadManager ¶
func NewPreloadManager(cacheableRoutes []string, initialEnabled bool) *PreloadManager
NewPreloadManager creates a new PreloadManager with the given cacheable routes. If initialEnabled is true, the scheduler is started immediately.
func (*PreloadManager) Configure ¶
func (pm *PreloadManager) Configure(cfg PreloadConfig)
Configure sets dependencies for ScheduleFolderPreload. Call after creation.
func (*PreloadManager) GetMetrics ¶
func (pm *PreloadManager) GetMetrics() PreloadMetricsSnapshot
GetMetrics returns the current preload metrics snapshot.
func (*PreloadManager) GetScheduler ¶
func (pm *PreloadManager) GetScheduler() *scheduler.Scheduler
GetScheduler returns the current scheduler for testing. Returns nil if disabled.
func (*PreloadManager) IsEnabled ¶
func (pm *PreloadManager) IsEnabled() bool
IsEnabled returns whether cache preloading is currently enabled.
func (*PreloadManager) ScheduleFolderPreload ¶
func (pm *PreloadManager) ScheduleFolderPreload(ctx context.Context, folderID int64, sessionID string, acceptEncoding string)
ScheduleFolderPreload schedules background cache preload for a folder. acceptEncoding is the triggering request's Accept-Encoding; its normalized value is used for preload keys so they match that client's subsequent requests. sessionID is used for task cancellation when user navigates away. Non-blocking.
func (*PreloadManager) SetEnabled ¶
func (pm *PreloadManager) SetEnabled(enabled bool)
SetEnabled dynamically enables or disables cache preloading. When disabled, all pending tasks are cancelled.
func (*PreloadManager) SetOnSetEnabled ¶
func (pm *PreloadManager) SetOnSetEnabled(fn func(bool))
SetOnSetEnabled sets an optional callback invoked when SetEnabled is called (for tests).
func (*PreloadManager) Shutdown ¶
func (pm *PreloadManager) Shutdown()
Shutdown gracefully shuts down the PreloadManager, stopping the scheduler if running. Call this during application shutdown.
type PreloadMetrics ¶
type PreloadMetrics struct {
TasksScheduled atomic.Int64
TasksCompleted atomic.Int64
TasksFailed atomic.Int64
TasksCancelled atomic.Int64
TasksSkipped atomic.Int64 // Due to deduplication or existing cache
TotalDuration atomic.Int64 // Nanoseconds
// contains filtered or unexported fields
}
PreloadMetrics collects observability data for cache preloading operations.
func (*PreloadMetrics) RecordCancelled ¶
func (m *PreloadMetrics) RecordCancelled()
RecordCancelled records a cancelled task.
func (*PreloadMetrics) RecordFailure ¶
func (m *PreloadMetrics) RecordFailure(path string, err error, duration time.Duration)
RecordFailure records a failed preload.
func (*PreloadMetrics) RecordSkipped ¶
func (m *PreloadMetrics) RecordSkipped(reason string)
RecordSkipped records a skipped task (deduplicated or cached).
func (*PreloadMetrics) RecordSuccess ¶
func (m *PreloadMetrics) RecordSuccess(path string, duration time.Duration)
RecordSuccess records a successful preload.
func (*PreloadMetrics) Summary ¶
func (m *PreloadMetrics) Summary() string
Summary returns a string summary for logging.
type PreloadMetricsSnapshot ¶
type PreloadMetricsSnapshot struct {
TasksScheduled int64
TasksCompleted int64
TasksFailed int64
TasksCancelled int64
TasksSkipped int64
TotalDuration time.Duration
}
PreloadMetricsSnapshot holds a snapshot of preload metrics.
type PreloadService ¶
type PreloadService interface {
// ScheduleFolderPreload schedules background cache preload for a folder.
// acceptEncoding is the triggering request's Accept-Encoding header; its
// normalized value (br/gzip/identity) is used for preload keys so they match
// that client's subsequent requests. sessionID is used for task cancellation
// when user navigates away. Non-blocking (fire-and-forget).
ScheduleFolderPreload(ctx context.Context, folderID int64, sessionID string, acceptEncoding string)
// SetEnabled dynamically enables or disables cache preloading.
// When disabled, all pending tasks are cancelled.
SetEnabled(enabled bool)
// IsEnabled returns whether cache preloading is currently enabled.
IsEnabled() bool
}
PreloadService defines the interface for cache preloading operations. Handlers receive this interface via dependency injection (Option B pattern).
type PreloadTask ¶
type PreloadTask struct {
CacheKey string
Path string
HXTarget string // optional; when set, request uses HX-Request/HX-Target and Encoding
Encoding string // optional; used with HXTarget (e.g. "gzip")
TaskTracker *TaskTracker
RequestConfig InternalRequestConfig
Metrics *PreloadMetrics
}
PreloadTask makes an internal HTTP request to warm the cache for a single endpoint. When HXTarget is non-empty, the request uses HTMX variant headers so the stored cache entry matches real browser requests (e.g. info box, lightbox).
func GetPreloadTask ¶
func GetPreloadTask() *PreloadTask
GetPreloadTask retrieves a PreloadTask from the pool.
type SessionTracker ¶
type SessionTracker struct {
// contains filtered or unexported fields
}
SessionTracker manages per-session preload state for folder navigation cancellation. When a user navigates to a new folder, outstanding tasks for the previous folder are cancelled to avoid wasting resources.
func (*SessionTracker) Cleanup ¶
func (s *SessionTracker) Cleanup(maxAge time.Duration)
Cleanup removes stale session entries (call periodically or on session end).
func (*SessionTracker) OnFolderOpen ¶
func (s *SessionTracker) OnFolderOpen(sessionID string, folderID int64) (previousFolderID int64)
OnFolderOpen is called when a user opens a folder. Returns the previous folderID (0 if none) for task cancellation.
type TaskTracker ¶
type TaskTracker struct {
// contains filtered or unexported fields
}
TaskTracker provides deduplication for preload tasks using full cache keys. It prevents scheduling duplicate tasks for the same cache entry.
func (*TaskTracker) CancelSessionTasks ¶
func (t *TaskTracker) CancelSessionTasks(sessionID string) []string
CancelSessionTasks marks all tasks for a session as cancelled. Returns list of taskIDs to cancel via scheduler.RemoveTask().
func (*TaskTracker) IsTaskPending ¶
func (t *TaskTracker) IsTaskPending(cacheKey string) bool
IsTaskPending returns true if a task for this cache key is already scheduled/running.
func (*TaskTracker) RegisterTask ¶
func (t *TaskTracker) RegisterTask(cacheKey, sessionID, taskID string) bool
RegisterTask marks a cache key as having a pending task. Returns false if task already pending (caller should skip).
func (*TaskTracker) UnregisterTask ¶
func (t *TaskTracker) UnregisterTask(cacheKey string)
UnregisterTask removes a cache key from pending (called when task completes).