Add dedicated db cache table (#22650)
Some checks failed
Some checks failed
This commit is contained in:
parent
31d01bccd3
commit
a8c16f2853
9 changed files with 205 additions and 14 deletions
52
cmd/cache-clear.go
Normal file
52
cmd/cache-clear.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/evcc-io/evcc/server/db/cache"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// cacheClearCmd represents the cache clear command
|
||||
var cacheClearCmd = &cobra.Command{
|
||||
Use: "clear",
|
||||
Short: "Clear all cache entries",
|
||||
Run: runCacheClear,
|
||||
}
|
||||
|
||||
func init() {
|
||||
cacheCmd.AddCommand(cacheClearCmd)
|
||||
cacheClearCmd.Flags().BoolP(flagForce, "f", false, "Force (no confirmation)")
|
||||
}
|
||||
|
||||
func runCacheClear(cmd *cobra.Command, args []string) {
|
||||
// load config
|
||||
if err := loadConfigFile(&conf, !cmd.Flag(flagIgnoreDatabase).Changed); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
// setup persistence
|
||||
if err := configureDatabase(conf.Database); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
confirmation, _ := cmd.Flags().GetBool(flagForce)
|
||||
if !confirmation {
|
||||
prompt := &survey.Confirm{
|
||||
Message: "Clear all cache entries",
|
||||
}
|
||||
|
||||
if err := survey.AskOne(prompt, &confirmation); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
if confirmation {
|
||||
if err := cache.Clear(); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
log.INFO.Println("Cache cleared successfully")
|
||||
}
|
||||
|
||||
// wait for shutdown
|
||||
<-shutdownDoneC()
|
||||
}
|
||||
53
cmd/cache-get.go
Normal file
53
cmd/cache-get.go
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
"github.com/evcc-io/evcc/server/db/cache"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// cacheGetCmd represents the cache get command
|
||||
var cacheGetCmd = &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Get cache entries",
|
||||
Run: runCacheGet,
|
||||
Args: cobra.MaximumNArgs(1),
|
||||
}
|
||||
|
||||
func init() {
|
||||
cacheCmd.AddCommand(cacheGetCmd)
|
||||
}
|
||||
|
||||
func runCacheGet(cmd *cobra.Command, args []string) {
|
||||
// load config
|
||||
if err := loadConfigFile(&conf, !cmd.Flag(flagIgnoreDatabase).Changed); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
// setup persistence
|
||||
if err := configureDatabase(conf.Database); err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
var re *regexp.Regexp
|
||||
if len(args) > 0 {
|
||||
re = regexp.MustCompile(args[0])
|
||||
}
|
||||
|
||||
entries, err := cache.All()
|
||||
if err != nil {
|
||||
log.FATAL.Fatal(err)
|
||||
}
|
||||
|
||||
for _, entry := range entries {
|
||||
if re != nil && !re.MatchString(entry.Key) {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%s:\n", entry.Key)
|
||||
fmt.Println(entry.Value)
|
||||
fmt.Println("---")
|
||||
}
|
||||
}
|
||||
15
cmd/cache.go
Normal file
15
cmd/cache.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// cacheCmd represents the cache command
|
||||
var cacheCmd = &cobra.Command{
|
||||
Use: "cache",
|
||||
Short: "Manage cache entries",
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(cacheCmd)
|
||||
}
|
||||
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/evcc-io/evcc/push"
|
||||
"github.com/evcc-io/evcc/server"
|
||||
"github.com/evcc-io/evcc/server/db"
|
||||
"github.com/evcc-io/evcc/server/db/cache"
|
||||
"github.com/evcc-io/evcc/server/db/settings"
|
||||
"github.com/evcc-io/evcc/server/eebus"
|
||||
"github.com/evcc-io/evcc/server/modbus"
|
||||
|
|
@ -588,6 +589,10 @@ func configureDatabase(conf globalconfig.DB) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if err := cache.Init(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
persistSettings := func() {
|
||||
if err := settings.Persist(); err != nil {
|
||||
log.ERROR.Println("cannot save settings:", err)
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@
|
|||
"sessions": "Ladevorgänge",
|
||||
"sessionsDescription": "Löscht den Verlauf deiner Ladevorgänge.",
|
||||
"settings": "Konfiguration & Einstellungen",
|
||||
"settingsDescription": "Löscht alle konfigurierten Geräte, Dienste, Pläne, usw.",
|
||||
"settingsDescription": "Löscht alle konfigurierten Geräte, Dienste, Pläne, Caches, usw.",
|
||||
"title": "Zurücksetzen"
|
||||
},
|
||||
"restore": {
|
||||
|
|
|
|||
|
|
@ -457,7 +457,7 @@
|
|||
"sessions": "Charging sessions",
|
||||
"sessionsDescription": "Deletes your charging session history.",
|
||||
"settings": "Configuration & settings",
|
||||
"settingsDescription": "Deletes all configured devices, services, plans, etc.",
|
||||
"settingsDescription": "Deletes all configured devices, services, plans, caches, etc.",
|
||||
"title": "Reset"
|
||||
},
|
||||
"restore": {
|
||||
|
|
|
|||
68
server/db/cache/cache.go
vendored
Normal file
68
server/db/cache/cache.go
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"slices"
|
||||
|
||||
"github.com/evcc-io/evcc/server/db"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
var ErrNotFound = errors.New("cache entry not found")
|
||||
|
||||
type Cache struct {
|
||||
Key string `json:"key" gorm:"primarykey"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func Init() error {
|
||||
return db.Instance.AutoMigrate(new(Cache))
|
||||
}
|
||||
|
||||
func Put(key string, value interface{}) error {
|
||||
data, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.Instance.Save(&Cache{
|
||||
Key: key,
|
||||
Value: string(data),
|
||||
}).Error
|
||||
}
|
||||
|
||||
func Get(key string, result interface{}) error {
|
||||
var cacheEntry Cache
|
||||
|
||||
err := db.Instance.First(&cacheEntry, "key = ?", key).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ErrNotFound
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return json.Unmarshal([]byte(cacheEntry.Value), result)
|
||||
}
|
||||
|
||||
func All() ([]Cache, error) {
|
||||
var entries []Cache
|
||||
|
||||
err := db.Instance.Find(&entries).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Sort by key for consistent output
|
||||
slices.SortFunc(entries, func(i, j Cache) int {
|
||||
return cmp.Compare(i.Key, j.Key)
|
||||
})
|
||||
|
||||
return entries, nil
|
||||
}
|
||||
|
||||
func Clear() error {
|
||||
return db.Instance.Delete(&Cache{}, "1=1").Error
|
||||
}
|
||||
|
|
@ -501,15 +501,13 @@ func resetDatabase(authObject auth.Auth, shutdown func()) http.HandlerFunc {
|
|||
}
|
||||
|
||||
if req.Settings {
|
||||
query := db.Instance.Exec("DELETE FROM settings")
|
||||
if query.Error != nil {
|
||||
jsonError(w, http.StatusInternalServerError, query.Error)
|
||||
tables := []string{"settings", "configs", "caches", "meters"}
|
||||
|
||||
for _, table := range tables {
|
||||
if err := db.Instance.Exec("DELETE FROM " + table).Error; err != nil {
|
||||
jsonError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
query = db.Instance.Exec("DELETE FROM configs")
|
||||
if query.Error != nil {
|
||||
jsonError(w, http.StatusInternalServerError, query.Error)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/evcc-io/evcc/api"
|
||||
"github.com/evcc-io/evcc/server/db/settings"
|
||||
"github.com/evcc-io/evcc/server/db/cache"
|
||||
)
|
||||
|
||||
type cached struct {
|
||||
|
|
@ -18,7 +18,7 @@ func cacheKey(typ string, other map[string]any) string {
|
|||
}
|
||||
|
||||
func cachePut(key string, typ api.TariffType, rates api.Rates) error {
|
||||
return settings.SetJson(key, &cached{
|
||||
return cache.Put(key, &cached{
|
||||
Type: typ,
|
||||
Rates: rates,
|
||||
})
|
||||
|
|
@ -26,5 +26,5 @@ func cachePut(key string, typ api.TariffType, rates api.Rates) error {
|
|||
|
||||
func cacheGet(key string) (*cached, error) {
|
||||
var res cached
|
||||
return &res, settings.Json(key, &res)
|
||||
return &res, cache.Get(key, &res)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue