Files
AstroJS/resolver-go/internal/closure/cache.go
T
2026-06-12 13:28:39 +08:00

88 lines
1.6 KiB
Go

package closure
import (
"context"
"errors"
"log"
"time"
)
func NewCompileCache(workers int) *CompileCache {
c := &CompileCache{
client: NewClientFromEnv(),
states: make(map[string]CompileState),
results: make(map[string][]byte),
errors: make(map[string]error),
jobs: make(chan CompileJob, 128),
}
for i := 0; i < workers; i++ {
go c.worker()
}
return c
}
func (c *CompileCache) Get(hash string) ([]byte, bool) {
c.mu.Lock()
defer c.mu.Unlock()
if c.states[hash] != CompileReady {
return nil, false
}
return c.results[hash], true
}
func (c *CompileCache) Enqueue(job CompileJob) {
c.mu.Lock()
switch c.states[job.Hash] {
case CompilePending, CompileReady:
c.mu.Unlock()
return
}
c.states[job.Hash] = CompilePending
c.mu.Unlock()
select {
case c.jobs <- job:
default:
// Queue full. Don't block request path.
c.mu.Lock()
c.states[job.Hash] = CompileMissing
c.errors[job.Hash] = errors.New("compile queue full")
c.mu.Unlock()
}
}
func (c *CompileCache) worker() {
for job := range c.jobs {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
req := CompileRequest{
ExternSources: job.ExternSources,
JSSources: job.JSSources,
Defines: job.Defines,
}
c.client.DebugPrintCurl(ctx, req)
out, err := c.client.Compile(ctx, req)
cancel()
c.mu.Lock()
if err == nil {
c.states[job.Hash] = CompileReady
c.results[job.Hash] = out
delete(c.errors, job.Hash)
} else {
log.Printf("compile failed: %v", err)
c.states[job.Hash] = CompileFailed
c.errors[job.Hash] = err
}
c.mu.Unlock()
}
}