Skip to content

Commit

Permalink
Merge pull request #463 from SiaFoundation/nate/add-db-backup
Browse files Browse the repository at this point in the history
Add SQLite3 backup
  • Loading branch information
n8maninger authored Sep 13, 2024
2 parents 77ac85a + 510c255 commit 573428f
Show file tree
Hide file tree
Showing 12 changed files with 463 additions and 82 deletions.
12 changes: 10 additions & 2 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ type (
BroadcastV2TransactionSet(index types.ChainIndex, txns []types.V2Transaction)
}

// The SQLite3Store provides an interface for backing up a SQLite3 database
SQLite3Store interface {
Backup(ctx context.Context, destPath string) error
}

// A ChainManager retrieves the current blockchain state
ChainManager interface {
Tip() types.ChainIndex
Expand Down Expand Up @@ -164,6 +169,8 @@ type (
webhooks Webhooks
sessions RHPSessionReporter

sqlite3Store SQLite3Store

syncer Syncer
chain ChainManager
accounts AccountManager
Expand Down Expand Up @@ -294,8 +301,9 @@ func NewServer(name string, hostKey types.PublicKey, cm ChainManager, s Syncer,
"GET /wallet/pending": a.handleGETWalletPending,
"POST /wallet/send": a.handlePOSTWalletSend,
// system endpoints
"GET /system/dir": a.handleGETSystemDir,
"PUT /system/dir": a.handlePUTSystemDir,
"GET /system/dir": a.handleGETSystemDir,
"PUT /system/dir": a.handlePUTSystemDir,
"POST /system/sqlite3/backup": a.handlePOSTSystemSQLite3Backup,
// webhook endpoints
"GET /webhooks": a.handleGETWebhooks,
"POST /webhooks": a.handlePOSTWebhooks,
Expand Down
6 changes: 6 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,12 @@ func (c *Client) LocalDir(path string) (resp SystemDirResponse, err error) {
return
}

// BackupSQLite3 creates a backup of the SQLite3 database at the specified path
// on the local filesystem.
func (c *Client) BackupSQLite3(destPath string) error {
return c.c.POST("/system/sqlite3/backup", BackupRequest{destPath}, nil)
}

// MkDir creates a new directory on the host.
func (c *Client) MkDir(path string) error {
req := CreateDirRequest{
Expand Down
14 changes: 14 additions & 0 deletions api/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ func (a *api) handleGETPeriodMetrics(jc jape.Context) {
return
} else if start.After(time.Now()) {
jc.Error(errors.New("start time cannot be in the future"), http.StatusBadRequest)
return
}

start, err := metrics.Normalize(start, interval)
Expand Down Expand Up @@ -579,6 +580,19 @@ func (a *api) handlePUTSystemDir(jc jape.Context) {
a.checkServerError(jc, "failed to create dir", os.MkdirAll(req.Path, 0775))
}

func (a *api) handlePOSTSystemSQLite3Backup(jc jape.Context) {
if a.sqlite3Store == nil {
jc.Error(errors.New("sqlite3 store not available"), http.StatusNotFound)
return
}

var req BackupRequest
if err := jc.Decode(&req); err != nil {
return
}
a.checkServerError(jc, "failed to backup", a.sqlite3Store.Backup(jc.Request.Context(), req.Path))
}

func (a *api) handleGETTPoolFee(jc jape.Context) {
a.writeResponse(jc, TPoolResp(a.chain.RecommendedFee()))
}
Expand Down
34 changes: 22 additions & 12 deletions api/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,54 @@ import (
// ServerOption is a functional option to configure an API server.
type ServerOption func(*api)

// ServerWithAlerts sets the alerts manager for the API server.
func ServerWithAlerts(al Alerts) ServerOption {
// WithAlerts sets the alerts manager for the API server.
func WithAlerts(al Alerts) ServerOption {
return func(a *api) {
a.alerts = al
}
}

// ServerWithWebhooks sets the webhooks manager for the API server.
func ServerWithWebhooks(w Webhooks) ServerOption {
// WithSQLite3Store sets the SQLite3 store for the API server.
//
// This option is not required since it is only used for backups and there
// may be other stores in the future.
func WithSQLite3Store(s SQLite3Store) ServerOption {
return func(a *api) {
a.sqlite3Store = s
}
}

// WithWebhooks sets the webhooks manager for the API server.
func WithWebhooks(w Webhooks) ServerOption {
return func(a *api) {
a.webhooks = w
}
}

// ServerWithPinnedSettings sets the pinned settings for the API server.
func ServerWithPinnedSettings(p PinnedSettings) ServerOption {
// WithPinnedSettings sets the pinned settings for the API server.
func WithPinnedSettings(p PinnedSettings) ServerOption {
return func(a *api) {
a.pinned = p
}
}

// ServerWithExplorer sets the explorer for the API server.
func ServerWithExplorer(explorer *explorer.Explorer) ServerOption {
// WithExplorer sets the explorer for the API server.
func WithExplorer(explorer *explorer.Explorer) ServerOption {
return func(a *api) {
a.explorerDisabled = false
a.explorer = explorer
}
}

// ServerWithRHPSessionReporter sets the RHP session reporter for the API server.
func ServerWithRHPSessionReporter(rsr RHPSessionReporter) ServerOption {
// WithRHPSessionReporter sets the RHP session reporter for the API server.
func WithRHPSessionReporter(rsr RHPSessionReporter) ServerOption {
return func(a *api) {
a.sessions = rsr
}
}

// ServerWithLogger sets the logger for the API server.
func ServerWithLogger(log *zap.Logger) ServerOption {
// WithLogger sets the logger for the API server.
func WithLogger(log *zap.Logger) ServerOption {
return func(a *api) {
a.log = log
}
Expand Down
5 changes: 5 additions & 0 deletions api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ type (
Path string `json:"path"`
}

// A BackupRequest is the request body for the [POST] /system/backup endpoint.
BackupRequest struct {
Path string `json:"path"`
}

// VerifySectorResponse is the response body for the [GET] /sectors/:root/verify endpoint.
VerifySectorResponse struct {
storage.SectorReference
Expand Down
2 changes: 1 addition & 1 deletion cmd/hostd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ func setDataDirectory() {
cfg.Directory = readInput("Enter data directory")
}

func buildConfig() {
func runConfigCmd() {
// write the config file
configPath := "hostd.yml"
if str := os.Getenv(configFileEnvVar); str != "" {
Expand Down
Loading

0 comments on commit 573428f

Please sign in to comment.