Initial commit
This commit is contained in:
137
internal/moon/db.go
Normal file
137
internal/moon/db.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package moon
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
|
||||
"github.com/cockroachdb/errors/oserror"
|
||||
"github.com/cockroachdb/pebble"
|
||||
)
|
||||
|
||||
// StoreKV сохраняет в указанной бд ключ и значение.
|
||||
func StoreKV(db *pebble.DB, key string, value string) error {
|
||||
var (
|
||||
kArray = []byte(key)
|
||||
vArray = []byte(value)
|
||||
)
|
||||
|
||||
err := db.Set(kArray, vArray, pebble.Sync)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = db.Flush()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// FetchV достаёт значение по ключу.
|
||||
func FetchV(db *pebble.DB, key string) (string, error) {
|
||||
var (
|
||||
kArray = []byte(key)
|
||||
|
||||
vArray []byte
|
||||
valueString = ""
|
||||
)
|
||||
|
||||
vArray, closer, err := db.Get(kArray)
|
||||
|
||||
if err != nil {
|
||||
return valueString, err
|
||||
}
|
||||
|
||||
valueString = string(vArray)
|
||||
err = closer.Close()
|
||||
|
||||
return valueString, err
|
||||
}
|
||||
|
||||
// GetValue достаёт настройку из БД с настройками.
|
||||
// TODO: should return string, error and should not log error internally.
|
||||
func (cfg *MyConfig) GetValue(dataBaseName string, chatID string, setting string) string {
|
||||
var err error
|
||||
|
||||
chatHash := sha256.Sum256([]byte(chatID))
|
||||
dataBaseDir := fmt.Sprintf("db/%s/%x", dataBaseName, chatHash)
|
||||
|
||||
// Если БД не открыта, откроем её
|
||||
if _, ok := DB[dataBaseDir]; !ok {
|
||||
var options pebble.Options
|
||||
// По дефолту ограничение ставится на мегабайты данных, а не на количество файлов, поэтому с дефолтными
|
||||
// настройками порождается огромное количество файлов. Умолчальное ограничение на количество файлов - 500 штук,
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений.
|
||||
options.L0CompactionFileThreshold = 8
|
||||
|
||||
if err := os.MkdirAll(dataBaseDir, os.ModePerm); err != nil {
|
||||
Log.Errorf("Unable to create db dir %s: %s", dataBaseDir, err)
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
DB[dataBaseDir], err = pebble.Open(dataBaseDir, &options)
|
||||
|
||||
if err != nil {
|
||||
Log.Errorf("Unable to open db, %s: %s\n", dataBaseDir, err)
|
||||
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
value, err := FetchV(DB[dataBaseDir], setting)
|
||||
|
||||
// Если из базы ничего не вынулось, по каким-то причинам, то просто вернём пустую строку.
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, pebble.ErrNotFound):
|
||||
Log.Debugf("Unable to get value for %s: no record found in db %s", setting, dataBaseDir)
|
||||
case errors.Is(err, fs.ErrNotExist):
|
||||
Log.Debugf("Unable to get value for %s: db dir %s does not exist", setting, dataBaseDir)
|
||||
case errors.Is(err, oserror.ErrNotExist):
|
||||
Log.Debugf("Unable to get value for %s: db dir %s does not exist", setting, dataBaseDir)
|
||||
default:
|
||||
Log.Errorf("Unable to get value for %s in db dir %s: %s", setting, dataBaseDir, err)
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
// SaveSetting сохраняет настройку в БД с настройками.
|
||||
func (cfg *MyConfig) SaveKeyValue(dataBaseName string, chatID string, setting string, value string) error {
|
||||
var (
|
||||
chatHash = sha256.Sum256([]byte(chatID))
|
||||
dataBaseDir = fmt.Sprintf("%s/db/%s/%x", cfg.DataDir, dataBaseName, chatHash)
|
||||
err error
|
||||
)
|
||||
|
||||
// Если БД не открыта, откроем её.
|
||||
if _, ok := DB[dataBaseDir]; !ok {
|
||||
var options pebble.Options
|
||||
// По дефолту ограничение ставится на мегабайты данных, а не на количество файлов, поэтому с дефолтными
|
||||
// настройками порождается огромное количество файлов. Умолчальное ограничение на количество файлов - 500 штук,
|
||||
// что нас не устраивает, поэтому немного снизим эту цифру до более приемлемых значений.
|
||||
options.L0CompactionFileThreshold = 8
|
||||
|
||||
if err := os.MkdirAll(dataBaseDir, os.ModePerm); err != nil {
|
||||
return fmt.Errorf("unable to create db dir %s: %w", dataBaseDir, err)
|
||||
}
|
||||
|
||||
DB[dataBaseDir], err = pebble.Open(dataBaseDir, &options)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open settings db, %s: %w", dataBaseDir, err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := StoreKV(DB[dataBaseDir], setting, value); err != nil {
|
||||
return fmt.Errorf("unable to save setting %s in database %s: %w", setting, dataBaseDir, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user