fix: replace fatal logs with proper error handling (#707)

* fix: replace fatal logs with proper error handling

- fires nwc shutdown event synchronously
- requires at least one minute leeway for access token expiry

* chore: rename error

* fix: do not mask original reason for error

* fix: config error handling and error messages

* chore: rename
This commit is contained in:
Roland 2024-09-25 17:31:05 +07:00 committed by GitHub
parent ff417c4f1e
commit 8ebb4ad716
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 264 additions and 94 deletions

View file

@ -97,7 +97,10 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l
if err != nil {
logger.Logger.WithError(err).Error("Failed to fetch user me")
// remove token so user can retry
svc.cfg.SetUpdate(accessTokenKey, "", "")
cfgErr := svc.cfg.SetUpdate(accessTokenKey, "", "")
if cfgErr != nil {
logger.Logger.WithError(cfgErr).Error("failed to remove existing access token")
}
return err
}
@ -109,7 +112,11 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l
// save the user's alby account ID on first time login
if existingUserIdentifier == "" {
svc.cfg.SetUpdate(userIdentifierKey, me.Identifier, "")
err := svc.cfg.SetUpdate(userIdentifierKey, me.Identifier, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set user identifier")
return err
}
if svc.cfg.GetEnv().AutoLinkAlbyAccount {
// link account on first login
@ -121,7 +128,10 @@ func (svc *albyOAuthService) CallbackHandler(ctx context.Context, code string, l
} else if me.Identifier != existingUserIdentifier {
// remove token so user can retry with correct account
svc.cfg.SetUpdate(accessTokenKey, "", "")
err := svc.cfg.SetUpdate(accessTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set user access token")
}
return errors.New("Alby Hub is connected to a different alby account. Please log out of your Alby Account at getalby.com and try again.")
}
@ -155,9 +165,18 @@ func (svc *albyOAuthService) IsConnected(ctx context.Context) bool {
}
func (svc *albyOAuthService) saveToken(token *oauth2.Token) {
svc.cfg.SetUpdate(accessTokenExpiryKey, strconv.FormatInt(token.Expiry.Unix(), 10), "")
svc.cfg.SetUpdate(accessTokenKey, token.AccessToken, "")
svc.cfg.SetUpdate(refreshTokenKey, token.RefreshToken, "")
err := svc.cfg.SetUpdate(accessTokenExpiryKey, strconv.FormatInt(token.Expiry.Unix(), 10), "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save access token expiry")
}
err = svc.cfg.SetUpdate(accessTokenKey, token.AccessToken, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save access token")
}
err = svc.cfg.SetUpdate(refreshTokenKey, token.RefreshToken, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save refresh token")
}
}
var tokenMutex sync.Mutex
@ -202,8 +221,8 @@ func (svc *albyOAuthService) fetchUserToken(ctx context.Context) (*oauth2.Token,
RefreshToken: refreshToken,
}
// only use the current token if it has at least 20 seconds before expiry
if currentToken.Expiry.After(time.Now().Add(time.Duration(20) * time.Second)) {
// only use the current token if it has at least 60 seconds before expiry
if currentToken.Expiry.After(time.Now().Add(time.Duration(60) * time.Second)) {
logger.Logger.Debug("Using existing Alby OAuth token")
return currentToken, nil
}
@ -290,7 +309,10 @@ func (svc *albyOAuthService) GetMe(ctx context.Context) (*AlbyMe, error) {
return nil, err
}
svc.cfg.SetUpdate(lightningAddressKey, me.LightningAddress, "")
err = svc.cfg.SetUpdate(lightningAddressKey, me.LightningAddress, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lightning address")
}
logger.Logger.WithFields(logrus.Fields{"me": me}).Info("Alby me response")
return me, nil
@ -451,9 +473,6 @@ func (svc *albyOAuthService) SendPayment(ctx context.Context, invoice string) er
}
func (svc *albyOAuthService) GetAuthUrl() string {
if svc.cfg.GetEnv().AlbyClientId == "" || svc.cfg.GetEnv().AlbyClientSecret == "" {
logger.Logger.Fatalf("No ALBY_OAUTH_CLIENT_ID or ALBY_OAUTH_CLIENT_SECRET set")
}
return svc.oauthConf.AuthCodeURL("unused")
}
@ -464,11 +483,26 @@ func (svc *albyOAuthService) UnlinkAccount(ctx context.Context) error {
}
svc.deleteAlbyAccountApps()
svc.cfg.SetUpdate(userIdentifierKey, "", "")
svc.cfg.SetUpdate(accessTokenKey, "", "")
svc.cfg.SetUpdate(accessTokenExpiryKey, "", "")
svc.cfg.SetUpdate(refreshTokenKey, "", "")
svc.cfg.SetUpdate(lightningAddressKey, "", "")
err = svc.cfg.SetUpdate(userIdentifierKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove user identifier from config")
}
err = svc.cfg.SetUpdate(accessTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove access token from config")
}
err = svc.cfg.SetUpdate(accessTokenExpiryKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove access token expiry from config")
}
err = svc.cfg.SetUpdate(refreshTokenKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove refresh token from config")
}
err = svc.cfg.SetUpdate(lightningAddressKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove lightning address from config")
}
return nil
}

View file

@ -525,7 +525,10 @@ func (api *api) GetNewOnchainAddress(ctx context.Context) (string, error) {
return "", err
}
api.cfg.SetUpdate(config.OnchainAddressKey, address, "")
err = api.cfg.SetUpdate(config.OnchainAddressKey, address, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save new onchain address to config")
}
return address, nil
}
@ -706,7 +709,10 @@ func (api *api) GetMnemonic(unlockPassword string) (*MnemonicResponse, error) {
}
func (api *api) SetNextBackupReminder(backupReminderRequest *BackupReminderRequest) error {
api.cfg.SetUpdate("NextBackupReminder", backupReminderRequest.NextBackupReminder, "")
err := api.cfg.SetUpdate("NextBackupReminder", backupReminderRequest.NextBackupReminder, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save next backup reminder to config")
}
return nil
}
@ -751,44 +757,89 @@ func (api *api) Setup(ctx context.Context, setupRequest *SetupRequest) error {
return errors.New("no unlock password provided")
}
api.cfg.Setup(setupRequest.UnlockPassword)
// TODO: move all below code to cfg.Setup()
err = api.cfg.SaveUnlockPasswordCheck(setupRequest.UnlockPassword)
if err != nil {
return err
}
// update next backup reminder
api.cfg.SetUpdate("NextBackupReminder", setupRequest.NextBackupReminder, "")
err = api.cfg.SetUpdate("NextBackupReminder", setupRequest.NextBackupReminder, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save next backup reminder")
}
// only update non-empty values
if setupRequest.LNBackendType != "" {
api.cfg.SetUpdate("LNBackendType", setupRequest.LNBackendType, "")
err = api.cfg.SetUpdate("LNBackendType", setupRequest.LNBackendType, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to save backend type")
return err
}
}
if setupRequest.BreezAPIKey != "" {
api.cfg.SetUpdate("BreezAPIKey", setupRequest.BreezAPIKey, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("BreezAPIKey", setupRequest.BreezAPIKey, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save breez api key")
return err
}
}
if setupRequest.Mnemonic != "" {
api.cfg.SetUpdate("Mnemonic", setupRequest.Mnemonic, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("Mnemonic", setupRequest.Mnemonic, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save encrypted mnemonic")
return err
}
}
if setupRequest.GreenlightInviteCode != "" {
api.cfg.SetUpdate("GreenlightInviteCode", setupRequest.GreenlightInviteCode, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("GreenlightInviteCode", setupRequest.GreenlightInviteCode, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save greenlight invite code")
return err
}
}
if setupRequest.LNDAddress != "" {
api.cfg.SetUpdate("LNDAddress", setupRequest.LNDAddress, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDAddress", setupRequest.LNDAddress, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd address")
return err
}
}
if setupRequest.LNDCertHex != "" {
api.cfg.SetUpdate("LNDCertHex", setupRequest.LNDCertHex, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDCertHex", setupRequest.LNDCertHex, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd cert hex")
return err
}
}
if setupRequest.LNDMacaroonHex != "" {
api.cfg.SetUpdate("LNDMacaroonHex", setupRequest.LNDMacaroonHex, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("LNDMacaroonHex", setupRequest.LNDMacaroonHex, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save lnd macaroon hex")
return err
}
}
if setupRequest.PhoenixdAddress != "" {
api.cfg.SetUpdate("PhoenixdAddress", setupRequest.PhoenixdAddress, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("PhoenixdAddress", setupRequest.PhoenixdAddress, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save phoenix address")
return err
}
}
if setupRequest.PhoenixdAuthorization != "" {
api.cfg.SetUpdate("PhoenixdAuthorization", setupRequest.PhoenixdAuthorization, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("PhoenixdAuthorization", setupRequest.PhoenixdAuthorization, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save phoenix auth")
return err
}
}
if setupRequest.CashuMintUrl != "" {
api.cfg.SetUpdate("CashuMintUrl", setupRequest.CashuMintUrl, setupRequest.UnlockPassword)
err = api.cfg.SetUpdate("CashuMintUrl", setupRequest.CashuMintUrl, setupRequest.UnlockPassword)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save cashu mint url")
return err
}
}
return nil

View file

@ -21,8 +21,8 @@ func main() {
// Create a channel to receive OS signals.
osSignalChannel := make(chan os.Signal, 1)
// Notify the channel on os.Interrupt, syscall.SIGTERM, and os.Kill.
signal.Notify(osSignalChannel, os.Interrupt, syscall.SIGTERM, os.Kill)
// Notify the channel on os.Interrupt, syscall.SIGTERM. os.Kill cannot be caught.
signal.Notify(osSignalChannel, os.Interrupt, syscall.SIGTERM)
ctx, cancel := context.WithCancel(context.Background())
svc, _ := service.NewService(ctx)
@ -35,7 +35,8 @@ func main() {
//start Echo server
go func() {
if err := e.Start(fmt.Sprintf(":%v", svc.GetConfig().GetEnv().Port)); err != nil && err != nethttp.ErrServerClosed {
logger.Logger.Fatalf("shutting down the server: %v", err)
logger.Logger.WithError(err).Error("echo server failed to start")
ctx.Done()
}
}()

View file

@ -25,50 +25,77 @@ const (
unlockPasswordCheck = "THIS STRING SHOULD MATCH IF PASSWORD IS CORRECT"
)
func NewConfig(env *AppConfig, db *gorm.DB) *config {
func NewConfig(env *AppConfig, db *gorm.DB) (*config, error) {
cfg := &config{
db: db,
}
cfg.init(env)
return cfg
err := cfg.init(env)
if err != nil {
return nil, err
}
return cfg, nil
}
func (cfg *config) init(env *AppConfig) {
func (cfg *config) init(env *AppConfig) error {
cfg.Env = env
if cfg.Env.Relay != "" {
cfg.SetIgnore("Relay", cfg.Env.Relay, "")
err := cfg.SetIgnore("Relay", cfg.Env.Relay, "")
if err != nil {
return err
}
}
if cfg.Env.LNBackendType != "" {
cfg.SetIgnore("LNBackendType", cfg.Env.LNBackendType, "")
err := cfg.SetIgnore("LNBackendType", cfg.Env.LNBackendType, "")
if err != nil {
return err
}
}
// LND specific to support env variables
if cfg.Env.LNDAddress != "" {
cfg.SetIgnore("LNDAddress", cfg.Env.LNDAddress, "")
err := cfg.SetIgnore("LNDAddress", cfg.Env.LNDAddress, "")
if err != nil {
return err
}
}
if cfg.Env.LNDCertFile != "" {
certBytes, err := os.ReadFile(cfg.Env.LNDCertFile)
if err != nil {
logger.Logger.Fatalf("Failed to read LND cert file: %v", err)
logger.Logger.WithError(err).Error("Failed to read LND cert file")
return err
}
certHex := hex.EncodeToString(certBytes)
cfg.SetIgnore("LNDCertHex", certHex, "")
err = cfg.SetIgnore("LNDCertHex", certHex, "")
if err != nil {
return err
}
}
if cfg.Env.LNDMacaroonFile != "" {
macBytes, err := os.ReadFile(cfg.Env.LNDMacaroonFile)
if err != nil {
logger.Logger.Fatalf("Failed to read LND macaroon file: %v", err)
logger.Logger.WithError(err).Error("Failed to read LND macaroon file")
return err
}
macHex := hex.EncodeToString(macBytes)
cfg.SetIgnore("LNDMacaroonHex", macHex, "")
err = cfg.SetIgnore("LNDMacaroonHex", macHex, "")
if err != nil {
return err
}
}
// Phoenix specific to support env variables
if cfg.Env.PhoenixdAddress != "" {
cfg.SetIgnore("PhoenixdAddress", cfg.Env.PhoenixdAddress, "")
err := cfg.SetIgnore("PhoenixdAddress", cfg.Env.PhoenixdAddress, "")
if err != nil {
return err
}
}
if cfg.Env.PhoenixdAuthorization != "" {
cfg.SetIgnore("PhoenixdAuthorization", cfg.Env.PhoenixdAuthorization, "")
err := cfg.SetIgnore("PhoenixdAuthorization", cfg.Env.PhoenixdAuthorization, "")
if err != nil {
return err
}
}
// set the JWT secret to the one from the env
@ -76,11 +103,17 @@ func (cfg *config) init(env *AppConfig) {
cfg.JWTSecret = cfg.Env.JWTSecret
if cfg.JWTSecret == "" {
hex, err := randomHex(32)
if err == nil {
cfg.SetIgnore("JWTSecret", hex, "")
if err != nil {
logger.Logger.WithError(err).Error("failed to generate JWT secret")
return err
}
err = cfg.SetIgnore("JWTSecret", hex, "")
if err != nil {
return err
}
cfg.JWTSecret, _ = cfg.Get("JWTSecret", "")
}
return nil
}
func (cfg *config) SetupCompleted() bool {
@ -147,26 +180,30 @@ func (cfg *config) set(key string, value string, clauses clause.OnConflict, encr
return nil
}
func (cfg *config) SetIgnore(key string, value string, encryptionKey string) {
func (cfg *config) SetIgnore(key string, value string, encryptionKey string) error {
clauses := clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
DoNothing: true,
}
err := cfg.set(key, value, clauses, encryptionKey, cfg.db)
if err != nil {
logger.Logger.Fatalf("Failed to save config: %v", err)
logger.Logger.WithField("key", key).WithError(err).Error("Failed to set config key with ignore", err)
return err
}
return nil
}
func (cfg *config) SetUpdate(key string, value string, encryptionKey string) {
func (cfg *config) SetUpdate(key string, value string, encryptionKey string) error {
clauses := clause.OnConflict{
Columns: []clause.Column{{Name: "key"}},
DoUpdates: clause.AssignmentColumns([]string{"value"}),
}
err := cfg.set(key, value, clauses, encryptionKey, cfg.db)
if err != nil {
logger.Logger.Fatalf("Failed to save config: %v", err)
logger.Logger.WithField("key", key).WithError(err).Error("Failed to set config key with update", err)
return err
}
return nil
}
func (cfg *config) ChangeUnlockPassword(currentUnlockPassword string, newUnlockPassword string) error {
@ -219,9 +256,13 @@ func (cfg *config) CheckUnlockPassword(encryptionKey string) bool {
return err == nil && (decryptedValue == "" || decryptedValue == unlockPasswordCheck)
}
// TODO: rename
func (cfg *config) Setup(encryptionKey string) {
cfg.SetUpdate("UnlockPasswordCheck", unlockPasswordCheck, encryptionKey)
func (cfg *config) SaveUnlockPasswordCheck(encryptionKey string) error {
err := cfg.SetUpdate("UnlockPasswordCheck", unlockPasswordCheck, encryptionKey)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save unlock password check to config")
return err
}
return nil
}
func (cfg *config) GetEnv() *AppConfig {

View file

@ -50,13 +50,13 @@ func (c *AppConfig) IsDefaultClientId() bool {
type Config interface {
Get(key string, encryptionKey string) (string, error)
SetIgnore(key string, value string, encryptionKey string)
SetUpdate(key string, value string, encryptionKey string)
SetIgnore(key string, value string, encryptionKey string) error
SetUpdate(key string, value string, encryptionKey string) error
GetJWTSecret() string
GetRelayUrl() string
GetEnv() *AppConfig
CheckUnlockPassword(password string) bool
ChangeUnlockPassword(currentUnlockPassword string, newUnlockPassword string) error
Setup(encryptionKey string)
SaveUnlockPasswordCheck(encryptionKey string) error
SetupCompleted() bool
}

View file

@ -46,13 +46,24 @@ func (ep *eventPublisher) RemoveSubscriber(listenerToRemove EventSubscriber) {
}
func (ep *eventPublisher) Publish(event *Event) {
ep.publish(event, false)
}
func (ep *eventPublisher) PublishSync(event *Event) {
ep.publish(event, true)
}
func (ep *eventPublisher) publish(event *Event, sync bool) {
ep.subscriberMtx.Lock()
defer ep.subscriberMtx.Unlock()
logger.Logger.WithFields(logrus.Fields{"event": event, "global": ep.globalProperties}).Debug("Publishing event")
for _, listener := range ep.listeners {
if sync {
listener.ConsumeEvent(context.Background(), event, ep.globalProperties)
} else {
// consume event without blocking thread
go listener.ConsumeEvent(context.Background(), event, ep.globalProperties)
}
}
}
func (ep *eventPublisher) SetGlobalProperty(key string, value interface{}) {

View file

@ -12,6 +12,7 @@ type EventPublisher interface {
RegisterSubscriber(eventListener EventSubscriber)
RemoveSubscriber(eventListener EventSubscriber)
Publish(event *Event)
PublishSync(event *Event)
SetGlobalProperty(key string, value interface{})
}

View file

@ -66,14 +66,19 @@ func NewGreenlightService(cfg config.Config, mnemonic, inviteCode, workDir, encr
credentials = &recoveredCredentials
if err != nil {
logger.Logger.Fatalf("Failed to register new node")
logger.Logger.WithError(err).Error("Failed to register new node")
return nil, err
}
}
if credentials == nil || credentials.GlCreds == "" {
return nil, errors.New("unexpected response from Recover")
}
cfg.SetUpdate(DEVICE_CREDENTIALS_KEY, credentials.GlCreds, encryptionKey)
err = cfg.SetUpdate(DEVICE_CREDENTIALS_KEY, credentials.GlCreds, encryptionKey)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save greenlight credentials")
return nil, err
}
}
client, err := glalby.NewBlockingGreenlightAlbyClient(mnemonic, *credentials)
@ -83,7 +88,7 @@ func NewGreenlightService(cfg config.Config, mnemonic, inviteCode, workDir, encr
return nil, err
}
if client == nil {
log.Fatalf("unexpected response from NewBlockingGreenlightAlbyClient")
logger.Logger.Error("unexpected response from NewBlockingGreenlightAlbyClient")
}
nodeInfo, err := client.GetInfo()

View file

@ -415,10 +415,15 @@ func (ls *LDKService) resetRouterInternal() {
if err != nil {
logger.Logger.Error("Failed to retrieve ResetRouter key")
return
}
if key != "" {
ls.cfg.SetUpdate(resetRouterKey, "", "")
err = ls.cfg.SetUpdate(resetRouterKey, "", "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to remove reset router key")
return
}
logger.Logger.WithField("key", key).Info("Resetting router")
ldkDbPath := filepath.Join(ls.workdir, "storage", "ldk_node_data.sqlite")
@ -1086,7 +1091,11 @@ func (ls *LDKService) RedeemOnchainFunds(ctx context.Context, toAddress string,
}
func (ls *LDKService) ResetRouter(key string) error {
ls.cfg.SetUpdate(resetRouterKey, key, "")
err := ls.cfg.SetUpdate(resetRouterKey, key, "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set reset router key")
return err
}
return nil
}

View file

@ -28,7 +28,11 @@ func (keys *keys) Init(cfg config.Config, encryptionKey string) error {
if nostrSecretKey == "" {
nostrSecretKey = nostr.GeneratePrivateKey()
cfg.SetUpdate("NostrSecretKey", nostrSecretKey, encryptionKey)
err := cfg.SetUpdate("NostrSecretKey", nostrSecretKey, encryptionKey)
if err != nil {
logger.Logger.WithError(err).Error("Failed to save generated nostr secret key")
return err
}
}
nostrPublicKey, err := nostr.GetPublicKey(nostrSecretKey)
if err != nil {
@ -41,15 +45,9 @@ func (keys *keys) Init(cfg config.Config, encryptionKey string) error {
}
func (keys *keys) GetNostrPublicKey() string {
if keys.nostrPublicKey == "" {
logger.Logger.Fatal("keys not initialized")
}
return keys.nostrPublicKey
}
func (keys *keys) GetNostrSecretKey() string {
if keys.nostrSecretKey == "" {
logger.Logger.Fatal("keys not initialized")
}
return keys.nostrSecretKey
}

View file

@ -2,7 +2,6 @@ package service
import (
"context"
"time"
"os"
"path/filepath"
@ -69,7 +68,11 @@ func NewService(ctx context.Context) (*service, error) {
return nil, err
}
finishRestoreNode(appConfig.Workdir)
err = finishRestoreNode(appConfig.Workdir)
if err != nil {
logger.Logger.WithError(err).Error("failed to restore backup")
return nil, err
}
// If DATABASE_URI is a URI or a path, leave it unchanged.
// If it only contains a filename, prepend the workdir.
@ -85,7 +88,10 @@ func NewService(ctx context.Context) (*service, error) {
return nil, err
}
cfg := config.NewConfig(appConfig, gormDB)
cfg, err := config.NewConfig(appConfig, gormDB)
if err != nil {
return nil, err
}
eventPublisher := events.NewEventPublisher()
@ -167,21 +173,23 @@ func (svc *service) StartSubscription(ctx context.Context, sub *nostr.Subscripti
return nil
}
func finishRestoreNode(workDir string) {
func finishRestoreNode(workDir string) error {
restoreDir := filepath.Join(workDir, "restore")
if restoreDirStat, err := os.Stat(restoreDir); err == nil && restoreDirStat.IsDir() {
logger.Logger.WithField("restoreDir", restoreDir).Infof("Restore directory found. Finishing Node restore")
existingFiles, err := os.ReadDir(restoreDir)
if err != nil {
logger.Logger.WithError(err).Fatal("Failed to read WORK_DIR")
logger.Logger.WithError(err).Error("Failed to read WORK_DIR")
return err
}
for _, file := range existingFiles {
if file.Name() != "restore" {
err = os.RemoveAll(filepath.Join(workDir, file.Name()))
if err != nil {
logger.Logger.WithField("filename", file.Name()).WithError(err).Fatal("Failed to remove file")
logger.Logger.WithField("filename", file.Name()).WithError(err).Error("Failed to remove file")
return err
}
logger.Logger.WithField("filename", file.Name()).Info("removed file")
}
@ -189,31 +197,33 @@ func finishRestoreNode(workDir string) {
files, err := os.ReadDir(restoreDir)
if err != nil {
logger.Logger.WithError(err).Fatal("Failed to read restore directory")
logger.Logger.WithError(err).Error("Failed to read restore directory")
return err
}
for _, file := range files {
err = os.Rename(filepath.Join(restoreDir, file.Name()), filepath.Join(workDir, file.Name()))
if err != nil {
logger.Logger.WithField("filename", file.Name()).WithError(err).Fatal("Failed to move file")
logger.Logger.WithField("filename", file.Name()).WithError(err).Error("Failed to move file")
return err
}
logger.Logger.WithField("filename", file.Name()).Info("copied file from restore directory")
}
err = os.RemoveAll(restoreDir)
if err != nil {
logger.Logger.WithError(err).Fatal("Failed to remove restore directory")
logger.Logger.WithError(err).Error("Failed to remove restore directory")
return err
}
logger.Logger.WithField("restoreDir", restoreDir).Info("removed restore directory")
}
return nil
}
func (svc *service) Shutdown() {
svc.StopApp()
svc.eventPublisher.Publish(&events.Event{
svc.eventPublisher.PublishSync(&events.Event{
Event: "nwc_stopped",
})
db.Stop(svc.db)
// wait for any remaining events
time.Sleep(1 * time.Second)
}
func (svc *service) GetDB() *gorm.DB {

View file

@ -3,6 +3,7 @@ package service
import (
"context"
"errors"
"fmt"
"path"
"strconv"
"time"
@ -29,12 +30,14 @@ func (svc *service) startNostr(ctx context.Context, encryptionKey string) error
err := svc.keys.Init(svc.cfg, encryptionKey)
if err != nil {
logger.Logger.WithError(err).Fatal("Failed to init nostr keys")
logger.Logger.WithError(err).Error("Failed to init nostr keys")
return err
}
npub, err := nip19.EncodePublicKey(svc.keys.GetNostrPublicKey())
if err != nil {
logger.Logger.WithError(err).Fatal("Error converting nostr privkey to pubkey")
logger.Logger.WithError(err).Error("Error converting nostr privkey to pubkey")
return err
}
logger.Logger.WithFields(logrus.Fields{
@ -204,7 +207,8 @@ func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) e
lnClient, err = cashu.NewCashuService(cashuWorkdir, cashuMintUrl)
default:
logger.Logger.Fatalf("Unsupported LNBackendType: %v", lnBackend)
logger.Logger.WithField("backend_type", lnBackend).Error("Unsupported LNBackendType")
return fmt.Errorf("unsupported backend type: %s", lnBackend)
}
if err != nil {
logger.Logger.WithError(err).Error("Failed to launch LN backend")
@ -227,7 +231,10 @@ func (svc *service) launchLNBackend(ctx context.Context, encryptionKey string) e
// Mark that the node has successfully started
// This will ensure the user cannot go through the setup again
svc.cfg.SetUpdate("NodeLastStartTime", strconv.FormatInt(time.Now().Unix(), 10), "")
err = svc.cfg.SetUpdate("NodeLastStartTime", strconv.FormatInt(time.Now().Unix(), 10), "")
if err != nil {
logger.Logger.WithError(err).Error("Failed to set last node start time")
}
svc.eventPublisher.Publish(&events.Event{
Event: "nwc_node_started",

View file

@ -33,10 +33,13 @@ func CreateTestService() (svc *TestService, err error) {
Workdir: ".test",
}
cfg := config.NewConfig(
cfg, err := config.NewConfig(
appConfig,
gormDb,
)
if err != nil {
return nil, err
}
keys := keys.NewKeys()
keys.Init(cfg, "")

View file

@ -3,7 +3,6 @@ package wails
import (
"context"
"embed"
"log"
"github.com/getAlby/hub/api"
"github.com/getAlby/hub/logger"
@ -65,7 +64,7 @@ func LaunchWailsApp(app *WailsApp, assets embed.FS, appIcon []byte) {
})
if err != nil {
log.Fatalf("Error %v", err)
logger.Logger.WithError(err).Error("failed to run Wails app")
}
}