From 7b9e4d5c2fdc7737a977562185d736249685b486 Mon Sep 17 00:00:00 2001 From: Roland <33993199+rolznz@users.noreply.github.com> Date: Sat, 13 Jul 2024 20:01:33 +0700 Subject: [PATCH] fix: stop nostr when app is shutdown and use context to stop lnclient (#271) --- api/api.go | 10 +++------- cmd/http/main.go | 2 +- main_wails.go | 2 +- service/models.go | 3 +-- service/service.go | 14 +------------- service/start.go | 33 ++++++++++++++++++++++--------- service/stop.go | 48 +++++++++++++++++++++++++++------------------- 7 files changed, 59 insertions(+), 53 deletions(-) diff --git a/api/api.go b/api/api.go index 38443aa1..7aa7e431 100644 --- a/api/api.go +++ b/api/api.go @@ -314,15 +314,11 @@ func (api *api) Stop() error { return errors.New("LNClient not started") } - // TODO: this should stop everything related to the lnclient - // stop the lnclient + // stop the lnclient, nostr relay etc. // The user will be forced to re-enter their unlock password to restart the node - err := api.svc.StopLNClient() - if err != nil { - logger.Logger.WithError(err).Error("Failed to stop LNClient") - } + api.svc.StopApp() - return err + return nil } func (api *api) GetNodeConnectionInfo(ctx context.Context) (*lnclient.NodeConnectionInfo, error) { diff --git a/cmd/http/main.go b/cmd/http/main.go index 929dec5d..328fb465 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -57,6 +57,6 @@ func main() { defer cancel() e.Shutdown(ctx) logger.Logger.Info("Echo server exited") - svc.WaitShutdown() + svc.Shutdown() logger.Logger.Info("Service exited") } diff --git a/main_wails.go b/main_wails.go index 0b021d42..46db4740 100644 --- a/main_wails.go +++ b/main_wails.go @@ -31,6 +31,6 @@ func main() { logger.Logger.Info("Cancelling service context...") // cancel the service context cancel() - svc.WaitShutdown() + svc.Shutdown() logger.Logger.Info("Service exited") } diff --git a/service/models.go b/service/models.go index bd056b53..3c0961b9 100644 --- a/service/models.go +++ b/service/models.go @@ -12,8 +12,7 @@ import ( type Service interface { StartApp(encryptionKey string) error StopApp() - StopLNClient() error - WaitShutdown() + Shutdown() // TODO: remove getters (currently used by http / wails services) GetAlbyOAuthSvc() alby.AlbyOAuthService diff --git a/service/service.go b/service/service.go index 63a4af84..57e71e58 100644 --- a/service/service.go +++ b/service/service.go @@ -203,7 +203,7 @@ func finishRestoreNode(workDir string) { } func (svc *service) Shutdown() { - svc.StopLNClient() + svc.StopApp() svc.eventPublisher.Publish(&events.Event{ Event: "nwc_stopped", }) @@ -211,13 +211,6 @@ func (svc *service) Shutdown() { time.Sleep(1 * time.Second) } -func (svc *service) StopApp() { - if svc.appCancelFn != nil { - svc.appCancelFn() - svc.wg.Wait() - } -} - func (svc *service) GetDB() *gorm.DB { return svc.db } @@ -245,8 +238,3 @@ func (svc *service) GetLNClient() lnclient.LNClient { func (svc *service) GetKeys() keys.Keys { return svc.keys } - -func (svc *service) WaitShutdown() { - logger.Logger.Info("Waiting for service to exit...") - svc.wg.Wait() -} diff --git a/service/start.go b/service/start.go index 83715e41..43731161 100644 --- a/service/start.go +++ b/service/start.go @@ -22,7 +22,7 @@ import ( "github.com/getAlby/hub/logger" ) -func (svc *service) StartNostr(ctx context.Context, encryptionKey string) error { +func (svc *service) startNostr(ctx context.Context, encryptionKey string) error { relayUrl := svc.cfg.GetRelayUrl() @@ -40,8 +40,10 @@ func (svc *service) StartNostr(ctx context.Context, encryptionKey string) error "npub": npub, "hex": svc.keys.GetNostrPublicKey(), }).Info("Starting Alby Hub") - svc.wg.Add(1) go func() { + svc.wg.Add(1) + // ensure the relay is properly disconnected before exiting + defer svc.wg.Done() //Start infinite loop which will be only broken by canceling ctx (SIGINT) var relay *nostr.Relay @@ -95,9 +97,7 @@ func (svc *service) StartNostr(ctx context.Context, encryptionKey string) error break } closeRelay(relay) - svc.Shutdown() logger.Logger.Info("Relay subroutine ended") - svc.wg.Done() }() return nil } @@ -123,17 +123,30 @@ func (svc *service) StartApp(encryptionKey string) error { return err } - svc.StartNostr(ctx, encryptionKey) + err = svc.startNostr(ctx, encryptionKey) + if err != nil { + cancelFn() + return err + } + svc.appCancelFn = cancelFn + return nil } func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) error { - err := svc.StopLNClient() - if err != nil { - return err + if svc.lnClient != nil { + logger.Logger.Error("LNClient already started") + return errors.New("LNClient already started") } + go func() { + // ensure the LNClient is stopped properly before exiting + svc.wg.Add(1) + <-ctx.Done() + svc.stopLNClient() + }() + lnBackend, _ := svc.cfg.Get("LNBackendType", "") if lnBackend == "" { return errors.New("no LNBackendType specified") @@ -141,6 +154,7 @@ func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) e logger.Logger.Infof("Launching LN Backend: %s", lnBackend) var lnClient lnclient.LNClient + var err error switch lnBackend { case config.LNDBackendType: LNDAddress, _ := svc.cfg.Get("LNDAddress", encryptionKey) @@ -183,6 +197,7 @@ func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) e return err } + svc.lnClient = lnClient info, err := lnClient.GetInfo(ctx) if err != nil { logger.Logger.WithError(err).Error("Failed to fetch node info") @@ -197,7 +212,7 @@ func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) e "node_type": lnBackend, }, }) - svc.lnClient = lnClient + return nil } diff --git a/service/stop.go b/service/stop.go index 2ec0fe03..56d6539d 100644 --- a/service/stop.go +++ b/service/stop.go @@ -7,28 +7,36 @@ import ( "github.com/getAlby/hub/logger" ) -// TODO: this should happen on ctx.Done() rather than having to call manually -// see svc.appCancelFn and how svc.StartNostr works -func (svc *service) StopLNClient() error { - if svc.lnClient != nil { - logger.Logger.Info("Shutting down LN client") - err := svc.lnClient.Shutdown() - if err != nil { - logger.Logger.WithError(err).Error("Failed to stop LN client") - svc.eventPublisher.Publish(&events.Event{ - Event: "nwc_node_stop_failed", - Properties: map[string]interface{}{ - "error": fmt.Sprintf("%v", err), - }, - }) - return err - } - logger.Logger.Info("Publishing node shutdown event") - svc.lnClient = nil +func (svc *service) StopApp() { + if svc.appCancelFn != nil { + logger.Logger.Info("Stopping app...") + svc.appCancelFn() + svc.wg.Wait() + logger.Logger.Info("app stopped") + } +} + +func (svc *service) stopLNClient() { + defer svc.wg.Done() + if svc.lnClient == nil { + return + } + logger.Logger.Info("Shutting down LN client") + err := svc.lnClient.Shutdown() + if err != nil { + logger.Logger.WithError(err).Error("Failed to stop LN client") svc.eventPublisher.Publish(&events.Event{ - Event: "nwc_node_stopped", + Event: "nwc_node_stop_failed", + Properties: map[string]interface{}{ + "error": fmt.Sprintf("%v", err), + }, }) + return } + logger.Logger.Info("Publishing node shutdown event") + svc.lnClient = nil + svc.eventPublisher.Publish(&events.Event{ + Event: "nwc_node_stopped", + }) logger.Logger.Info("LNClient stopped successfully") - return nil }