Move utilitarian/generic packages to utils: lastfm, spotify, gravatar, cache, and pool

This commit is contained in:
Deluan
2021-02-09 11:33:26 -05:00
parent b855fe865e
commit 5fdd8b32d7
25 changed files with 8 additions and 8 deletions
+90
View File
@@ -0,0 +1,90 @@
package pool
import (
"time"
"github.com/navidrome/navidrome/log"
)
type Executor func(workload interface{})
type Pool struct {
name string
workers []worker
exec Executor
queue chan work // receives jobs to send to workers
done chan bool // when receives bool stops workers
working bool
}
// TODO This hardcoded value will go away when the queue is persisted in disk
const bufferSize = 10000
func NewPool(name string, workerCount int, exec Executor) (*Pool, error) {
p := &Pool{
name: name,
exec: exec,
queue: make(chan work, bufferSize),
done: make(chan bool),
working: false,
}
for i := 0; i < workerCount; i++ {
worker := worker{
p: p,
id: i,
}
worker.Start()
p.workers = append(p.workers, worker)
}
go func() {
ticker := time.NewTicker(10 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if len(p.queue) > 0 {
log.Debug("Queue status", "poolName", p.name, "items", len(p.queue))
} else {
if p.working {
log.Info("Queue is empty, all items processed", "poolName", p.name)
}
p.working = false
}
case <-p.done:
close(p.queue)
return
}
}
}()
return p, nil
}
func (p *Pool) Submit(workload interface{}) {
p.working = true
p.queue <- work{workload}
}
func (p *Pool) Stop() {
p.done <- true
}
type work struct {
workload interface{}
}
type worker struct {
id int
p *Pool
}
// start worker
func (w *worker) Start() {
go func() {
for job := range w.p.queue {
w.p.exec(job.workload) // do work
}
}()
}
+45
View File
@@ -0,0 +1,45 @@
package pool
import (
"testing"
"github.com/navidrome/navidrome/log"
"github.com/navidrome/navidrome/tests"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
func TestPool(t *testing.T) {
tests.Init(t, false)
log.SetLevel(log.LevelCritical)
RegisterFailHandler(Fail)
RunSpecs(t, "Pool Suite")
}
type testItem struct {
ID int
}
var processed []int
var _ = Describe("Pool", func() {
var pool *Pool
BeforeEach(func() {
processed = nil
pool, _ = NewPool("test", 2, execute)
})
It("processes items", func() {
for i := 0; i < 5; i++ {
pool.Submit(&testItem{ID: i})
}
Eventually(func() []int { return processed }, "10s").Should(HaveLen(5))
Expect(processed).To(ContainElements(0, 1, 2, 3, 4))
})
})
func execute(workload interface{}) {
item := workload.(*testItem)
processed = append(processed, item.ID)
}