Refactor to serve all responses from cached files on disk

- StoreOutput now returns output hash for immediate retrieval
- Cache misses now serve from disk file after storing (same as hits)
- Log served_bytes from actual io.Copy result (avoids stat calls)
- Remove ContentLength field usage for cache hits (stream from file)
- Fix tests to properly check all return values
This commit is contained in:
2026-01-08 05:11:55 -08:00
parent 1a97f42cd8
commit 6304556837
4 changed files with 60 additions and 45 deletions

View File

@@ -88,10 +88,9 @@ func (s *Service) Get(ctx context.Context, req *ImageRequest) (*ImageResponse, e
// Fall through to re-fetch
} else {
return &ImageResponse{
Content: reader,
ContentLength: -1, // Unknown until read
ContentType: result.ContentType,
CacheStatus: CacheHit,
Content: reader,
ContentType: result.ContentType,
CacheStatus: CacheHit,
}, nil
}
}
@@ -152,27 +151,28 @@ func (s *Service) fetchAndProcess(ctx context.Context, req *ImageRequest) (*Imag
return nil, fmt.Errorf("image processing failed: %w", err)
}
// Read processed data to cache it
processedData, err := io.ReadAll(processResult.Content)
if err != nil {
return nil, fmt.Errorf("failed to read processed image: %w", err)
}
_ = processResult.Content.Close()
// Store output content
// Store output content to cache
metaID, err := s.cache.GetSourceMetadataID(ctx, req)
if err == nil {
err = s.cache.StoreOutput(ctx, req, metaID, bytes.NewReader(processedData), processResult.ContentType)
if err != nil {
s.log.Warn("failed to store output content", "error", err)
}
if err != nil {
return nil, fmt.Errorf("failed to get source metadata ID: %w", err)
}
outputHash, err := s.cache.StoreOutput(ctx, req, metaID, processResult.Content, processResult.ContentType)
_ = processResult.Content.Close()
if err != nil {
return nil, fmt.Errorf("failed to store output content: %w", err)
}
// Serve from the cached file on disk (same path as cache hits)
reader, err := s.cache.GetOutput(outputHash)
if err != nil {
return nil, fmt.Errorf("failed to read cached output: %w", err)
}
return &ImageResponse{
Content: io.NopCloser(bytes.NewReader(processedData)),
ContentLength: int64(len(processedData)),
ContentType: processResult.ContentType,
FetchedBytes: int64(len(sourceData)),
Content: reader,
ContentType: processResult.ContentType,
FetchedBytes: int64(len(sourceData)),
}, nil
}