Skip to content

Commit

Permalink
feat: add status display (#2721)
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartwdouglas authored Sep 19, 2024
1 parent 4546243 commit e8ad733
Show file tree
Hide file tree
Showing 6 changed files with 449 additions and 4 deletions.
4 changes: 3 additions & 1 deletion backend/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import (
"github.com/TBD54566975/ftl/internal/rpc/headers"
"github.com/TBD54566975/ftl/internal/sha256"
"github.com/TBD54566975/ftl/internal/slices"
"github.com/TBD54566975/ftl/internal/status"
)

// CommonConfig between the production controller and development server.
Expand Down Expand Up @@ -1753,7 +1754,7 @@ func (s *Service) syncRoutes(ctx context.Context) (ret time.Duration, err error)
// Which is what makes as a deployment 'live' from a clients POV
optURI, err := s.runnerScaling.GetEndpointForDeployment(ctx, v.Module, v.Key.String())
if err != nil {
deploymentLogger.Errorf(err, "Failed to get updated endpoint for deployment %s", v.Key.String())
deploymentLogger.Debugf("Failed to get updated endpoint for deployment %s", v.Key.String())
continue
} else if uri, ok := optURI.Get(); ok {
// Check if this is a new route
Expand All @@ -1767,6 +1768,7 @@ func (s *Service) syncRoutes(ctx context.Context) (ret time.Duration, err error)
continue
}
deploymentLogger.Infof("Deployed %s", v.Key.String())
status.UpdateModuleState(ctx, v.Module, status.BuildStateDeployed)
}
if prev, ok := newRoutes[v.Module]; ok {
// We have already seen a route for this module, the existing route must be an old one
Expand Down
6 changes: 5 additions & 1 deletion frontend/cli/cmd_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/TBD54566975/ftl/internal/lsp"
"github.com/TBD54566975/ftl/internal/projectconfig"
"github.com/TBD54566975/ftl/internal/rpc"
"github.com/TBD54566975/ftl/internal/status"
)

type devCmd struct {
Expand All @@ -28,6 +29,7 @@ type devCmd struct {
}

func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error {

if len(d.Build.Dirs) == 0 {
d.Build.Dirs = projConfig.AbsModuleDirs()
}
Expand All @@ -52,7 +54,8 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
fmt.Println(dsn)
return nil
}

sm := status.FromContext(ctx)
starting := sm.NewStatus("\u001B[92mStarting FTL Server 🚀\u001B[39m")
// cmdServe will notify this channel when startup commands are complete and the controller is ready
controllerReady := make(chan bool, 1)
if !d.NoServe {
Expand All @@ -78,6 +81,7 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
return nil
case <-controllerReady:
}
starting.Close()

opts := []buildengine.Option{buildengine.Parallelism(d.Build.Parallelism), buildengine.BuildEnv(d.Build.BuildEnv), buildengine.WithDevMode(true)}
if d.Lsp {
Expand Down
9 changes: 7 additions & 2 deletions frontend/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/TBD54566975/ftl/internal/log"
"github.com/TBD54566975/ftl/internal/projectconfig"
"github.com/TBD54566975/ftl/internal/rpc"
"github.com/TBD54566975/ftl/internal/status"
)

type CLI struct {
Expand All @@ -29,6 +30,7 @@ type CLI struct {

Authenticators map[string]string `help:"Authenticators to use for FTL endpoints." mapsep:"," env:"FTL_AUTHENTICATORS" placeholder:"HOST=EXE,…"`
Insecure bool `help:"Skip TLS certificate verification. Caution: susceptible to machine-in-the-middle attacks."`
Plain bool `help:"Use a plain console with no color or status line." env:"FTL_PLAIN"`

Interactive interactiveCmd `cmd:"" help:"Interactive mode." default:""`
Ping pingCmd `cmd:"" help:"Ping the FTL cluster."`
Expand Down Expand Up @@ -59,6 +61,7 @@ type CLI struct {
var cli CLI

func main() {
ctx, cancel := context.WithCancel(context.Background())
kctx := kong.Parse(&cli,
kong.Description(`FTL - Towards a 𝝺-calculus for large-scale systems`),
kong.Configuration(kongtoml.Loader, ".ftl.toml", "~/.ftl.toml"),
Expand All @@ -79,13 +82,15 @@ func main() {
},
)

if !cli.Plain {
sm := status.NewStatusManager(ctx)
ctx = sm.IntoContext(ctx)
}
rpc.InitialiseClients(cli.Authenticators, cli.Insecure)

// Set some envars for child processes.
os.Setenv("LOG_LEVEL", cli.LogConfig.Level.String())

ctx, cancel := context.WithCancel(context.Background())

logger := log.Configure(os.Stderr, cli.LogConfig)
ctx = log.ContextWithLogger(ctx, logger)

Expand Down
7 changes: 7 additions & 0 deletions internal/buildengine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/TBD54566975/ftl/internal/moduleconfig"
"github.com/TBD54566975/ftl/internal/rpc"
"github.com/TBD54566975/ftl/internal/slices"
"github.com/TBD54566975/ftl/internal/status"
)

type CompilerBuildError struct {
Expand Down Expand Up @@ -450,6 +451,7 @@ func (e *Engine) watchForModuleChanges(ctx context.Context, period time.Duration
if err != nil {
didError = true
e.reportBuildFailed(err)
status.UpdateModuleState(ctx, config.Module, status.BuildStateFailed)
logger.Errorf(err, "build and deploy failed for module %q", event.Module.Config.Module)
} else {
didUpdateDeployments = true
Expand Down Expand Up @@ -532,6 +534,7 @@ func (e *Engine) BuildAndDeploy(ctx context.Context, replicas int32, waitForDepl
return e.buildWithCallback(ctx, func(buildCtx context.Context, module Module) error {
buildGroup.Go(func() error {
e.modulesToBuild.Store(module.Config.Module, false)
status.UpdateModuleState(ctx, module.Config.Module, status.BuildStateDeploying)
return Deploy(buildCtx, module, replicas, waitForDeployOnline, e.client)
})
return nil
Expand Down Expand Up @@ -580,6 +583,8 @@ func (e *Engine) buildWithCallback(ctx context.Context, callback buildCallback,
}
e.moduleMetas.Store(name, moduleMeta{module: module})
mustBuild[name] = true

status.UpdateModuleState(ctx, name, status.BuildStateWaiting)
}
graph, err := e.Graph(moduleNames...)
if err != nil {
Expand Down Expand Up @@ -706,6 +711,7 @@ func (e *Engine) mustSchema(ctx context.Context, moduleName string, builtModules
//
// Assumes that all dependencies have been built and are available in "built".
func (e *Engine) build(ctx context.Context, moduleName string, builtModules map[string]*schema.Module, schemas chan<- *schema.Module) error {
status.UpdateModuleState(ctx, moduleName, status.BuildStateBuilding)
meta, ok := e.moduleMetas.Load(moduleName)
if !ok {
return fmt.Errorf("module %q not found", moduleName)
Expand All @@ -726,6 +732,7 @@ func (e *Engine) build(ctx context.Context, moduleName string, builtModules map[
if err != nil {
return fmt.Errorf("could not load schema for module %q: %w", config.Module, err)
}
status.UpdateModuleState(ctx, moduleName, status.BuildStateBuilt)
schemas <- moduleSchema
return nil
}
Expand Down
28 changes: 28 additions & 0 deletions internal/status/noop.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package status

import "context"

var _ StatusManager = &noopStatusManager{}
var _ StatusLine = &noopStatusLine{}

type noopStatusManager struct{}

func (r *noopStatusManager) SetModuleState(module string, state BuildState) {

}

func (r *noopStatusManager) IntoContext(ctx context.Context) context.Context {
return context.WithValue(ctx, statusKeyInstance, r)
}

type noopStatusLine struct{}

func (n noopStatusLine) SetMessage(message string) {
}

func (n noopStatusLine) Close() {
}

func (r *noopStatusManager) NewStatus(message string) StatusLine {
return &noopStatusLine{}
}
Loading

0 comments on commit e8ad733

Please sign in to comment.