Skip to content

Commit 4eca67d

Browse files
committed
add cache to the healthcheck
1 parent fb806d4 commit 4eca67d

File tree

1 file changed

+58
-18
lines changed

1 file changed

+58
-18
lines changed

core/utils.go

Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"log"
1010
"net/http"
1111
"os"
12+
"sync"
1213
"time"
1314

1415
"github.com/skip2/go-qrcode"
@@ -111,6 +112,16 @@ func TimeUntilExpiration(expiration *time.Time) string {
111112
return ""
112113
}
113114

115+
var (
116+
lastStatusCode int
117+
lastStatus string
118+
lastDBStatus string
119+
lastModTime time.Time
120+
lastSize int64
121+
cacheMu sync.RWMutex
122+
cacheInit bool
123+
)
124+
114125
// Application health check
115126
func HealthCheck(w http.ResponseWriter, r *http.Request) {
116127
statusCode := http.StatusOK
@@ -123,34 +134,63 @@ func HealthCheck(w http.ResponseWriter, r *http.Request) {
123134
dbStatus = "missing_file"
124135
} else {
125136
// Check DB file exists
126-
if info, err := os.Stat(db.DBPath); os.IsNotExist(err) {
137+
info, err := os.Stat(db.DBPath)
138+
if os.IsNotExist(err) {
127139
statusCode = http.StatusInternalServerError
128140
status = "error"
129141
dbStatus = "missing_file"
130-
} else if info.Size() < 100 {
131-
// File too small to be valid sqlite
142+
} else if err != nil {
132143
statusCode = http.StatusInternalServerError
133144
status = "error"
134-
dbStatus = "corrupted"
145+
dbStatus = "unreachable"
135146
} else {
136-
// Open a new connection to check integrity
137-
tmpDB, err := gorm.Open(sqlite.Open(db.DBPath), &gorm.Config{})
138-
if err != nil {
139-
statusCode = http.StatusInternalServerError
140-
status = "error"
141-
dbStatus = "corrupted"
142-
} else {
143-
var result int
144-
if err := tmpDB.Raw("SELECT 1").Scan(&result).Error; err != nil || result != 1 {
147+
// Only re-check if cache initialized and file unchanged
148+
cacheMu.RLock()
149+
cached := cacheInit && info.ModTime().Equal(lastModTime) && info.Size() == lastSize
150+
if cached {
151+
statusCode = lastStatusCode
152+
status = lastStatus
153+
dbStatus = lastDBStatus
154+
}
155+
cacheMu.RUnlock()
156+
157+
if !cached {
158+
if info.Size() < 100 {
159+
// File too small to be valid sqlite
145160
statusCode = http.StatusInternalServerError
146161
status = "error"
147-
dbStatus = "unreachable"
162+
dbStatus = "corrupted"
163+
} else {
164+
// Open a new connection to check integrity
165+
tmpDB, err := gorm.Open(sqlite.Open(db.DBPath), &gorm.Config{})
166+
if err != nil {
167+
statusCode = http.StatusInternalServerError
168+
status = "error"
169+
dbStatus = "corrupted"
170+
} else {
171+
var result int
172+
if err := tmpDB.Raw("SELECT 1").Scan(&result).Error; err != nil || result != 1 {
173+
statusCode = http.StatusInternalServerError
174+
status = "error"
175+
dbStatus = "unreachable"
176+
}
177+
178+
// Close underlying connection pool to avoid memory leaks
179+
if sqlDB, err := tmpDB.DB(); err == nil {
180+
sqlDB.Close()
181+
}
182+
}
148183
}
149184

150-
// Close underlying connection pool to avoid memory leaks
151-
if sqlDB, err := tmpDB.DB(); err == nil {
152-
sqlDB.Close()
153-
}
185+
// Update cache after full check
186+
cacheMu.Lock()
187+
lastStatusCode = statusCode
188+
lastStatus = status
189+
lastDBStatus = dbStatus
190+
lastModTime = info.ModTime()
191+
lastSize = info.Size()
192+
cacheInit = true
193+
cacheMu.Unlock()
154194
}
155195
}
156196
}

0 commit comments

Comments
 (0)