forked from Botanical/BotanJS
90 lines
1.4 KiB
Go
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)
|
|
}
|