From 4b79b3e2300e6a01af8ab32946f577cc8c64a42e Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 13:11:41 +0100 Subject: [PATCH 01/15] fix: Fall back to standard output logger if the startup logger can't be built --- CHANGELOG.md | 2 +- backend/handler.go | 2 +- main.go | 26 ++++++++++++++------------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bc7abe6..59577f74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ - [xxxx](https://github.com/vegaprotocol/vega/issues/xxxx) - ### 🐛 Fixes -- [xxxx](https://github.com/vegaprotocol/vega/issues/xxxx) - +- [465](https://github.com/vegaprotocol/vega/issues/465) - Fall back to standard output logger if the startup logger can't be built ## 0.8.2 diff --git a/backend/handler.go b/backend/handler.go index 82768286..e687bc3d 100644 --- a/backend/handler.go +++ b/backend/handler.go @@ -32,7 +32,7 @@ type Handler struct { // appInitialised represents the initialization state of the application // and is used to prevent calls to the API when the application is not - // initialised. + // initialized. appInitialised bool log *zap.Logger diff --git a/main.go b/main.go index 7935c13f..fda8c603 100644 --- a/main.go +++ b/main.go @@ -25,13 +25,7 @@ var assets embed.FS var icon []byte func main() { - startupLogFilePath, err := app.StartupLogFilePath() - if err != nil { - // There is not much we can do to log such an early error. - panic(err) - } - - log := logger.NewFileLogger(startupLogFilePath) + log := startupLogger() defer func() { if r := recover(); r != nil { @@ -43,10 +37,7 @@ func main() { date := time.Now().UTC().Format("2006-01-02-15-04-05") // Create an instance of the handler structure - handler, err := backend.NewHandler() - if err != nil { - log.Fatal(fmt.Sprintf("Couldn't instantiate the backend: %v, PID(%d), date(%v)", err, pid, date)) - } + handler := backend.NewHandler() log.Info(fmt.Sprintf("Starting the application: PID(%d), date(%v)", pid, date)) defer log.Info(fmt.Sprintf("The application exited: PID(%d), date(%v)", pid, date)) @@ -89,6 +80,17 @@ func main() { Icon: icon, }, }); err != nil { - log.Fatal(fmt.Sprintf("Couldn't run the application: %v, PID(%d), date(%v)", err, pid, date)) + log.Fatal(fmt.Sprintf("The application encountered an error while running: %v, PID(%d), date(%v)", err, pid, date)) } } + +func startupLogger() logger.Logger { + startupLogFilePath, err := app.StartupLogFilePath() + if err != nil { + // There is not much we can do, except fallback on a basic standard output + // logger. + return logger.NewDefaultLogger() + } + + return logger.NewFileLogger(startupLogFilePath) +} From 7b2c1fa081630fd970a1d6c11066c098ed13d51e Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 13:13:28 +0100 Subject: [PATCH 02/15] fix: Do not crash when application start with bad configuration --- CHANGELOG.md | 2 +- backend/handler.go | 58 ++++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59577f74..289a7a96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ - [xxxx](https://github.com/vegaprotocol/vega/issues/xxxx) - ### 🛠 Improvements -- [xxxx](https://github.com/vegaprotocol/vega/issues/xxxx) - +- [422](https://github.com/vegaprotocol/vega/issues/422) - Do not crash when application start with bad configuration ### 🐛 Fixes - [465](https://github.com/vegaprotocol/vega/issues/465) - Fall back to standard output logger if the startup logger can't be built diff --git a/backend/handler.go b/backend/handler.go index e687bc3d..f0a8b700 100644 --- a/backend/handler.go +++ b/backend/handler.go @@ -67,25 +67,48 @@ type Handler struct { tokenStore *tokenStoreV1.EmptyStore } -func NewHandler() (*Handler, error) { - h := &Handler{} +func NewHandler() *Handler { + return &Handler{} +} + +// Startup is called during application startup +func (h *Handler) Startup(ctx context.Context) { + h.ctx = ctx + + h.log.Debug("Entering Startup") + defer h.log.Debug("Leaving Startup") +} +// DOMReady is called after the front-end dom has been loaded +func (h *Handler) DOMReady(_ context.Context) { + // Add your action here +} + +// Shutdown is called during application termination +func (h *Handler) Shutdown(_ context.Context) { + h.log.Debug("Entering Shutdown") + defer h.log.Debug("Leaving Shutdown") + + h.closeAllResources() +} + +func (h *Handler) StartupBackend() error { var err error if err := h.initializeAppLogger(); err != nil { - return nil, err + return err } h.configLoader, err = app.NewConfigLoader() if err != nil { - return nil, fmt.Errorf("could not create the configuration loader: %w", err) + return fmt.Errorf("could not create the configuration loader: %w", err) } h.runningServiceManager = newServiceManager() h.appInitialised, err = h.isAppInitialised() if err != nil { - return nil, fmt.Errorf("could not verify wheter the application is initialized or not: %w", err) + return fmt.Errorf("could not verify wheter the application is initialized or not: %w", err) } // If the application is not initialized, it means it's the first time the @@ -95,32 +118,11 @@ func NewHandler() (*Handler, error) { // the "on-boarding" workflow on the front-end. if h.appInitialised { if err := h.reloadBackendComponentsFromConfig(); err != nil { - return nil, fmt.Errorf("could not load the backend components during the application start up: %w", err) + return fmt.Errorf("could not load the backend components during the application start up: %w", err) } } - return h, nil -} - -// Startup is called during application startup -func (h *Handler) Startup(ctx context.Context) { - h.ctx = ctx - - h.log.Debug("Entering Startup") - defer h.log.Debug("Leaving Startup") -} - -// DOMReady is called after the front-end dom has been loaded -func (h *Handler) DOMReady(_ context.Context) { - // Add your action here -} - -// Shutdown is called during application termination -func (h *Handler) Shutdown(_ context.Context) { - h.log.Debug("Entering Shutdown") - defer h.log.Debug("Leaving Shutdown") - - h.closeAllResources() + return nil } func (h *Handler) initializeAppLogger() error { From 02a0596073acad776079e610f87c4a960841edc1 Mon Sep 17 00:00:00 2001 From: Botond Date: Fri, 27 Jan 2023 13:00:34 +0000 Subject: [PATCH 03/15] fix: adjust frontend service interface --- frontend/src/hooks/use-wallet-service.tsx | 27 +++++++++++++------- frontend/src/wailsjs/go/backend/Handler.d.ts | 2 ++ frontend/src/wailsjs/go/backend/Handler.js | 4 +++ frontend/src/wailsjs/runtime/package.json | 0 frontend/src/wailsjs/runtime/runtime.d.ts | 0 frontend/src/wailsjs/runtime/runtime.js | 0 6 files changed, 24 insertions(+), 9 deletions(-) mode change 100644 => 100755 frontend/src/wailsjs/runtime/package.json mode change 100644 => 100755 frontend/src/wailsjs/runtime/runtime.d.ts mode change 100644 => 100755 frontend/src/wailsjs/runtime/runtime.js diff --git a/frontend/src/hooks/use-wallet-service.tsx b/frontend/src/hooks/use-wallet-service.tsx index 133520bf..ec486b64 100644 --- a/frontend/src/hooks/use-wallet-service.tsx +++ b/frontend/src/hooks/use-wallet-service.tsx @@ -32,12 +32,16 @@ export const useWalletService = (): Service => { // Config GetAppConfig: Handlers.GetAppConfig, SearchForExistingConfiguration: Handlers.SearchForExistingConfiguration, - UpdateAppConfig: (payload: AppConfig) => { - return Handlers.UpdateAppConfig(new AppModel.Config(payload)) + UpdateAppConfig: async (payload: AppConfig) => { + Handlers.UpdateAppConfig(new AppModel.Config(payload)) + return undefined }, // Initialization - InitialiseApp: Handlers.InitialiseApp, + InitialiseApp: async ({ vegaHome }: { vegaHome : string }) => { + await Handlers.InitialiseApp({ vegaHome }) + return undefined + }, IsAppInitialised: Handlers.IsAppInitialised, // Telemetry @@ -55,20 +59,25 @@ export const useWalletService = (): Service => { }, // Service - StartService: ({ network }) => { - return Handlers.StartService({ network, noVersionCheck: false }) + StartService: async ({ network }) => { + await Handlers.StartService({ network, noVersionCheck: false }) + return undefined + }, + StopService: async () => { + await Handlers.StopService() + return undefined }, - StopService: Handlers.StopService, GetCurrentServiceInfo: Handlers.GetCurrentServiceInfo, // API EventsOn: EventsOn, EventsOff: EventsOff, - RespondToInteraction: (payload: InteractionResponse) => { + RespondToInteraction: async (payload: InteractionResponse) => { if ('data' in payload) { - return Handlers.RespondToInteraction(payload) + await Handlers.RespondToInteraction(payload) } - return Handlers.RespondToInteraction({ ...payload, data: {} }) + await Handlers.RespondToInteraction({ ...payload, data: {} }) + return undefined } } } diff --git a/frontend/src/wailsjs/go/backend/Handler.d.ts b/frontend/src/wailsjs/go/backend/Handler.d.ts index 37e2b523..1fcbcc9f 100755 --- a/frontend/src/wailsjs/go/backend/Handler.d.ts +++ b/frontend/src/wailsjs/go/backend/Handler.d.ts @@ -32,6 +32,8 @@ export function SearchForExistingConfiguration():Promise; +export function StartupBackend():Promise; + export function StopService():Promise; export function SubmitWalletAPIRequest(arg1:jsonrpc.Request):Promise; diff --git a/frontend/src/wailsjs/go/backend/Handler.js b/frontend/src/wailsjs/go/backend/Handler.js index 8476a2f1..ca4d2442 100755 --- a/frontend/src/wailsjs/go/backend/Handler.js +++ b/frontend/src/wailsjs/go/backend/Handler.js @@ -54,6 +54,10 @@ export function StartService(arg1) { return window['go']['backend']['Handler']['StartService'](arg1); } +export function StartupBackend() { + return window['go']['backend']['Handler']['StartupBackend'](); +} + export function StopService() { return window['go']['backend']['Handler']['StopService'](); } diff --git a/frontend/src/wailsjs/runtime/package.json b/frontend/src/wailsjs/runtime/package.json old mode 100644 new mode 100755 diff --git a/frontend/src/wailsjs/runtime/runtime.d.ts b/frontend/src/wailsjs/runtime/runtime.d.ts old mode 100644 new mode 100755 diff --git a/frontend/src/wailsjs/runtime/runtime.js b/frontend/src/wailsjs/runtime/runtime.js old mode 100644 new mode 100755 From e968a453e640aa3c1a3bc0faf1beac6ed3567e81 Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 13:52:36 +0100 Subject: [PATCH 04/15] feat: Add guards aroung the backend endpoints to prevent crashes --- backend/api_v2.go | 6 +++++- backend/app.go | 16 ++++++++++++---- backend/app_config.go | 4 ++-- backend/handler.go | 18 +++++++++++++++--- backend/service.go | 4 ++-- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/backend/api_v2.go b/backend/api_v2.go index a611cb5d..00316317 100644 --- a/backend/api_v2.go +++ b/backend/api_v2.go @@ -45,7 +45,7 @@ func (h *Handler) SubmitWalletAPIRequest(request jsonrpc.Request) (*jsonrpc.Resp h.log.Debug("Entering SubmitWalletAPIRequest", zap.String("method", request.Method)) defer h.log.Debug("Leaving SubmitWalletAPIRequest", zap.String("method", request.Method)) - if err := h.ensureAppIsInitialised(); err != nil { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { return nil, err } @@ -59,6 +59,10 @@ func (h *Handler) RespondToInteraction(interaction interactor.Interaction) error h.log.Debug("Entering RespondToInteraction") defer h.log.Debug("Leaving RespondToInteraction") + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + return err + } + if interaction.TraceID == "" { return ErrTraceIDIsRequired } diff --git a/backend/app.go b/backend/app.go index 3c286eac..10fdc377 100644 --- a/backend/app.go +++ b/backend/app.go @@ -8,7 +8,10 @@ import ( "go.uber.org/zap" ) -var ErrAppIsNotInitialised = errors.New("the application has not been initialised") +var ( + ErrBackendNotStarted = errors.New("the application backend is not started") + ErrAppIsNotInitialised = errors.New("the application has not been initialised") +) func (h *Handler) IsAppInitialised() (bool, error) { isConfigInit, err := h.isAppInitialised() @@ -42,7 +45,7 @@ func (h *Handler) InitialiseApp(req *InitialiseAppRequest) error { return fmt.Errorf("could not save the application configuration: %w", err) } - h.appInitialised = true + h.appInitialised.Store(true) if err := h.reloadBackendComponentsFromConfig(); err != nil { h.log.Error("Could not reload the backend components during the application initialisation", zap.Error(err)) @@ -52,8 +55,13 @@ func (h *Handler) InitialiseApp(req *InitialiseAppRequest) error { return nil } -func (h *Handler) ensureAppIsInitialised() error { - if !h.appInitialised { +func (h *Handler) ensureBackendStartedAndAppIsInitialised() error { + if !h.backendStarted.Load() { + h.log.Error("The application backend is not started") + return ErrBackendNotStarted + } + + if !h.appInitialised.Load() { h.log.Error("The application is not initialised") return ErrAppIsNotInitialised } diff --git a/backend/app_config.go b/backend/app_config.go index 5dfcdba4..5fe87932 100644 --- a/backend/app_config.go +++ b/backend/app_config.go @@ -60,7 +60,7 @@ func (h *Handler) GetAppConfig() (app.Config, error) { h.log.Debug("Entering GetAppConfig") defer h.log.Debug("Leaving GetAppConfig") - if err := h.ensureAppIsInitialised(); err != nil { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { return app.Config{}, err } @@ -73,7 +73,7 @@ func (h *Handler) UpdateAppConfig(updatedConfig app.Config) error { h.log.Debug("Entering UpdateAppConfig") defer h.log.Debug("Leaving UpdateAppConfig") - if err := h.ensureAppIsInitialised(); err != nil { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { return err } diff --git a/backend/handler.go b/backend/handler.go index f0a8b700..f3dc749c 100644 --- a/backend/handler.go +++ b/backend/handler.go @@ -3,6 +3,7 @@ package backend import ( "context" "fmt" + "sync/atomic" vgclose "code.vegaprotocol.io/vega/libs/close" "code.vegaprotocol.io/vega/libs/jsonrpc" @@ -30,10 +31,13 @@ type Handler struct { // the one to inject on runtime methods like menu, event, dialogs, etc. ctx context.Context + // To prevent multiple startup of the back and thus resource leaks. + backendStarted atomic.Bool + // appInitialised represents the initialization state of the application // and is used to prevent calls to the API when the application is not // initialized. - appInitialised bool + appInitialised atomic.Bool log *zap.Logger // logLevel is a reference to the logger's log level to dynamically change @@ -90,9 +94,15 @@ func (h *Handler) Shutdown(_ context.Context) { defer h.log.Debug("Leaving Shutdown") h.closeAllResources() + } func (h *Handler) StartupBackend() error { + if h.backendStarted.Load() { + return nil + } + h.backendStarted.Store(true) + var err error if err := h.initializeAppLogger(); err != nil { @@ -106,17 +116,19 @@ func (h *Handler) StartupBackend() error { h.runningServiceManager = newServiceManager() - h.appInitialised, err = h.isAppInitialised() + appInitialised, err := h.isAppInitialised() if err != nil { return fmt.Errorf("could not verify wheter the application is initialized or not: %w", err) } + h.appInitialised.Store(appInitialised) + // If the application is not initialized, it means it's the first time the // user is running the application. As a result, we can't load the backend // components that require an existing configuration. The user will have // to go through the application initialization process, that is part of // the "on-boarding" workflow on the front-end. - if h.appInitialised { + if h.appInitialised.Load() { if err := h.reloadBackendComponentsFromConfig(); err != nil { return fmt.Errorf("could not load the backend components during the application start up: %w", err) } diff --git a/backend/service.go b/backend/service.go index fcb89cf7..ec506800 100644 --- a/backend/service.go +++ b/backend/service.go @@ -76,7 +76,7 @@ func (h *Handler) StartService(req *StartServiceRequest) (err error) { h.log.Debug("Entering StartService") defer h.log.Debug("Leaving StartService") - if err := h.ensureAppIsInitialised(); err != nil { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { return err } @@ -156,7 +156,7 @@ func (h *Handler) GetCurrentServiceInfo() (GetCurrentServiceInfo, error) { h.log.Debug("Entering GetCurrentServiceInfo") defer h.log.Debug("Leaving GetCurrentServiceInfo") - if err := h.ensureAppIsInitialised(); err != nil { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { return GetCurrentServiceInfo{}, err } From 69e4a32c4e0d7cdcade47804249e7a09ee8b639d Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 14:09:39 +0100 Subject: [PATCH 05/15] fix: Do not use logger when the backend is not started --- backend/handler.go | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/backend/handler.go b/backend/handler.go index f3dc749c..990a5f06 100644 --- a/backend/handler.go +++ b/backend/handler.go @@ -78,9 +78,6 @@ func NewHandler() *Handler { // Startup is called during application startup func (h *Handler) Startup(ctx context.Context) { h.ctx = ctx - - h.log.Debug("Entering Startup") - defer h.log.Debug("Leaving Startup") } // DOMReady is called after the front-end dom has been loaded @@ -90,11 +87,8 @@ func (h *Handler) DOMReady(_ context.Context) { // Shutdown is called during application termination func (h *Handler) Shutdown(_ context.Context) { - h.log.Debug("Entering Shutdown") - defer h.log.Debug("Leaving Shutdown") - h.closeAllResources() - + h.backendStarted.Store(false) } func (h *Handler) StartupBackend() error { From 213b6a6202b54a082aaf405cef509dd8e902feee Mon Sep 17 00:00:00 2001 From: Botond Date: Fri, 27 Jan 2023 13:24:36 +0000 Subject: [PATCH 06/15] fix: bump ui --- frontend/package.json | 2 +- frontend/src/hooks/use-wallet-service.tsx | 3 ++- frontend/src/wailsjs/runtime/package.json | 0 frontend/src/wailsjs/runtime/runtime.d.ts | 0 frontend/src/wailsjs/runtime/runtime.js | 0 frontend/yarn.lock | 8 ++++---- 6 files changed, 7 insertions(+), 6 deletions(-) mode change 100755 => 100644 frontend/src/wailsjs/runtime/package.json mode change 100755 => 100644 frontend/src/wailsjs/runtime/runtime.d.ts mode change 100755 => 100644 frontend/src/wailsjs/runtime/runtime.js diff --git a/frontend/package.json b/frontend/package.json index ccde90ca..f20fbd98 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -34,7 +34,7 @@ "@sentry/react": "7.19.0", "@sentry/tracing": "7.19.0", "@vegaprotocol/wallet-admin": "0.1.2", - "@vegaprotocol/wallet-ui": "0.1.31", + "@vegaprotocol/wallet-ui": "0.1.32", "core-js": "3.26.1", "jest-environment-jsdom": "29.3.1", "loglevel": "1.8.1", diff --git a/frontend/src/hooks/use-wallet-service.tsx b/frontend/src/hooks/use-wallet-service.tsx index ec486b64..4ab65520 100644 --- a/frontend/src/hooks/use-wallet-service.tsx +++ b/frontend/src/hooks/use-wallet-service.tsx @@ -38,6 +38,7 @@ export const useWalletService = (): Service => { }, // Initialization + StartupBackend: Handlers.StartupBackend, InitialiseApp: async ({ vegaHome }: { vegaHome : string }) => { await Handlers.InitialiseApp({ vegaHome }) return undefined @@ -59,7 +60,7 @@ export const useWalletService = (): Service => { }, // Service - StartService: async ({ network }) => { + StartService: async ({ network }: { network: string }) => { await Handlers.StartService({ network, noVersionCheck: false }) return undefined }, diff --git a/frontend/src/wailsjs/runtime/package.json b/frontend/src/wailsjs/runtime/package.json old mode 100755 new mode 100644 diff --git a/frontend/src/wailsjs/runtime/runtime.d.ts b/frontend/src/wailsjs/runtime/runtime.d.ts old mode 100755 new mode 100644 diff --git a/frontend/src/wailsjs/runtime/runtime.js b/frontend/src/wailsjs/runtime/runtime.js old mode 100755 new mode 100644 diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 46be8890..b00cad40 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -2280,10 +2280,10 @@ resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-admin/-/wallet-admin-0.1.2.tgz#bd58ad743a131cbc801c8fb1b09a6178400e3d2b" integrity sha512-xu1rs/homgEZ4TNN6YxR/V1jRc+fu1NkUp89GHlK69mcB0E7ASnWEdIAv0gtRylvaHRjoPpe8bmTKm1AF1406g== -"@vegaprotocol/wallet-ui@0.1.31": - version "0.1.31" - resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-ui/-/wallet-ui-0.1.31.tgz#0c9876d9e4e5f49d3fbbf1ebec2b2799f8a3eea7" - integrity sha512-HgDz3c1bBvAXeaghclSmC/W0Za4GUH1QTqfQD/cGt/bgut4iLom+jdJ6mraZs2msCgDop2ykacbeTAPKf4QaJg== +"@vegaprotocol/wallet-ui@0.1.32": + version "0.1.32" + resolved "https://registry.yarnpkg.com/@vegaprotocol/wallet-ui/-/wallet-ui-0.1.32.tgz#3a11d6402f6944ba81b8c0c52f238efca135722e" + integrity sha512-7K2+BN4PJCBGXhaZtGBXS8N2dN60/dbuy+edUczfCaqUQ2zKvNouAFryamqUyKsG0MTGF+BFjbeKYk6apJOMLg== dependencies: "@radix-ui/react-checkbox" "1.0.1" "@radix-ui/react-dialog" "1.0.2" From 28552efd3639e12ade21afca9f56e00daf6ff228 Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 14:43:25 +0100 Subject: [PATCH 07/15] fix: Ensure we don't set the backend as started when it failed to --- app/config_loader.go | 4 ++-- backend/handler.go | 15 ++++++++++++--- frontend/package.json.md5 | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/app/config_loader.go b/app/config_loader.go index f9e2d15c..074c6550 100644 --- a/app/config_loader.go +++ b/app/config_loader.go @@ -33,11 +33,11 @@ func (l *ConfigLoader) GetConfig() (Config, error) { cfg := DefaultConfig() if err := paths.ReadStructuredFile(l.configFilePath, &cfg); err != nil { - return Config{}, fmt.Errorf("could not read configuration file: %w", err) + return Config{}, fmt.Errorf("could not read configuration file at %q: %w", l.configFilePath, err) } if err := cfg.EnsureIsValid(); err != nil { - return Config{}, err + return Config{}, fmt.Errorf("the configuration at %q is invalid: %w", l.configFilePath, err) } return cfg, nil diff --git a/backend/handler.go b/backend/handler.go index 990a5f06..9dbd592b 100644 --- a/backend/handler.go +++ b/backend/handler.go @@ -3,6 +3,7 @@ package backend import ( "context" "fmt" + "sync" "sync/atomic" vgclose "code.vegaprotocol.io/vega/libs/close" @@ -33,6 +34,7 @@ type Handler struct { // To prevent multiple startup of the back and thus resource leaks. backendStarted atomic.Bool + startupMu sync.Mutex // appInitialised represents the initialization state of the application // and is used to prevent calls to the API when the application is not @@ -91,13 +93,20 @@ func (h *Handler) Shutdown(_ context.Context) { h.backendStarted.Store(false) } -func (h *Handler) StartupBackend() error { +func (h *Handler) StartupBackend() (err error) { + h.startupMu.Lock() + defer h.startupMu.Unlock() + if h.backendStarted.Load() { return nil } - h.backendStarted.Store(true) - var err error + defer func() { + if err == nil { + // Only set the backend as started on success. + h.backendStarted.Store(true) + } + }() if err := h.initializeAppLogger(); err != nil { return err diff --git a/frontend/package.json.md5 b/frontend/package.json.md5 index 786505d0..1822ebe6 100644 --- a/frontend/package.json.md5 +++ b/frontend/package.json.md5 @@ -1 +1 @@ -3dd6d2d4a7b698e1a3c5db54a4f020ac \ No newline at end of file +685406a25b4dfc732f5abd5f3f2f1101 \ No newline at end of file From f2efb78c37a37d3162164a3cc29110294e66e99b Mon Sep 17 00:00:00 2001 From: Botond Date: Fri, 27 Jan 2023 14:44:24 +0000 Subject: [PATCH 08/15] fix: remove version from app name --- wails.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wails.json b/wails.json index 5eca2235..fe0be73a 100644 --- a/wails.json +++ b/wails.json @@ -10,7 +10,7 @@ "outputfilename": "Vegawallet", "info": { "companyName": "Gobalsky Labs Ltd.", - "productName": "Vegawallet_v0.9.0", + "productName": "Vegawallet", "productVersion": "0.9.0", "copyright": "Copyright (c) 2022 Gobalsky Labs Ltd.", "comments": "Application to manage your Vega Protocol wallet." From e051b00e980d207385abbce21cac17b9f312e282 Mon Sep 17 00:00:00 2001 From: Botond Date: Fri, 27 Jan 2023 14:49:08 +0000 Subject: [PATCH 09/15] fix: remove react strict mode --- frontend/src/index.tsx | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index c6882125..2a3e7114 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,25 +1,14 @@ import 'core-js/stable' - -import React from 'react' import { createRoot } from 'react-dom/client' import App from './app' -import { ENV } from './config/environment' const element = document.getElementById('app') if (element) { const root = createRoot(element) - if (ENV === 'development') { - root.render() - } else { - root.render( - - - - ) - } + root.render() } else { throw Error('Could not find root element with id "app".') } From e83c9eb674d5c0b185e032f0f5b83c5dd6330a48 Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 16:42:18 +0100 Subject: [PATCH 10/15] fix: Ensure we don't emit empty OS notification when closing interaction channels --- backend/service.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backend/service.go b/backend/service.go index ec506800..fa7fc684 100644 --- a/backend/service.go +++ b/backend/service.go @@ -191,7 +191,10 @@ func (h *Handler) listenToIncomingInteractions(ctx context.Context) { case <-ctx.Done(): log.Info("Stopping the listening to incoming interactions") return - case interaction := <-h.runningServiceManager.receptionChan: + case interaction, ok := <-h.runningServiceManager.receptionChan: + if !ok { + return + } h.emitReceivedInteraction(log, interaction) } } @@ -206,7 +209,10 @@ func (h *Handler) listenToServiceRuntimeError(jobCtx context.Context, errChan <- case <-jobCtx.Done(): log.Info("Stopping the listening to the service runtime error") return - case err := <-errChan: + case err, ok := <-errChan: + if !ok { + return + } h.log.Error("An error occurred while running the service", zap.Error(err)) h.runningServiceManager.ShutdownService() runtime.EventsEmit(h.ctx, ServiceStoppedWithError, struct { From 60f74337742eb752ef16903a464e63e95e3902b3 Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 17:36:03 +0100 Subject: [PATCH 11/15] fix: Ensure we don't call the GetVersion endpoint before the user went through the on-boarding workflow --- backend/service.go | 9 --------- backend/version.go | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/backend/service.go b/backend/service.go index fa7fc684..30f9205c 100644 --- a/backend/service.go +++ b/backend/service.go @@ -174,15 +174,6 @@ func (h *Handler) GetCurrentServiceInfo() (GetCurrentServiceInfo, error) { }, nil } -func (h *Handler) ensurePortCanBeBound(svcURL string) error { - if _, err := http.Get("http://" + svcURL); err == nil { - // If there is no error, it means the server managed to establish a - // connection of some kind. It's not good for us. - return fmt.Errorf("could not start the service as an application is already served on %q", svcURL) - } - return nil -} - func (h *Handler) listenToIncomingInteractions(ctx context.Context) { log := h.log.Named("service-interactions-listener") log.Info("Listening to incoming interactions") diff --git a/backend/version.go b/backend/version.go index 0259220a..788bf284 100644 --- a/backend/version.go +++ b/backend/version.go @@ -53,6 +53,15 @@ func (h *Handler) GetLatestRelease() (LatestRelease, error) { } func (h *Handler) GetVersion() *GetVersionResponse { + if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + return &GetVersionResponse{ + Version: app.Version, + GitHash: app.VersionHash, + Backend: wversion.GetSoftwareVersionInfo(), + Compatibility: nil, + } + } + h.log.Debug("Entering GetVersion") defer h.log.Debug("Leaving GetVersion") From 3023b8386064d7b54df1b4b8b0032fcdb4f84599 Mon Sep 17 00:00:00 2001 From: Valentin Trinque Date: Fri, 27 Jan 2023 17:52:23 +0100 Subject: [PATCH 12/15] chore: improve the guards on endpoints to avoid panic but still get some logs --- backend/api_v1.go | 3 +-- backend/api_v2.go | 12 ++++++++++-- backend/app.go | 6 +++++- backend/app_config.go | 12 ++++++++++-- backend/service.go | 12 ++++++++++-- backend/version.go | 17 ++++++++--------- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/backend/api_v1.go b/backend/api_v1.go index 0190579f..1e7acfea 100644 --- a/backend/api_v1.go +++ b/backend/api_v1.go @@ -10,8 +10,7 @@ import ( var ErrAPIv1Unsupported = errors.New("sending transactions through the API v1 is no longer supported") -type unsupportedV1APIPolicy struct { -} +type unsupportedV1APIPolicy struct{} func (u *unsupportedV1APIPolicy) Ask(_ *v1.SubmitTransactionRequest, _ string, _ time.Time) (bool, error) { return false, ErrAPIv1Unsupported diff --git a/backend/api_v2.go b/backend/api_v2.go index 00316317..85df84fc 100644 --- a/backend/api_v2.go +++ b/backend/api_v2.go @@ -42,10 +42,14 @@ func (h *Handler) APIV2DescribeAPIToken(token string) (connections.TokenDescript } func (h *Handler) SubmitWalletAPIRequest(request jsonrpc.Request) (*jsonrpc.Response, error) { + if err := h.ensureBackendStarted(); err != nil { + return nil, err + } + h.log.Debug("Entering SubmitWalletAPIRequest", zap.String("method", request.Method)) defer h.log.Debug("Leaving SubmitWalletAPIRequest", zap.String("method", request.Method)) - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return nil, err } @@ -56,10 +60,14 @@ func (h *Handler) SubmitWalletAPIRequest(request jsonrpc.Request) (*jsonrpc.Resp } func (h *Handler) RespondToInteraction(interaction interactor.Interaction) error { + if err := h.ensureBackendStarted(); err != nil { + return err + } + h.log.Debug("Entering RespondToInteraction") defer h.log.Debug("Leaving RespondToInteraction") - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return err } diff --git a/backend/app.go b/backend/app.go index 10fdc377..72d4aaf3 100644 --- a/backend/app.go +++ b/backend/app.go @@ -55,12 +55,16 @@ func (h *Handler) InitialiseApp(req *InitialiseAppRequest) error { return nil } -func (h *Handler) ensureBackendStartedAndAppIsInitialised() error { +func (h *Handler) ensureBackendStarted() error { if !h.backendStarted.Load() { h.log.Error("The application backend is not started") return ErrBackendNotStarted } + return nil +} + +func (h *Handler) ensureAppIsInitialised() error { if !h.appInitialised.Load() { h.log.Error("The application is not initialised") return ErrAppIsNotInitialised diff --git a/backend/app_config.go b/backend/app_config.go index 5fe87932..83aed9e9 100644 --- a/backend/app_config.go +++ b/backend/app_config.go @@ -57,10 +57,14 @@ func (h *Handler) SearchForExistingConfiguration() (*SearchForExistingConfigurat // GetAppConfig return the application configuration. func (h *Handler) GetAppConfig() (app.Config, error) { + if err := h.ensureBackendStarted(); err != nil { + return app.Config{}, err + } + h.log.Debug("Entering GetAppConfig") defer h.log.Debug("Leaving GetAppConfig") - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return app.Config{}, err } @@ -70,10 +74,14 @@ func (h *Handler) GetAppConfig() (app.Config, error) { // UpdateAppConfig update the application configuration. This requires a restart // to take effect. func (h *Handler) UpdateAppConfig(updatedConfig app.Config) error { + if err := h.ensureBackendStarted(); err != nil { + return err + } + h.log.Debug("Entering UpdateAppConfig") defer h.log.Debug("Leaving UpdateAppConfig") - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return err } diff --git a/backend/service.go b/backend/service.go index 30f9205c..d2e2e95a 100644 --- a/backend/service.go +++ b/backend/service.go @@ -73,10 +73,14 @@ func (r StartServiceRequest) Check() error { } func (h *Handler) StartService(req *StartServiceRequest) (err error) { + if err := h.ensureBackendStarted(); err != nil { + return err + } + h.log.Debug("Entering StartService") defer h.log.Debug("Leaving StartService") - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return err } @@ -153,10 +157,14 @@ type GetCurrentServiceInfo struct { } func (h *Handler) GetCurrentServiceInfo() (GetCurrentServiceInfo, error) { + if err := h.ensureBackendStarted(); err != nil { + return GetCurrentServiceInfo{}, err + } + h.log.Debug("Entering GetCurrentServiceInfo") defer h.log.Debug("Leaving GetCurrentServiceInfo") - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { + if err := h.ensureAppIsInitialised(); err != nil { return GetCurrentServiceInfo{}, err } diff --git a/backend/version.go b/backend/version.go index 788bf284..d1bfd08d 100644 --- a/backend/version.go +++ b/backend/version.go @@ -52,19 +52,18 @@ func (h *Handler) GetLatestRelease() (LatestRelease, error) { return latestRelease, nil } -func (h *Handler) GetVersion() *GetVersionResponse { - if err := h.ensureBackendStartedAndAppIsInitialised(); err != nil { - return &GetVersionResponse{ - Version: app.Version, - GitHash: app.VersionHash, - Backend: wversion.GetSoftwareVersionInfo(), - Compatibility: nil, - } +func (h *Handler) GetVersion() (*GetVersionResponse, error) { + if err := h.ensureBackendStarted(); err != nil { + return nil, err } h.log.Debug("Entering GetVersion") defer h.log.Debug("Leaving GetVersion") + if err := h.ensureAppIsInitialised(); err != nil { + return nil, err + } + compatibility, _ := wversion.CheckSoftwareCompatibility(h.networkStore, wversion.GetNetworkVersionThroughGRPC) return &GetVersionResponse{ @@ -72,5 +71,5 @@ func (h *Handler) GetVersion() *GetVersionResponse { GitHash: app.VersionHash, Backend: wversion.GetSoftwareVersionInfo(), Compatibility: compatibility, - } + }, nil } From f422b7e9932cd59df7b97dc1b7077f2ff943df1b Mon Sep 17 00:00:00 2001 From: Botond Date: Sat, 28 Jan 2023 12:35:51 +0000 Subject: [PATCH 13/15] chore: readd frontend dev env --- frontend/src/index.tsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 2a3e7114..62fcae4a 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,13 +1,25 @@ import 'core-js/stable' + +import React from 'react' import { createRoot } from 'react-dom/client' import App from './app' +import { ENV } from './config/environment' const element = document.getElementById('app') if (element) { const root = createRoot(element) + if (ENV === 'development') { + root.render() + } else { + root.render( + + + + ) + } root.render() } else { throw Error('Could not find root element with id "app".') From 6613534beb93deaf6d7e900b53d358c16bfba1f3 Mon Sep 17 00:00:00 2001 From: Botond Date: Sat, 28 Jan 2023 13:11:55 +0000 Subject: [PATCH 14/15] fix: hack in guard for double-interaction submissions --- frontend/src/hooks/use-wallet-service.tsx | 29 +++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/frontend/src/hooks/use-wallet-service.tsx b/frontend/src/hooks/use-wallet-service.tsx index 4ab65520..89e64bbb 100644 --- a/frontend/src/hooks/use-wallet-service.tsx +++ b/frontend/src/hooks/use-wallet-service.tsx @@ -11,6 +11,27 @@ import { EventsOff, EventsOn } from '../wailsjs/runtime' const logger = createLogger('DesktopWallet') +const debouncedResponseHandler = () => { + let lastTraceId: string | null = null + let lastEvent: string | null = null + + return async (payload: InteractionResponse) => { + setTimeout(() => { + lastTraceId = null + lastEvent = null + }, 500) + + if (lastTraceId === payload.traceID && lastEvent === payload.name) { + return + } + + if ('data' in payload) { + await Handlers.RespondToInteraction(payload) + } + await Handlers.RespondToInteraction({ ...payload, data: {} }) + } +} + export const useWalletService = (): Service => { return { TYPE: 'http', @@ -73,12 +94,6 @@ export const useWalletService = (): Service => { // API EventsOn: EventsOn, EventsOff: EventsOff, - RespondToInteraction: async (payload: InteractionResponse) => { - if ('data' in payload) { - await Handlers.RespondToInteraction(payload) - } - await Handlers.RespondToInteraction({ ...payload, data: {} }) - return undefined - } + RespondToInteraction: debouncedResponseHandler(), } } From b2daca6d85b9201ee6dfc75ba496657ec3165821 Mon Sep 17 00:00:00 2001 From: Botond Date: Sun, 29 Jan 2023 11:58:15 +0000 Subject: [PATCH 15/15] fix: the most stupid error of the century, return from the callback, applause, bow, curtains --- frontend/src/hooks/use-wallet-service.tsx | 32 ++++++----------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/frontend/src/hooks/use-wallet-service.tsx b/frontend/src/hooks/use-wallet-service.tsx index 89e64bbb..b45171e1 100644 --- a/frontend/src/hooks/use-wallet-service.tsx +++ b/frontend/src/hooks/use-wallet-service.tsx @@ -11,27 +11,6 @@ import { EventsOff, EventsOn } from '../wailsjs/runtime' const logger = createLogger('DesktopWallet') -const debouncedResponseHandler = () => { - let lastTraceId: string | null = null - let lastEvent: string | null = null - - return async (payload: InteractionResponse) => { - setTimeout(() => { - lastTraceId = null - lastEvent = null - }, 500) - - if (lastTraceId === payload.traceID && lastEvent === payload.name) { - return - } - - if ('data' in payload) { - await Handlers.RespondToInteraction(payload) - } - await Handlers.RespondToInteraction({ ...payload, data: {} }) - } -} - export const useWalletService = (): Service => { return { TYPE: 'http', @@ -92,8 +71,13 @@ export const useWalletService = (): Service => { GetCurrentServiceInfo: Handlers.GetCurrentServiceInfo, // API - EventsOn: EventsOn, - EventsOff: EventsOff, - RespondToInteraction: debouncedResponseHandler(), + EventsOn, + EventsOff, + RespondToInteraction: async (payload: any) => { + if ('data' in payload) { + return await Handlers.RespondToInteraction(payload) + } + return await Handlers.RespondToInteraction({ ...payload, data: {} }) + } } }