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/push"
|
||||||
"github.com/evcc-io/evcc/server"
|
"github.com/evcc-io/evcc/server"
|
||||||
"github.com/evcc-io/evcc/server/db"
|
"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/db/settings"
|
||||||
"github.com/evcc-io/evcc/server/eebus"
|
"github.com/evcc-io/evcc/server/eebus"
|
||||||
"github.com/evcc-io/evcc/server/modbus"
|
"github.com/evcc-io/evcc/server/modbus"
|
||||||
|
|
@ -588,6 +589,10 @@ func configureDatabase(conf globalconfig.DB) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cache.Init(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
persistSettings := func() {
|
persistSettings := func() {
|
||||||
if err := settings.Persist(); err != nil {
|
if err := settings.Persist(); err != nil {
|
||||||
log.ERROR.Println("cannot save settings:", err)
|
log.ERROR.Println("cannot save settings:", err)
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@
|
||||||
"sessions": "Ladevorgänge",
|
"sessions": "Ladevorgänge",
|
||||||
"sessionsDescription": "Löscht den Verlauf deiner Ladevorgänge.",
|
"sessionsDescription": "Löscht den Verlauf deiner Ladevorgänge.",
|
||||||
"settings": "Konfiguration & Einstellungen",
|
"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"
|
"title": "Zurücksetzen"
|
||||||
},
|
},
|
||||||
"restore": {
|
"restore": {
|
||||||
|
|
|
||||||
|
|
@ -457,7 +457,7 @@
|
||||||
"sessions": "Charging sessions",
|
"sessions": "Charging sessions",
|
||||||
"sessionsDescription": "Deletes your charging session history.",
|
"sessionsDescription": "Deletes your charging session history.",
|
||||||
"settings": "Configuration & settings",
|
"settings": "Configuration & settings",
|
||||||
"settingsDescription": "Deletes all configured devices, services, plans, etc.",
|
"settingsDescription": "Deletes all configured devices, services, plans, caches, etc.",
|
||||||
"title": "Reset"
|
"title": "Reset"
|
||||||
},
|
},
|
||||||
"restore": {
|
"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 {
|
if req.Settings {
|
||||||
query := db.Instance.Exec("DELETE FROM settings")
|
tables := []string{"settings", "configs", "caches", "meters"}
|
||||||
if query.Error != nil {
|
|
||||||
jsonError(w, http.StatusInternalServerError, query.Error)
|
for _, table := range tables {
|
||||||
return
|
if err := db.Instance.Exec("DELETE FROM " + table).Error; err != nil {
|
||||||
}
|
jsonError(w, http.StatusInternalServerError, err)
|
||||||
query = db.Instance.Exec("DELETE FROM configs")
|
return
|
||||||
if query.Error != nil {
|
}
|
||||||
jsonError(w, http.StatusInternalServerError, query.Error)
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/evcc-io/evcc/api"
|
"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 {
|
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 {
|
func cachePut(key string, typ api.TariffType, rates api.Rates) error {
|
||||||
return settings.SetJson(key, &cached{
|
return cache.Put(key, &cached{
|
||||||
Type: typ,
|
Type: typ,
|
||||||
Rates: rates,
|
Rates: rates,
|
||||||
})
|
})
|
||||||
|
|
@ -26,5 +26,5 @@ func cachePut(key string, typ api.TariffType, rates api.Rates) error {
|
||||||
|
|
||||||
func cacheGet(key string) (*cached, error) {
|
func cacheGet(key string) (*cached, error) {
|
||||||
var res cached
|
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