summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEltrac <hi@guhub.cn>2025-11-21 13:46:10 +0800
committerEltrac <hi@guhub.cn>2025-11-21 13:46:10 +0800
commit5205a76de15203655f9807578c8b5586f98a82bc (patch)
treeb22d0aeead6000d364a8bf1bb42516846b0a8b2b
parent963b66e9e7047a188cc31319212d21a78cff49b0 (diff)
perf: cache stats for fasterlookup
-rw-r--r--brewcheck.go10
-rw-r--r--cache.go37
-rw-r--r--main.go35
-rw-r--r--statistics.go25
4 files changed, 87 insertions, 20 deletions
diff --git a/brewcheck.go b/brewcheck.go
index d550db4..02546b1 100644
--- a/brewcheck.go
+++ b/brewcheck.go
@@ -4,20 +4,17 @@ import (
"fmt"
"os"
"os/exec"
- "path/filepath"
"time"
- "github.com/adrg/xdg"
"github.com/fatih/color"
)
const TTL = 3 * 24 * time.Hour // 3 days
+const cacheName = "brew-checked"
func EnsureBrewAvailable() {
- cache := filepath.Join(xdg.CacheHome, "wthis", "brew-checked")
-
// 1. check if cache file exists and is fresh
- data, _ := os.ReadFile(cache)
+ data, _ := ReadCache(cacheName, TTL)
t, _ := time.Parse(time.RFC3339, string(data))
if time.Since(t) < TTL {
return
@@ -32,6 +29,5 @@ func EnsureBrewAvailable() {
}
// 3. write cache
- _ = os.MkdirAll(filepath.Dir(cache), 0o755)
- _ = os.WriteFile(cache, []byte(time.Now().Format(time.RFC3339)), 0o644)
+ WriteCache(cacheName, []byte(time.Now().Format(time.RFC3339)))
}
diff --git a/cache.go b/cache.go
new file mode 100644
index 0000000..d0b11e5
--- /dev/null
+++ b/cache.go
@@ -0,0 +1,37 @@
+package main
+
+import (
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/adrg/xdg"
+)
+
+func CachePath(rel string) string {
+ path := filepath.Join(xdg.CacheHome, "wthis", rel)
+ _ = os.MkdirAll(filepath.Dir(path), 0o755)
+ return path
+}
+
+func ReadCache(relPath string, ttl time.Duration) ([]byte, bool) {
+ path := CachePath(relPath)
+
+ info, err := os.Stat(path)
+ if err != nil {
+ return nil, false
+ }
+ if time.Since(info.ModTime()) > ttl {
+ return nil, false
+ }
+ b, err := os.ReadFile(path)
+ if err != nil {
+ return nil, false
+ }
+ return b, true
+}
+
+func WriteCache(relPath string, data []byte) error {
+ path := CachePath(relPath)
+ return os.WriteFile(path, data, 0o644)
+}
diff --git a/main.go b/main.go
index fb72972..ae02d5f 100644
--- a/main.go
+++ b/main.go
@@ -24,21 +24,30 @@ func main() {
pkgName := cmd.Args().First()
// prompt
showLoadingPrompt(fmt.Sprintf("What the heck is \"%s\"", pkgName))
- // search, tidy up, and print
- fmlChan := make(chan *FormulaInfo)
- caskChan := make(chan *CaskInfo)
- rvsChan := make(chan []string)
- go func() {
- formula, cask := GetBrewInfo(pkgName)
- fmlChan <- formula
- caskChan <- cask
- }()
- go func() {
- rvsChan <- GetBrewUses(pkgName)
- }()
- stat := NewStatistics(<-fmlChan, <-caskChan, pkgName,<-rvsChan)
+ // try reading from cache
+ var stat *statistics
+ if stat = NewStatisticsFromCache(pkgName); stat == nil {
+ fmt.Println("cache not hit")
+ // cache not hit, then search
+ fmlChan := make(chan *FormulaInfo)
+ caskChan := make(chan *CaskInfo)
+ rvsChan := make(chan []string)
+ // start 2 goroutines, fetching formula/cask info and uses
+ go func() {
+ formula, cask := GetBrewInfo(pkgName)
+ fmlChan <- formula
+ caskChan <- cask
+ }()
+ go func() {
+ rvsChan <- GetBrewUses(pkgName)
+ }()
+ stat = NewStatistics(<-fmlChan, <-caskChan, pkgName,<-rvsChan)
+ stat.Cache()
+ }
+ // print
hideLoadingPrompt()
stat.Print()
+
return nil
},
}
diff --git a/statistics.go b/statistics.go
index 17a01d9..9feaf05 100644
--- a/statistics.go
+++ b/statistics.go
@@ -1,6 +1,7 @@
package main
import (
+ "encoding/json"
"fmt"
"os"
"path/filepath"
@@ -9,6 +10,7 @@ import (
)
type statistics struct {
+ PkgName string
Name string
Type string //formula or cask
Desc string
@@ -26,6 +28,8 @@ type statistics struct {
ReverseDependencies []string
}
+const dataTTL = time.Hour / 2
+
func NewStatistics(formula *FormulaInfo, cask *CaskInfo, pkgName string, rvs []string) *statistics {
var statObject statistics
@@ -59,6 +63,8 @@ func NewStatistics(formula *FormulaInfo, cask *CaskInfo, pkgName string, rvs []s
// === general === //
+ statObject.PkgName = pkgName
+
// get system atime
var atime time.Time
binPath := filepath.Join("/opt/homebrew/bin", pkgName)
@@ -75,6 +81,25 @@ func NewStatistics(formula *FormulaInfo, cask *CaskInfo, pkgName string, rvs []s
return &statObject
}
+func NewStatisticsFromCache(pkgName string) *statistics {
+ raw, success := ReadCache("pkg/"+pkgName+".json", dataTTL)
+ if success {
+ var stat statistics
+ json.Unmarshal(raw, &stat)
+ return &stat
+ }
+ return nil
+}
+
+func (s *statistics) Cache() {
+ data, err := json.Marshal(s)
+ if err != nil {
+ fmt.Println("Error marshaling statistics:", err)
+ return
+ }
+ WriteCache("pkg/"+s.PkgName+".json", data)
+}
+
func (s *statistics) Print() {
if s == nil {
fmt.Println("Package not found.")