-
Angelo Capossele authored
*
Add panic if backgroundWorker fails * Use log.Panicf instead of panicAngelo Capossele authored*
Add panic if backgroundWorker fails * Use log.Panicf instead of panic
plugin.go 2.79 KiB
// Package database is a plugin that manages the badger database (e.g. garbage collection).
package database
import (
"errors"
"sync"
"time"
"github.com/iotaledger/goshimmer/packages/database"
"github.com/iotaledger/goshimmer/packages/database/prefix"
"github.com/iotaledger/goshimmer/packages/shutdown"
"github.com/iotaledger/goshimmer/plugins/config"
"github.com/iotaledger/hive.go/daemon"
"github.com/iotaledger/hive.go/kvstore"
"github.com/iotaledger/hive.go/logger"
"github.com/iotaledger/hive.go/node"
"github.com/iotaledger/hive.go/timeutil"
)
// PluginName is the name of the database plugin.
const PluginName = "Database"
var (
// Plugin is the plugin instance of the database plugin.
Plugin = node.NewPlugin(PluginName, node.Enabled, configure, run)
log *logger.Logger
db database.DB
store kvstore.KVStore
storeOnce sync.Once
)
// Store returns the KVStore instance.
func Store() kvstore.KVStore {
storeOnce.Do(createStore)
return store
}
// StoreRealm is a factory method for a different realm backed by the KVStore instance.
func StoreRealm(realm kvstore.Realm) kvstore.KVStore {
return Store().WithRealm(realm)
}
func createStore() {
log = logger.NewLogger(PluginName)
var err error
if config.Node.GetBool(CfgDatabaseInMemory) {
db, err = database.NewMemDB()
} else {
dbDir := config.Node.GetString(CfgDatabaseDir)
db, err = database.NewDB(dbDir)
}
if err != nil {
log.Fatal(err)
}
store = db.NewStore()
}
func configure(_ *node.Plugin) {
// assure that the store is initialized
store := Store()
err := checkDatabaseVersion(store.WithRealm([]byte{prefix.DBPrefixDatabaseVersion}))
if errors.Is(err, ErrDBVersionIncompatible) {
log.Panicf("The database scheme was updated. Please delete the database folder.\n%s", err)
}
if err != nil {
log.Panicf("Failed to check database version: %s", err)
}
// we open the database in the configure, so we must also make sure it's closed here
err = daemon.BackgroundWorker(PluginName, closeDB, shutdown.PriorityDatabase)
if err != nil {
log.Panicf("Failed to start as daemon: %s", err)
}
}
func run(_ *node.Plugin) {
if err := daemon.BackgroundWorker(PluginName+"[GC]", runGC, shutdown.PriorityBadgerGarbageCollection); err != nil {
log.Panicf("Failed to start as daemon: %s", err)
}
}
func closeDB(shutdownSignal <-chan struct{}) {
<-shutdownSignal
log.Infof("Syncing database to disk...")
if err := db.Close(); err != nil {
log.Errorf("Failed to flush the database: %s", err)
}
log.Infof("Syncing database to disk... done")
}
func runGC(shutdownSignal <-chan struct{}) {
if !db.RequiresGC() {
return
}
// run the garbage collection with the given interval
timeutil.Ticker(func() {
if err := db.GC(); err != nil {
log.Warnf("Garbage collection failed: %s", err)
}
}, 5*time.Minute, shutdownSignal)
}