From 5509e0d1a4821acb1caaa2689965c18df17659fd Mon Sep 17 00:00:00 2001
From: Runxi Yu <me@runxiyu.org>
Date: Tue, 25 Mar 2025 02:58:46 +0800
Subject: [PATCH] Use cache for raw files too

---
 cache.go                | 14 ++++++++++++++
 http_handle_repo_raw.go | 32 +++++++++++++++++++++++++++++++-

diff --git a/cache.go b/cache.go
index 7259e3840714a93ed180cf2481d180818163b16e..59c400455b0d1f659cf90a9ac9eb1486494033f3 100644
--- a/cache.go
+++ b/cache.go
@@ -58,3 +58,17 @@ 	if err != nil {
 		clog.Fatal(1, "Error initializing commitPathFileHTMLCache: "+err.Error())
 	}
 }
+
+var commitPathFileRawCache *ristretto.Cache[[]byte, string]
+
+func init() {
+	var err error
+	commitPathFileRawCache, err = ristretto.NewCache(&ristretto.Config[[]byte, string]{
+		NumCounters: 1e4,
+		MaxCost:     1 << 60,
+		BufferItems: 8192,
+	})
+	if err != nil {
+		clog.Fatal(1, "Error initializing commitPathFileRawCache: "+err.Error())
+	}
+}
diff --git a/http_handle_repo_raw.go b/http_handle_repo_raw.go
index 6b697207835f5e543bf5cd0a20f5a539cc3a2484..36e59d7b32f832158972831b44083047097e4ad8 100644
--- a/http_handle_repo_raw.go
+++ b/http_handle_repo_raw.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"net/http"
 	"strings"
+	"time"
 
 	"github.com/go-git/go-git/v5"
 	"github.com/go-git/go-git/v5/plumbing"
@@ -17,6 +18,7 @@ func httpHandleRepoRaw(writer http.ResponseWriter, request *http.Request, params map[string]any) {
 	var rawPathSpec, pathSpec string
 	var repo *git.Repository
 	var refHash plumbing.Hash
+	var refHashSlice []byte
 	var commitObj *object.Commit
 	var tree *object.Tree
 	var err error
@@ -29,6 +31,19 @@ 	if refHash, err = getRefHash(repo, params["ref_type"].(string), params["ref_name"].(string)); err != nil {
 		errorPage500(writer, params, "Error getting ref hash: "+err.Error())
 		return
 	}
+	refHashSlice = refHash[:]
+
+	cacheHandle := append(refHashSlice, []byte(pathSpec)...)
+
+	if value, found := treeReadmeCache.Get(cacheHandle); found {
+		params["files"] = value.DisplayTree
+		renderTemplate(writer, "repo_raw_dir", params)
+		return
+	}
+	if value, found := commitPathFileRawCache.Get(cacheHandle); found {
+		fmt.Fprint(writer, value)
+		return
+	}
 
 	if commitObj, err = repo.CommitObject(refHash); err != nil {
 		errorPage500(writer, params, "Error getting commit object: "+err.Error())
@@ -39,6 +54,7 @@ 		errorPage500(writer, params, "Error getting file tree: "+err.Error())
 		return
 	}
 
+	start := time.Now()
 	var target *object.Tree
 	if pathSpec == "" {
 		target = tree
@@ -57,6 +73,8 @@ 			if fileContent, err = file.Contents(); err != nil {
 				errorPage500(writer, params, "Error reading file: "+err.Error())
 				return
 			}
+			cost := time.Since(start).Nanoseconds()
+			commitPathFileRawCache.Set(cacheHandle, fileContent, cost)
 			fmt.Fprint(writer, fileContent)
 			return
 		}
@@ -66,7 +84,19 @@ 	if redirectDir(writer, request) {
 		return
 	}
 
-	params["files"] = makeDisplayTree(target)
+	displayTree := makeDisplayTree(target)
+	readmeFilename, readmeRendered := renderReadmeAtTree(target)
+	cost := time.Since(start).Nanoseconds()
+
+	params["files"] = displayTree
+	params["readme_filename"] = readmeFilename
+	params["readme"] = readmeRendered
+
+	treeReadmeCache.Set(cacheHandle, treeReadmeCacheEntry{
+		DisplayTree:    displayTree,
+		ReadmeFilename: readmeFilename,
+		ReadmeRendered: readmeRendered,
+	}, cost)
 
 	renderTemplate(writer, "repo_raw_dir", params)
 }

-- 
2.48.1