Files
AstroJS/resolver-go/internal/compilecache/cache.go
T
2026-06-13 04:00:52 +08:00

90 lines
1.4 KiB
Go

package compilecache
import (
"context"
)
func New(compiler Compiler, workers int, queueSize int) *Cache {
if workers <= 0 {
workers = 1
}
if queueSize <= 0 {
queueSize = 128
}
c := &Cache{
compiler: compiler,
states: make(map[string]State),
results: make(map[string][]byte),
errors: make(map[string]error),
jobs: make(chan Job, queueSize),
}
for i := 0; i < workers; i++ {
go c.worker()
}
return c
}
func (c *Cache) Get(hash string) (State, []byte, error) {
c.mu.Lock()
defer c.mu.Unlock()
state, ok := c.states[hash]
if !ok {
return Missing, nil, nil
}
switch state {
case Ready:
return Ready, c.results[hash], nil
case Failed:
return Failed, nil, c.errors[hash]
default:
return state, nil, nil
}
}
func (c *Cache) Enqueue(job Job) State {
c.mu.Lock()
state, ok := c.states[job.Hash]
if ok {
c.mu.Unlock()
return state
}
c.states[job.Hash] = Pending
c.mu.Unlock()
// Do not hold the lock while sending.
c.jobs <- job
return Pending
}
func (c *Cache) worker() {
for job := range c.jobs {
c.run(job)
}
}
func (c *Cache) run(job Job) {
result, err := c.compiler.Compile(context.Background(), job)
c.mu.Lock()
defer c.mu.Unlock()
if err != nil {
c.states[job.Hash] = Failed
c.errors[job.Hash] = err
delete(c.results, job.Hash)
return
}
c.states[job.Hash] = Ready
c.results[job.Hash] = result
delete(c.errors, job.Hash)
}