diff --git a/cmd/mint/mint.go b/cmd/mint/mint.go index d1ff443..951fdce 100644 --- a/cmd/mint/mint.go +++ b/cmd/mint/mint.go @@ -5,8 +5,11 @@ import ( "errors" "fmt" "log" + "net/http" "os" + "os/signal" "strconv" + "syscall" "github.com/elnosh/gonuts/cashu/nuts/nut06" "github.com/elnosh/gonuts/mint" @@ -32,6 +35,11 @@ func configFromEnv() (*mint.Config, error) { return nil, fmt.Errorf("invalid DERIVATION_PATH_IDX: %v", err) } + port := os.Getenv("MINT_PORT") + if len(port) == 0 { + port = "3338" + } + mintLimits := mint.MintLimits{} if maxBalanceEnv, ok := os.LookupEnv("MAX_BALANCE"); ok { maxBalance, err := strconv.ParseUint(maxBalanceEnv, 10, 64) @@ -126,7 +134,7 @@ func configFromEnv() (*mint.Config, error) { return &mint.Config{ DerivationPathIdx: uint32(derivationPathIdx), - Port: os.Getenv("MINT_PORT"), + Port: port, MintPath: os.Getenv("MINT_DB_PATH"), DBMigrationPath: "../../mint/storage/sqlite/migrations", InputFeePpk: inputFeePpk, @@ -151,5 +159,20 @@ func main() { log.Fatalf("error starting mint server: %v", err) } - mint.StartMintServer(mintServer) + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT) + + go func() { + <-c + mintServer.LogInfo("starting shutdown") + mintServer.Shutdown() + }() + + mintServer.LogInfo("mint server listening on port: " + mintConfig.Port) + if err := mintServer.Start(); err != nil && err != http.ErrServerClosed { + log.Fatalf("error runnming mint: %v\n", err) + } else if err == http.ErrServerClosed { + mintServer.LogInfo("shutdown complete") + } + } diff --git a/mint/server.go b/mint/server.go index 892e5a9..19dd360 100644 --- a/mint/server.go +++ b/mint/server.go @@ -1,11 +1,11 @@ package mint import ( + "context" "encoding/json" "errors" "fmt" "io" - "log" "log/slog" "net/http" "os" @@ -28,9 +28,8 @@ type MintServer struct { logger *slog.Logger } -func StartMintServer(server *MintServer) { - server.logger.Info("mint server listening on: " + server.httpServer.Addr) - log.Fatal(server.httpServer.ListenAndServe()) +func (ms *MintServer) Start() error { + return ms.httpServer.ListenAndServe() } func SetupMintServer(config Config) (*MintServer, error) { @@ -44,10 +43,18 @@ func SetupMintServer(config Config) (*MintServer, error) { return nil, err } mintServer := &MintServer{mint: mint, logger: logger} - mintServer.setupHttpServer(config.Port) + err = mintServer.setupHttpServer(config.Port) + if err != nil { + return nil, err + } return mintServer, nil } +func (ms *MintServer) Shutdown() { + ms.mint.db.Close() + ms.httpServer.Shutdown(context.Background()) +} + func setupLogger() (*slog.Logger, error) { replacer := func(groups []string, a slog.Attr) slog.Attr { if a.Key == slog.SourceKey { @@ -73,12 +80,12 @@ func (ms *MintServer) LogInfo(format string, v ...any) { ms.logger.Info(msg) } -// func (m *Mint) LogError(format string, v ...any) { -// msg := fmt.Sprintf(format, v...) -// m.logger.Error(msg) -// } +func (ms *MintServer) LogError(format string, v ...any) { + msg := fmt.Sprintf(format, v...) + ms.logger.Error(msg) +} -func (ms *MintServer) setupHttpServer(port string) { +func (ms *MintServer) setupHttpServer(port string) error { r := mux.NewRouter() r.HandleFunc("/v1/keys", ms.getActiveKeysets).Methods(http.MethodGet, http.MethodOptions) @@ -96,7 +103,7 @@ func (ms *MintServer) setupHttpServer(port string) { r.Use(setupHeaders) if len(port) == 0 { - port = "3338" + return fmt.Errorf("port cannot be empty") } server := &http.Server{ Addr: "127.0.0.1:" + port, @@ -104,6 +111,7 @@ func (ms *MintServer) setupHttpServer(port string) { } ms.httpServer = server + return nil } func setupHeaders(next http.Handler) http.Handler { diff --git a/mint/storage/sqlite/sqlite.go b/mint/storage/sqlite/sqlite.go index 79ca09f..b92e8b3 100644 --- a/mint/storage/sqlite/sqlite.go +++ b/mint/storage/sqlite/sqlite.go @@ -46,6 +46,10 @@ func InitSQLite(path, migrationPath string) (*SQLiteDB, error) { return &SQLiteDB{db: db}, nil } +func (sqlite *SQLiteDB) Close() { + sqlite.db.Close() +} + func (sqlite *SQLiteDB) GetBalance() (uint64, error) { var balance uint64 row := sqlite.db.QueryRow("SELECT balance FROM balance") diff --git a/mint/storage/storage.go b/mint/storage/storage.go index 0074a55..ccdf86b 100644 --- a/mint/storage/storage.go +++ b/mint/storage/storage.go @@ -26,6 +26,8 @@ type MintDB interface { SaveMeltQuote(MeltQuote) error GetMeltQuote(string) (*MeltQuote, error) UpdateMeltQuote(quoteId string, preimage string, state nut05.State) error + + Close() } type DBKeyset struct { diff --git a/wallet/wallet_integration_test.go b/wallet/wallet_integration_test.go index ecfe8ca..8b498c8 100644 --- a/wallet/wallet_integration_test.go +++ b/wallet/wallet_integration_test.go @@ -13,7 +13,6 @@ import ( "testing" btcdocker "github.com/elnosh/btc-docker-test" - "github.com/elnosh/gonuts/mint" "github.com/elnosh/gonuts/testutils" "github.com/elnosh/gonuts/wallet" "github.com/lightningnetwork/lnd/lnrpc" @@ -86,7 +85,7 @@ func testMain(m *testing.M) int { defer func() { os.RemoveAll(testMintPath) }() - go mint.StartMintServer(testMint) + go testMint.Start() mintPath := filepath.Join(".", "testmintwithfees") mintWithFees, err := testutils.CreateTestMintServer(lnd1, "8888", mintPath, dbMigrationPath, 100) @@ -97,7 +96,7 @@ func testMain(m *testing.M) int { defer func() { os.RemoveAll(mintPath) }() - go mint.StartMintServer(mintWithFees) + go mintWithFees.Start() return m.Run() } @@ -250,7 +249,7 @@ func TestReceive(t *testing.T) { defer func() { os.RemoveAll(testMintPath) }() - go mint.StartMintServer(testMint) + go testMint.Start() mint2URL := "http://127.0.0.1:3339" testWalletPath2 := filepath.Join(".", "/testreceivewallet2")