建立单进程组件运行时
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
// Package controller composes independently runnable scheduler and backend workers.
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
type ComponentName string
|
||||
|
||||
const (
|
||||
Scheduler ComponentName = "scheduler"
|
||||
PodWorker ComponentName = "pod-worker"
|
||||
VMWorker ComponentName = "vm-worker"
|
||||
)
|
||||
|
||||
var defaultComponents = []ComponentName{Scheduler, PodWorker, VMWorker}
|
||||
|
||||
// Selection parses --components. An empty value enables all components.
|
||||
type Selection []ComponentName
|
||||
|
||||
func ParseSelection(value string) (Selection, error) {
|
||||
if strings.TrimSpace(value) == "" || strings.TrimSpace(value) == "all" {
|
||||
return append(Selection(nil), defaultComponents...), nil
|
||||
}
|
||||
var selected Selection
|
||||
for _, raw := range strings.Split(value, ",") {
|
||||
name := ComponentName(strings.TrimSpace(raw))
|
||||
if !slices.Contains(defaultComponents, name) {
|
||||
return nil, fmt.Errorf("unknown controller component %q", name)
|
||||
}
|
||||
if !slices.Contains(selected, name) {
|
||||
selected = append(selected, name)
|
||||
}
|
||||
}
|
||||
if len(selected) == 0 {
|
||||
return nil, errors.New("at least one controller component is required")
|
||||
}
|
||||
return selected, nil
|
||||
}
|
||||
|
||||
type Component interface {
|
||||
Run(context.Context) error
|
||||
}
|
||||
|
||||
type Registry map[ComponentName]Component
|
||||
|
||||
// Run starts exactly the selected components in one process. The first real
|
||||
// failure cancels its peers; ordinary context cancellation is graceful.
|
||||
func Run(ctx context.Context, selection Selection, registry Registry) error {
|
||||
group, groupContext := errgroup.WithContext(ctx)
|
||||
for _, name := range selection {
|
||||
component, ok := registry[name]
|
||||
if !ok || component == nil {
|
||||
return fmt.Errorf("component %q is not configured", name)
|
||||
}
|
||||
name, component := name, component
|
||||
group.Go(func() error {
|
||||
err := component.Run(groupContext)
|
||||
if errors.Is(err, context.Canceled) && groupContext.Err() != nil {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("component %s: %w", name, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
return group.Wait()
|
||||
}
|
||||
Reference in New Issue
Block a user