fix: validate cache data and suppress static file logging
This commit is contained in:
@@ -41,12 +41,15 @@ RUN apt-get update && apt-get install -y ca-certificates sqlite3 && rm -rf /var/
|
|||||||
RUN mkdir -p /app/data
|
RUN mkdir -p /app/data
|
||||||
|
|
||||||
COPY --from=builder /app/main_server .
|
COPY --from=builder /app/main_server .
|
||||||
|
COPY --from=builder /app/entrypoint.sh .
|
||||||
COPY --from=builder /app/static ./static
|
COPY --from=builder /app/static ./static
|
||||||
COPY --from=builder /app/dist ./dist
|
COPY --from=builder /app/dist ./dist
|
||||||
COPY --from=builder /app/migrations ./migrations
|
COPY --from=builder /app/migrations ./migrations
|
||||||
|
|
||||||
|
RUN chmod +x ./entrypoint.sh
|
||||||
|
|
||||||
# Expose the application port
|
# Expose the application port
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
|
|
||||||
# Run entrypoint which handles migrations
|
# Run entrypoint which handles migrations and cache clearing
|
||||||
CMD ["./main_server"]
|
ENTRYPOINT ["./entrypoint.sh"]
|
||||||
|
|||||||
11
entrypoint.sh
Normal file
11
entrypoint.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Clear potentially corrupted Jikan cache entries on each deploy
|
||||||
|
DB_FILE="${DATABASE_FILE:-/app/data/mal.db}"
|
||||||
|
if [ -f "$DB_FILE" ]; then
|
||||||
|
sqlite3 "$DB_FILE" "DELETE FROM jikan_cache WHERE key LIKE 'top:%';" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start the server
|
||||||
|
exec ./main_server
|
||||||
@@ -232,10 +232,27 @@ type cacheResult struct {
|
|||||||
hasStale bool
|
hasStale bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isEmptyResult(out any) bool {
|
||||||
|
switch v := out.(type) {
|
||||||
|
case *TopAnimeResponse:
|
||||||
|
return len(v.Data) == 0
|
||||||
|
case *SearchResponse:
|
||||||
|
return len(v.Data) == 0
|
||||||
|
case *AnimeResponse:
|
||||||
|
return v.Data.MalID == 0
|
||||||
|
case *EpisodesResponse:
|
||||||
|
return len(v.Data) == 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) getWithCache(ctx context.Context, cacheKey string, ttl time.Duration, url string, out any) error {
|
func (c *Client) getWithCache(ctx context.Context, cacheKey string, ttl time.Duration, url string, out any) error {
|
||||||
if c.getCache(ctx, cacheKey, out) {
|
if c.getCache(ctx, cacheKey, out) {
|
||||||
|
if !isEmptyResult(out) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
log.Printf("jikan: cache hit for %s but data is empty, refetching", cacheKey)
|
||||||
|
}
|
||||||
|
|
||||||
var stale any
|
var stale any
|
||||||
hasStale := c.getStaleCache(ctx, cacheKey, &stale)
|
hasStale := c.getStaleCache(ctx, cacheKey, &stale)
|
||||||
@@ -245,11 +262,11 @@ func (c *Client) getWithCache(ctx context.Context, cacheKey string, ttl time.Dur
|
|||||||
staleBytes, marshalErr := json.Marshal(stale)
|
staleBytes, marshalErr := json.Marshal(stale)
|
||||||
if marshalErr == nil {
|
if marshalErr == nil {
|
||||||
unmarshalErr := json.Unmarshal(staleBytes, out)
|
unmarshalErr := json.Unmarshal(staleBytes, out)
|
||||||
if unmarshalErr == nil {
|
if unmarshalErr == nil && !isEmptyResult(out) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Printf("jikan: stale cache unmarshal failed, falling back to error: %v", err)
|
log.Printf("jikan: stale cache unmarshal failed or empty, falling back to error: %v", err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -67,6 +68,14 @@ func (rw *statusRecorder) Unwrap() http.ResponseWriter {
|
|||||||
func RequestLogger(next http.Handler) http.Handler {
|
func RequestLogger(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
|
if strings.HasPrefix(r.URL.Path, "/dist/static/") ||
|
||||||
|
strings.HasPrefix(r.URL.Path, "/static/") ||
|
||||||
|
r.URL.Path == "/favicon.ico" {
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
recorder := newStatusRecorder(w)
|
recorder := newStatusRecorder(w)
|
||||||
|
|
||||||
next.ServeHTTP(recorder, r)
|
next.ServeHTTP(recorder, r)
|
||||||
|
|||||||
Reference in New Issue
Block a user