cachepreload

package
v0.1.149 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 23, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package cachepreload provides cache preloading when folders are opened.

Index

Constants

View Source
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

func GenerateCacheKey(method, path, query, encoding string) string

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

func GenerateCacheKeyWithHX(method, path, query, htmx, hxTarget, encoding string) string

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.

func (*FolderPreloadTask) Run

func (t *FolderPreloadTask) Run(ctx context.Context) error

Run implements scheduler.Task. Uses GetPreloadRoutesByFolderID as the source of truth (direct children only).

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.

func (*PreloadTask) Run

func (t *PreloadTask) Run(ctx context.Context) error

Run implements scheduler.Task.

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).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL