vspd: Separate vspd and webapi.

The vspd Run func is now blocking and returns when its provided context
is cancelled. This means it is invoked/canceled in the same way as the
webapi Run func.

webapi is now created in the main run func rather than within vspd,
further decoupling these components.
This commit is contained in:
jholdstock 2023-09-15 14:53:42 +01:00 committed by Jamie Holdstock
parent ba3c7bf6d9
commit 6c245b8418
2 changed files with 83 additions and 84 deletions

View File

@ -8,11 +8,13 @@ import (
"fmt" "fmt"
"os" "os"
"runtime" "runtime"
"sync"
"github.com/decred/dcrd/wire" "github.com/decred/dcrd/wire"
"github.com/decred/vspd/database" "github.com/decred/vspd/database"
"github.com/decred/vspd/internal/config" "github.com/decred/vspd/internal/config"
"github.com/decred/vspd/internal/version" "github.com/decred/vspd/internal/version"
"github.com/decred/vspd/internal/webapi"
"github.com/decred/vspd/rpc" "github.com/decred/vspd/rpc"
) )
@ -71,11 +73,51 @@ func run() int {
wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.network.Params, rpcLog) wallets := rpc.SetupWallet(cfg.walletUsers, cfg.walletPasswords, cfg.walletHosts, cfg.walletCerts, cfg.network.Params, rpcLog)
defer wallets.Close() defer wallets.Close()
vspd := newVspd(cfg, log, db, dcrd, wallets, blockNotifChan) // Create webapi server.
apiCfg := webapi.Config{
Listen: cfg.Listen,
VSPFee: cfg.VSPFee,
Network: cfg.network,
SupportEmail: cfg.SupportEmail,
VspClosed: cfg.VspClosed,
VspClosedMsg: cfg.VspClosedMsg,
AdminPass: cfg.AdminPass,
Debug: cfg.WebServerDebug,
Designation: cfg.Designation,
MaxVoteChangeRecords: maxVoteChangeRecords,
VspdVersion: version.String(),
}
api, err := webapi.New(db, cfg.logger("API"), dcrd, wallets, apiCfg)
if err != nil {
log.Errorf("Failed to initialize webapi: %v", err)
return 1
}
// WaitGroup for services to signal when they have shutdown cleanly.
var shutdownWg sync.WaitGroup
// Create a context that is canceled when a shutdown request is received // Create a context that is canceled when a shutdown request is received
// through an interrupt signal. // through an interrupt signal.
ctx := shutdownListener(log) ctx := shutdownListener(log)
return vspd.run(ctx) // Start the webapi server.
shutdownWg.Add(1)
go func() {
api.Run(ctx)
shutdownWg.Done()
}()
// Start vspd.
vspd := newVspd(cfg, log, db, dcrd, wallets, blockNotifChan)
shutdownWg.Add(1)
go func() {
vspd.run(ctx)
shutdownWg.Done()
}()
// Wait for shutdown tasks to complete before running deferred tasks and
// returning.
shutdownWg.Wait()
return 0
} }

View File

@ -9,14 +9,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"strings" "strings"
"sync"
"time" "time"
"github.com/decred/dcrd/wire" "github.com/decred/dcrd/wire"
"github.com/decred/slog" "github.com/decred/slog"
"github.com/decred/vspd/database" "github.com/decred/vspd/database"
"github.com/decred/vspd/internal/version"
"github.com/decred/vspd/internal/webapi"
"github.com/decred/vspd/rpc" "github.com/decred/vspd/rpc"
"github.com/jrick/wsrpc/v2" "github.com/jrick/wsrpc/v2"
) )
@ -69,14 +66,14 @@ func newVspd(cfg *vspdConfig, log slog.Logger, db *database.VspDatabase,
return v return v
} }
func (v *vspd) run(ctx context.Context) int { func (v *vspd) run(ctx context.Context) {
// Run database integrity checks to ensure all data in database is present // Run database integrity checks to ensure all data in database is present
// and up-to-date. // and up-to-date.
err := v.checkDatabaseIntegrity(ctx) err := v.checkDatabaseIntegrity(ctx)
if err != nil { if err != nil {
// Don't log error if shutdown was requested, just return. // Don't log error if shutdown was requested, just return.
if errors.Is(err, context.Canceled) { if errors.Is(err, context.Canceled) {
return 0 return
} }
// vspd should still start if this fails, so just log an error. // vspd should still start if this fails, so just log an error.
@ -85,7 +82,7 @@ func (v *vspd) run(ctx context.Context) int {
// Stop if shutdown requested. // Stop if shutdown requested.
if ctx.Err() != nil { if ctx.Err() != nil {
return 0 return
} }
// Run the block connected handler now to catch up with any blocks mined // Run the block connected handler now to catch up with any blocks mined
@ -94,7 +91,7 @@ func (v *vspd) run(ctx context.Context) int {
// Stop if shutdown requested. // Stop if shutdown requested.
if ctx.Err() != nil { if ctx.Err() != nil {
return 0 return
} }
// Run voting wallet consistency check now to ensure all wallets are up to // Run voting wallet consistency check now to ensure all wallets are up to
@ -103,42 +100,10 @@ func (v *vspd) run(ctx context.Context) int {
// Stop if shutdown requested. // Stop if shutdown requested.
if ctx.Err() != nil { if ctx.Err() != nil {
return 0 return
} }
// Create webapi server.
apiCfg := webapi.Config{
Listen: v.cfg.Listen,
VSPFee: v.cfg.VSPFee,
Network: v.cfg.network,
SupportEmail: v.cfg.SupportEmail,
VspClosed: v.cfg.VspClosed,
VspClosedMsg: v.cfg.VspClosedMsg,
AdminPass: v.cfg.AdminPass,
Debug: v.cfg.WebServerDebug,
Designation: v.cfg.Designation,
MaxVoteChangeRecords: maxVoteChangeRecords,
VspdVersion: version.String(),
}
api, err := webapi.New(v.db, v.cfg.logger("API"), v.dcrd, v.wallets, apiCfg)
if err != nil {
v.log.Errorf("Failed to initialize webapi: %v", err)
return 1
}
// WaitGroup for services to signal when they have shutdown cleanly.
var shutdownWg sync.WaitGroup
// Start the webapi server.
shutdownWg.Add(1)
go func() {
api.Run(ctx)
shutdownWg.Done()
}()
// Start all background tasks and notification handlers. // Start all background tasks and notification handlers.
shutdownWg.Add(1)
go func() {
backupTicker := time.NewTicker(v.cfg.BackupInterval) backupTicker := time.NewTicker(v.cfg.BackupInterval)
defer backupTicker.Stop() defer backupTicker.Stop()
consistencyTicker := time.NewTicker(consistencyInterval) consistencyTicker := time.NewTicker(consistencyInterval)
@ -174,17 +139,9 @@ func (v *vspd) run(ctx context.Context) int {
// Handle shutdown request. // Handle shutdown request.
case <-ctx.Done(): case <-ctx.Done():
shutdownWg.Done()
return return
} }
} }
}()
// Wait for shutdown tasks to complete before running deferred tasks and
// returning.
shutdownWg.Wait()
return 0
} }
// checkDatabaseIntegrity starts the process of ensuring that all data expected // checkDatabaseIntegrity starts the process of ensuring that all data expected