From 5d8ae028f743a8d206cb9cfb38a42ceef9ef4ccd Mon Sep 17 00:00:00 2001 From: David Moore <4121492+davemooreuws@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:08:33 +1100 Subject: [PATCH] fix: wait till services have started before opening dashboard (#590) * fix: wait till services have started before starting dashboard * fix: remove log dep to avoid tui hang in stmux --------- Co-authored-by: Jye Cusch --- .github/workflows/dashboard-test.yaml | 1 + go.mod | 7 ++---- go.sum | 6 ----- pkg/dashboard/serve.go | 33 ++++++++++++++++++--------- pkg/logger/simple.go | 31 ------------------------- pkg/operations/local_run/local_run.go | 10 +++++--- pkg/operations/start/start.go | 10 ++++++-- pkg/operations/version/version.go | 4 ++-- pkg/run/gateway.go | 17 +++++++------- pkg/run/run.go | 21 ++++------------- 10 files changed, 55 insertions(+), 85 deletions(-) delete mode 100644 pkg/logger/simple.go diff --git a/.github/workflows/dashboard-test.yaml b/.github/workflows/dashboard-test.yaml index f3b5bae06..1f55f90bf 100644 --- a/.github/workflows/dashboard-test.yaml +++ b/.github/workflows/dashboard-test.yaml @@ -46,6 +46,7 @@ jobs: - name: Run nitric start with test-app in the background run: | cd ${{ github.workspace }}/cli/dashboard/test-app + npm install -g node-gyp yarn install nitric start & yarn dev:functions & diff --git a/go.mod b/go.mod index 522f1d936..fdd837263 100644 --- a/go.mod +++ b/go.mod @@ -50,11 +50,12 @@ require ( github.com/charmbracelet/bubbles v0.16.1 github.com/charmbracelet/bubbletea v0.24.2 github.com/charmbracelet/lipgloss v0.8.0 - github.com/charmbracelet/log v0.2.4 github.com/docker/distribution v2.8.0+incompatible github.com/fasthttp/websocket v1.5.3 + github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e github.com/mitchellh/mapstructure v1.5.0 github.com/nitrictech/nitric/cloud/common v0.0.0-20230710061936-f8ccb102d31b + github.com/nitrictech/pearls v0.0.0-20230927035425-dc9ec468bb24 github.com/olahol/melody v1.1.3 github.com/samber/lo v1.38.1 github.com/seaweedfs/seaweedfs v0.0.0-20230109022022-51d4a4b28d0e @@ -166,7 +167,6 @@ require ( github.com/fzipp/gocyclo v0.6.0 // indirect github.com/go-critic/go-critic v0.8.1 // indirect github.com/go-errors/errors v1.1.1 // indirect - github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/errors v0.20.3 // indirect @@ -209,7 +209,6 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.1 // indirect github.com/gookit/color v1.5.3 // indirect - github.com/goombaio/namegenerator v0.0.0-20181006234301-989e774b106e // indirect github.com/gordonklaus/ineffassign v0.0.0-20230610083614-0e73809eb601 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -302,7 +301,6 @@ require ( github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 // indirect github.com/nishanths/exhaustive v0.11.0 // indirect github.com/nishanths/predeclared v0.2.2 // indirect - github.com/nitrictech/pearls v0.0.0-20230927035425-dc9ec468bb24 // indirect github.com/nitrictech/protoutils v0.0.0-20220321044654-02667a814cdf // indirect github.com/nunnatsa/ginkgolinter v0.12.1 // indirect github.com/oklog/ulid v1.3.1 // indirect @@ -340,7 +338,6 @@ require ( github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd // indirect github.com/ryancurrah/gomodguard v1.3.0 // indirect github.com/ryanrolds/sqlclosecheck v0.4.0 // indirect - github.com/sahilm/fuzzy v0.1.0 // indirect github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect github.com/sashamelentyev/interfacebloat v1.1.0 // indirect github.com/sashamelentyev/usestdlibvars v1.23.0 // indirect diff --git a/go.sum b/go.sum index c8fbfc438..58b6842fd 100644 --- a/go.sum +++ b/go.sum @@ -460,8 +460,6 @@ github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06 github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg= github.com/charmbracelet/lipgloss v0.8.0 h1:IS00fk4XAHcf8uZKc3eHeMUTCxUH6NkaTrdyCQk84RU= github.com/charmbracelet/lipgloss v0.8.0/go.mod h1:p4eYUZZJ/0oXTuCQKFF8mqyKCz0ja6y+7DniDDw5KKU= -github.com/charmbracelet/log v0.2.4 h1:3pKtq5/Y5QMKtcZt7kDqD1p9w7lICzHYQACBFY4ocHA= -github.com/charmbracelet/log v0.2.4/go.mod h1:nQGK8tvc4pS9cvVEH/pWJiZ50eUq1aoXUOjGpXvdD0k= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8 h1:W9o46d2kbNL06lq7UNDPV0zYLzkrde/bjIqO02eoll0= github.com/chavacava/garif v0.0.0-20230227094218-b8c73b2037b8/go.mod h1:gakxgyXaaPkxvLw1XQxNGK4I37ys9iBRzNUx/B7pUCo= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= @@ -803,8 +801,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= -github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= @@ -1937,8 +1933,6 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= github.com/safchain/ethtool v0.0.0-20210803160452-9aa261dae9b1/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= -github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= -github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= diff --git a/pkg/dashboard/serve.go b/pkg/dashboard/serve.go index cb7e959e1..667f840b3 100644 --- a/pkg/dashboard/serve.go +++ b/pkg/dashboard/serve.go @@ -70,7 +70,8 @@ type Dashboard struct { websocketsInfo map[string]*WebsocketInfo resourcesLastUpdated time.Time bucketNotifications []*codeconfig.BucketNotification - noBrowser bool + port int + hasStarted bool } type Api struct { @@ -111,7 +112,7 @@ type RefreshOptions struct { //go:embed dist/* var content embed.FS -func New(p *project.Project, envMap map[string]string, noBrowser bool) (*Dashboard, error) { +func New(p *project.Project, envMap map[string]string) (*Dashboard, error) { stackWebSocket := melody.New() historyWebSocket := melody.New() @@ -129,7 +130,7 @@ func New(p *project.Project, envMap map[string]string, noBrowser bool) (*Dashboa schedules: []*codeconfig.TopicResult{}, topics: []*codeconfig.TopicResult{}, websocketsInfo: map[string]*WebsocketInfo{}, - noBrowser: noBrowser, + hasStarted: false, }, nil } @@ -215,11 +216,11 @@ func (d *Dashboard) AddWebsocketInfoMessage(socket string, message WebsocketMess return nil } -func (d *Dashboard) Serve(storagePlugin storage.StorageService) (*int, error) { +func (d *Dashboard) Serve(storagePlugin storage.StorageService, noBrowser bool) error { // Get the embedded files from the 'dist' directory staticFiles, err := fs.Sub(content, "dist") if err != nil { - return nil, err + return err } fs := http.FileServer(http.FS(staticFiles)) @@ -309,7 +310,7 @@ func (d *Dashboard) Serve(storagePlugin storage.StorageService) (*int, error) { // using ephemeral ports, we will redirect to the dashboard on main api 4000 dashListener, err := utils.GetNextListener(utils.MinPort(49152), utils.MaxPort(65535)) if err != nil { - return nil, err + return err } serveFn := func() { @@ -320,17 +321,27 @@ func (d *Dashboard) Serve(storagePlugin storage.StorageService) (*int, error) { } go serveFn() - port := dashListener.Addr().(*net.TCPAddr).Port + d.port = dashListener.Addr().(*net.TCPAddr).Port // open browser - if !d.noBrowser { - err = openBrowser(fmt.Sprintf("http://localhost:%s", strconv.Itoa(port))) + if !noBrowser { + err = openBrowser(fmt.Sprintf("http://localhost:%s", strconv.Itoa(d.port))) if err != nil { - return nil, err + return err } } - return &port, nil + d.hasStarted = true + + return nil +} + +func (d *Dashboard) GetPort() int { + return d.port +} + +func (d *Dashboard) HasStarted() bool { + return d.hasStarted } func handleResponseWriter(w http.ResponseWriter, data []byte) { diff --git a/pkg/logger/simple.go b/pkg/logger/simple.go deleted file mode 100644 index 0b6410178..000000000 --- a/pkg/logger/simple.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright Nitric Pty Ltd. -// -// SPDX-License-Identifier: Apache-2.0 -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at: -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package logger - -import ( - "os" - - "github.com/charmbracelet/log" -) - -// Simple logger for printing out to the command line -var Simple = log.NewWithOptions( - os.Stdout, - log.Options{ - ReportTimestamp: false, - }, -) diff --git a/pkg/operations/local_run/local_run.go b/pkg/operations/local_run/local_run.go index bfc198d67..487538237 100644 --- a/pkg/operations/local_run/local_run.go +++ b/pkg/operations/local_run/local_run.go @@ -66,7 +66,7 @@ func Run(ctx context.Context) { utils.CheckErr(err) } - dash, err := dashboard.New(proj, envMap, true) + dash, err := dashboard.New(proj, envMap) if err != nil { utils.CheckErr(err) } @@ -155,10 +155,14 @@ func Run(ctx context.Context) { utils.CheckErr(err) } + // Start local dashboard + err = dash.Serve(ls.GetStorageService(), true) + utils.CheckErr(err) + stackState.Update(pool, ls) area, _ := pterm.DefaultArea.Start() - area.Update(stackState.Tables(9001, *ls.GetDashPort())) + area.Update(stackState.Tables(9001, dash.GetPort())) // Create a debouncer for the refresh and remove locking debounced := debounce.New(500 * time.Millisecond) @@ -173,7 +177,7 @@ func Run(ctx context.Context) { stackState.Update(pool, ls) - area.Update(stackState.Tables(9001, *ls.GetDashPort())) + area.Update(stackState.Tables(9001, dash.GetPort())) for _, warning := range stackState.Warnings() { pterm.Warning.Println(warning) diff --git a/pkg/operations/start/start.go b/pkg/operations/start/start.go index 7656b2302..e337dde8b 100644 --- a/pkg/operations/start/start.go +++ b/pkg/operations/start/start.go @@ -60,7 +60,7 @@ func Run(ctx context.Context, noBrowser bool) { History: history, } - dash, err := dashboard.New(proj, map[string]string{}, noBrowser || output.CI) + dash, err := dashboard.New(proj, map[string]string{}) utils.CheckErr(err) ls := run.NewLocalServices(proj, true, dash) @@ -118,9 +118,15 @@ func Run(ctx context.Context, noBrowser bool) { cobra.CheckErr(err) } + if !dash.HasStarted() { + // Start local dashboard + err = dash.Serve(ls.GetStorageService(), noBrowser || output.CI) + utils.CheckErr(err) + } + stackState.Update(pool, ls) - area.Update(stackState.Tables(9001, *ls.GetDashPort())) + area.Update(stackState.Tables(9001, dash.GetPort())) for _, warning := range stackState.Warnings() { pterm.Warning.Println(warning) diff --git a/pkg/operations/version/version.go b/pkg/operations/version/version.go index bf64977b0..74ccc2dba 100644 --- a/pkg/operations/version/version.go +++ b/pkg/operations/version/version.go @@ -18,11 +18,11 @@ package version import ( "context" + "fmt" - "github.com/nitrictech/cli/pkg/logger" "github.com/nitrictech/cli/pkg/version" ) func Run(ctx context.Context) { - logger.Simple.Print(version.Version) + fmt.Println(version.Version) } diff --git a/pkg/run/gateway.go b/pkg/run/gateway.go index 74d3f7825..50a7108cd 100644 --- a/pkg/run/gateway.go +++ b/pkg/run/gateway.go @@ -71,11 +71,10 @@ type BaseHttpGateway struct { websocketPlugin *RunWebsocketService serviceListener net.Listener gateway.UnimplementedGatewayPlugin - stop chan bool - pool pool.WorkerPool - dashPort int - project *project.Project - dash *dashboard.Dashboard + stop chan bool + pool pool.WorkerPool + project *project.Project + dash *dashboard.Dashboard } var _ gateway.GatewayService = &BaseHttpGateway{} @@ -183,7 +182,7 @@ func (s *BaseHttpGateway) handleHttpProxyRequest(idx int) fasthttp.RequestHandle Filter: httpWorkerFilter(port), }) if err != nil { - ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dashPort), fasthttp.StatusTemporaryRedirect) + ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dash.GetPort()), fasthttp.StatusTemporaryRedirect) return } @@ -266,7 +265,7 @@ func (s *BaseHttpGateway) handleApiHttpRequest(idx int) fasthttp.RequestHandler Filter: apiWorkerFilter(apiName), }) if err != nil { - ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dashPort), fasthttp.StatusTemporaryRedirect) + ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dash.GetPort()), fasthttp.StatusTemporaryRedirect) return } @@ -775,9 +774,9 @@ func (s *BaseHttpGateway) Start(pool pool.WorkerPool) error { r.NotFound = func(ctx *fasthttp.RequestCtx) { if string(ctx.Path()) == "/" { - ctx.Redirect(fmt.Sprintf("http://localhost:%v", s.dashPort), fasthttp.StatusMovedPermanently) + ctx.Redirect(fmt.Sprintf("http://localhost:%v", s.dash.GetPort()), fasthttp.StatusMovedPermanently) } else { - ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dashPort), fasthttp.StatusTemporaryRedirect) + ctx.Redirect(fmt.Sprintf("http://localhost:%v/not-found", s.dash.GetPort()), fasthttp.StatusTemporaryRedirect) } } diff --git a/pkg/run/run.go b/pkg/run/run.go index f83aeb5bc..ba8e342b1 100644 --- a/pkg/run/run.go +++ b/pkg/run/run.go @@ -41,7 +41,7 @@ type LocalServices interface { Websockets() map[string]string TriggerAddress() string GetWorkerPool() pool.WorkerPool - GetDashPort() *int + GetStorageService() *RunStorageService } type LocalServicesStatus struct { @@ -149,14 +149,6 @@ func (l *localServices) Status() *LocalServicesStatus { return l.status } -func (l *localServices) GetDashPort() *int { - if l.gateway != nil { - return &l.gateway.dashPort - } - - return nil -} - func (l *localServices) Start(pool pool.WorkerPool) error { var err error @@ -219,13 +211,6 @@ func (l *localServices) Start(pool pool.WorkerPool) error { return err } - // Start local dashboard - port, err := l.dashboard.Serve(l.storageService) - if err != nil { - return err - } - - l.gateway.dashPort = *port l.gateway.project = l.project l.gateway.dash = l.dashboard @@ -255,3 +240,7 @@ func (l *localServices) Start(pool pool.WorkerPool) error { func (l *localServices) GetWorkerPool() pool.WorkerPool { return l.gateway.pool } + +func (l *localServices) GetStorageService() *RunStorageService { + return l.storageService +}