orchard/internal/controller/controller.go

98 lines
2.1 KiB
Go

package controller
import (
"context"
"crypto/tls"
"errors"
"fmt"
storepkg "github.com/cirruslabs/orchard/internal/controller/store"
"github.com/cirruslabs/orchard/internal/controller/store/badger"
"go.uber.org/zap"
"net"
"net/http"
"time"
)
var ErrInitFailed = errors.New("controller initialization failed")
type Controller struct {
dataDir *DataDir
listenAddr string
tlsConfig *tls.Config
listener net.Listener
httpServer *http.Server
store storepkg.Store
logger *zap.SugaredLogger
}
func New(opts ...Option) (*Controller, error) {
controller := &Controller{}
// Apply options
for _, opt := range opts {
opt(controller)
}
// Apply defaults
if controller.dataDir == nil {
return nil, fmt.Errorf("%w: please specify the data directory path with WithDataDir()",
ErrInitFailed)
}
if controller.listenAddr == "" {
controller.listenAddr = ":6120"
}
if controller.logger == nil {
controller.logger = zap.NewNop().Sugar()
}
// Instantiate controller
store, err := badger.NewBadgerStore(controller.dataDir.DBPath())
if err != nil {
return nil, err
}
controller.store = store
listener, err := net.Listen("tcp", controller.listenAddr)
if err != nil {
return nil, err
}
if controller.tlsConfig != nil {
controller.listener = tls.NewListener(listener, controller.tlsConfig)
} else {
controller.listener = listener
}
controller.httpServer = &http.Server{
Handler: controller.initAPI(),
ReadTimeout: 5 * time.Second,
}
return controller, nil
}
func (controller *Controller) Run(ctx context.Context) error {
// Run the scheduler so that each VM will eventually
// be assigned to a specific Worker
go func() {
err := runScheduler(controller.store)
if err != nil {
panic(err)
}
}()
// A helper function to shut down the HTTP server on context cancellation
go func() {
<-ctx.Done()
if err := controller.httpServer.Shutdown(ctx); err != nil {
controller.logger.Errorf("failed to cleanly shutdown the HTTP server: %v", err)
}
}()
if err := controller.httpServer.Serve(controller.listener); err != nil {
return err
}
return nil
}