mirror of https://github.com/artifacthub/hub.git
84 lines
2.0 KiB
Go
84 lines
2.0 KiB
Go
package notification
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/artifacthub/hub/internal/hub"
|
|
"github.com/patrickmn/go-cache"
|
|
"github.com/spf13/viper"
|
|
)
|
|
|
|
const (
|
|
defaultNumWorkers = 2
|
|
cacheDefaultExpiration = 5 * time.Minute
|
|
cacheCleanupInterval = 10 * time.Minute
|
|
)
|
|
|
|
// Services is a wrapper around several internal services used to handle
|
|
// notifications deliveries.
|
|
type Services struct {
|
|
DB hub.DB
|
|
ES hub.EmailSender
|
|
NotificationManager hub.NotificationManager
|
|
SubscriptionManager hub.SubscriptionManager
|
|
RepositoryManager hub.RepositoryManager
|
|
PackageManager hub.PackageManager
|
|
HTTPClient hub.HTTPClient
|
|
}
|
|
|
|
// Dispatcher handles a group of workers in charge of delivering notifications.
|
|
type Dispatcher struct {
|
|
numWorkers int
|
|
workers []*Worker
|
|
}
|
|
|
|
// NewDispatcher creates a new Dispatcher instance.
|
|
func NewDispatcher(cfg *viper.Viper, svc *Services, opts ...func(d *Dispatcher)) *Dispatcher {
|
|
// Setup dispatcher
|
|
d := &Dispatcher{
|
|
numWorkers: defaultNumWorkers,
|
|
}
|
|
for _, o := range opts {
|
|
o(d)
|
|
}
|
|
|
|
// Setup and launch workers
|
|
c := cache.New(cacheDefaultExpiration, cacheCleanupInterval)
|
|
baseURL := cfg.GetString("server.baseURL")
|
|
d.workers = make([]*Worker, 0, d.numWorkers)
|
|
for i := 0; i < d.numWorkers; i++ {
|
|
d.workers = append(d.workers, NewWorker(svc, c, baseURL))
|
|
}
|
|
|
|
return d
|
|
}
|
|
|
|
// WithNumWorkers allows providing a specific number of workers for a
|
|
// Dispatcher instance.
|
|
func WithNumWorkers(n int) func(d *Dispatcher) {
|
|
return func(d *Dispatcher) {
|
|
d.numWorkers = n
|
|
}
|
|
}
|
|
|
|
// Run starts the workers and lets them run until the dispatcher is asked to
|
|
// stop via the context provided.
|
|
func (d *Dispatcher) Run(ctx context.Context, wg *sync.WaitGroup) {
|
|
defer wg.Done()
|
|
|
|
// Start workers
|
|
wwg := &sync.WaitGroup{}
|
|
wctx, stopWorkers := context.WithCancel(context.Background())
|
|
for _, w := range d.workers {
|
|
wwg.Add(1)
|
|
go w.Run(wctx, wwg)
|
|
}
|
|
|
|
// Stop workers when dispatcher is asked to stop
|
|
<-ctx.Done()
|
|
stopWorkers()
|
|
wwg.Wait()
|
|
}
|