Skip to content

Commit

Permalink
cmd,sqlite: add rebuild command
Browse files Browse the repository at this point in the history
  • Loading branch information
n8maninger committed May 21, 2024
1 parent fcef632 commit 107d34c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
28 changes: 28 additions & 0 deletions cmd/hostd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"go.sia.tech/hostd/build"
"go.sia.tech/hostd/config"
"go.sia.tech/hostd/internal/explorer"
"go.sia.tech/hostd/persist/sqlite"
"go.sia.tech/jape"
"go.sia.tech/web/hostd"
"go.uber.org/zap"
Expand Down Expand Up @@ -231,6 +232,33 @@ func main() {
case "config":
buildConfig()
return
case "rebuild":
fp := flag.Arg(1)

levelStr := cfg.Log.StdOut.Level
if levelStr == "" {
levelStr = cfg.Log.Level
}

level := parseLogLevel(levelStr)
core := zapcore.NewCore(humanEncoder(cfg.Log.StdOut.EnableANSI), zapcore.Lock(os.Stdout), level)
log := zap.New(core, zap.AddCaller())
defer log.Sync()

db, err := sqlite.OpenDatabase(fp, log)
if err != nil {
log.Fatal("failed to open database", zap.Error(err))
}
defer db.Close()

if err := db.CheckContractAccountFunding(); err != nil {
log.Fatal("failed to check contract account funding", zap.Error(err))
} else if err := db.RecalcContractAccountFunding(); err != nil {
log.Fatal("failed to recalculate contract account funding", zap.Error(err))
} else if err := db.CheckContractAccountFunding(); err != nil {
log.Fatal("failed to check contract account funding", zap.Error(err))
}
return
}

ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
Expand Down
93 changes: 93 additions & 0 deletions persist/sqlite/recalc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package sqlite

import (
"fmt"

"go.sia.tech/core/types"
"go.uber.org/zap"
)

func checkContractAccountFunding(tx txn, log *zap.Logger) error {
rows, err := tx.Query(`SELECT contract_id, amount FROM contract_account_funding`)
if err != nil {
return fmt.Errorf("failed to query contract account funding: %w", err)
}
defer rows.Close()

contractFunding := make(map[int64]types.Currency)
for rows.Next() {
var contractID int64
var amount types.Currency
if err := rows.Scan(&contractID, (*sqlCurrency)(&amount)); err != nil {
return fmt.Errorf("failed to scan contract account funding: %w", err)
}
contractFunding[contractID] = contractFunding[contractID].Add(amount)
}

if err := rows.Err(); err != nil {
return fmt.Errorf("failed to iterate contract account funding: %w", err)
} else if err := rows.Close(); err != nil {
return fmt.Errorf("failed to close contract account funding: %w", err)
}

for contractID, amount := range contractFunding {
var actualAmount types.Currency
err := tx.QueryRow(`SELECT account_funding FROM contracts WHERE id=$1`, contractID).Scan((*sqlCurrency)(&actualAmount))
if err != nil {
return fmt.Errorf("failed to query contract account funding: %w", err)
}

if !actualAmount.Equals(amount) {
log.Debug("incorrect contract account funding", zap.Int64("contractID", contractID), zap.Stringer("expected", amount), zap.Stringer("actual", actualAmount))
}
}
return nil
}

func recalcContractAccountFunding(tx txn, _ *zap.Logger) error {
rows, err := tx.Query(`SELECT contract_id, amount FROM contract_account_funding`)
if err != nil {
return fmt.Errorf("failed to query contract account funding: %w", err)
}
defer rows.Close()

contractFunding := make(map[int64]types.Currency)
for rows.Next() {
var contractID int64
var amount types.Currency
if err := rows.Scan(&contractID, (*sqlCurrency)(&amount)); err != nil {
return fmt.Errorf("failed to scan contract account funding: %w", err)
}
contractFunding[contractID] = contractFunding[contractID].Add(amount)
}

if err := rows.Err(); err != nil {
return fmt.Errorf("failed to iterate contract account funding: %w", err)
} else if err := rows.Close(); err != nil {
return fmt.Errorf("failed to close contract account funding: %w", err)
}

for contractID, amount := range contractFunding {
res, err := tx.Exec(`UPDATE contracts SET account_funding=$1 WHERE id=$2`, sqlCurrency(amount), contractID)
if err != nil {
return fmt.Errorf("failed to query contract account funding: %w", err)
} else if rowsAffected, err := res.RowsAffected(); err != nil {
return fmt.Errorf("failed to query contract account funding: %w", err)
} else if rowsAffected != 1 {
return fmt.Errorf("failed to update contract account funding: %w", err)
}
}
return nil
}

func (s *Store) CheckContractAccountFunding() error {

Check warning on line 83 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 1.21)

exported: exported method Store.CheckContractAccountFunding should have comment or be unexported (revive)

Check warning on line 83 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test

exported: exported method Store.CheckContractAccountFunding should have comment or be unexported (revive)

Check warning on line 83 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test

exported: exported method Store.CheckContractAccountFunding should have comment or be unexported (revive)
return s.transaction(func(tx txn) error {
return checkContractAccountFunding(tx, s.log)
})
}

func (s *Store) RecalcContractAccountFunding() error {

Check warning on line 89 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test (ubuntu-latest, 1.21)

exported: exported method Store.RecalcContractAccountFunding should have comment or be unexported (revive)

Check warning on line 89 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test

exported: exported method Store.RecalcContractAccountFunding should have comment or be unexported (revive)

Check warning on line 89 in persist/sqlite/recalc.go

View workflow job for this annotation

GitHub Actions / test

exported: exported method Store.RecalcContractAccountFunding should have comment or be unexported (revive)
return s.transaction(func(tx txn) error {
return recalcContractAccountFunding(tx, s.log)
})
}

0 comments on commit 107d34c

Please sign in to comment.