@@ -48,26 +48,10 @@ func NewServer(addr string) *Server {
4848 tmpl = nil
4949 }
5050
51- // Initialize cache
51+ // Load cache settings; runtime cache components are initialized at server start.
5252 cacheCfg := cache .DefaultConfig ()
53- cacheManager , _ := cache .NewManager (cacheCfg )
5453 cacheSettings , _ := cache .LoadSettings (cacheCfg .BasePath )
5554
56- // Initialize photo store with shared database
57- var photoStore * cache.PhotoStore
58- photoDB , err := cache .OpenSharedDB (cacheCfg .BasePath , "photos.db" )
59- if err == nil {
60- photoStore , _ = cache .NewPhotoStore (photoDB , cacheCfg .BasePath , cache .DefaultPhotoTTL )
61- // Prune expired photos on startup
62- if photoStore != nil {
63- go func () {
64- if pruned , err := photoStore .Prune (); err == nil && pruned > 0 {
65- fmt .Fprintf (os .Stderr , "Pruned %d expired photos from cache\n " , pruned )
66- }
67- }()
68- }
69- }
70-
7155 return & Server {
7256 addr : addr ,
7357 demoMode : false ,
@@ -78,15 +62,63 @@ func NewServer(addr string) *Server {
7862 nylasClient : nylasClient ,
7963 templates : tmpl ,
8064 hasAPIKey : hasAPIKey ,
81- cacheManager : cacheManager ,
8265 cacheSettings : cacheSettings ,
83- photoStore : photoStore ,
8466 offlineQueues : make (map [string ]* cache.OfflineQueue ),
8567 syncStopCh : make (chan struct {}),
8668 isOnline : true ,
8769 }
8870}
8971
72+ // initCacheRuntime initializes runtime cache components for the server.
73+ // This is intentionally deferred until Start() so NewServer remains lightweight.
74+ func (s * Server ) initCacheRuntime () {
75+ if s .demoMode || s .cacheManager != nil {
76+ return
77+ }
78+
79+ cacheCfg := cache .DefaultConfig ()
80+
81+ // If settings weren't loaded during construction, best-effort load them now.
82+ if s .cacheSettings == nil {
83+ settings , err := cache .LoadSettings (cacheCfg .BasePath )
84+ if err != nil {
85+ return
86+ }
87+ s .cacheSettings = settings
88+ }
89+
90+ // Respect cache enablement from settings.
91+ if ! s .cacheSettings .IsCacheEnabled () {
92+ return
93+ }
94+
95+ cacheCfg = s .cacheSettings .ToConfig (cacheCfg .BasePath )
96+
97+ cacheManager , err := cache .NewManager (cacheCfg )
98+ if err != nil {
99+ return
100+ }
101+ s .cacheManager = cacheManager
102+
103+ photoDB , err := cache .OpenSharedDB (cacheCfg .BasePath , "photos.db" )
104+ if err != nil {
105+ return
106+ }
107+
108+ photoStore , err := cache .NewPhotoStore (photoDB , cacheCfg .BasePath , cache .DefaultPhotoTTL )
109+ if err != nil {
110+ return
111+ }
112+ s .photoStore = photoStore
113+
114+ // Prune expired photos asynchronously after startup.
115+ go func () {
116+ if pruned , err := photoStore .Prune (); err == nil && pruned > 0 {
117+ fmt .Fprintf (os .Stderr , "Pruned %d expired photos from cache\n " , pruned )
118+ }
119+ }()
120+ }
121+
90122// NewDemoServer creates an Air server in demo mode with sample data.
91123func NewDemoServer (addr string ) * Server {
92124 tmpl , err := loadTemplates ()
@@ -256,7 +288,10 @@ func (s *Server) Start() error {
256288 // Template-rendered index page
257289 mux .HandleFunc ("/" , s .handleIndex )
258290
259- // Start background sync if not in demo mode and cache is enabled
291+ // Initialize cache runtime components after routes are wired.
292+ s .initCacheRuntime ()
293+
294+ // Start background sync if cache is available and enabled.
260295 if ! s .demoMode && s .cacheManager != nil && s .cacheSettings != nil && s .cacheSettings .IsCacheEnabled () {
261296 s .startBackgroundSync ()
262297 }
0 commit comments