mirror of
https://github.com/1Panel-dev/1Panel.git
synced 2026-09-22 08:00:53 +00:00
feat: Implement caching for settings retrieval and update logic (#11886)
* feat: Implement caching for settings retrieval and update logic - Introduced a caching mechanism for settings using go-cache to improve performance. - Updated the Create, Update, and UpdateOrCreate methods to cache values after database operations. - Modified the Get and GetValueByKey methods to utilize the cache for faster access. - Adjusted middleware to use the new GetValueByKey method for retrieving settings, enhancing code consistency. * feat: Enhance setting cache management with dynamic TTL - Introduced a function to determine cache TTL based on setting keys, allowing critical settings to have shorter cache durations. - Updated cache logic in Create, Update, Get, and GetValueByKey methods to utilize the new TTL management, improving performance and consistency in settings retrieval. * refactor: Simplify setting cache TTL management - Removed the dynamic TTL function and standardized the cache TTL to a fixed duration for all settings. - Updated cache logic in Create, Update, Get, and GetValueByKey methods to use the new fixed TTL, enhancing code clarity and maintainability. - Added a new function to restart the core service after resetting settings, improving the reset command's functionality. * refactor: Remove core restart functionality from reset commands - Eliminated the restartCoreAfterReset function to simplify the reset command logic. - Updated reset commands to return nil after setting changes, enhancing clarity and reducing unnecessary complexity.
This commit is contained in:
@@ -2,14 +2,22 @@ package repo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/model"
|
||||
"github.com/1Panel-dev/1Panel/core/global"
|
||||
"github.com/1Panel-dev/1Panel/core/init/migration/helper"
|
||||
"github.com/patrickmn/go-cache"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type SettingRepo struct{}
|
||||
|
||||
var (
|
||||
settingCache = cache.New(5*time.Minute, 10*time.Minute)
|
||||
settingTTL = 5 * time.Minute
|
||||
)
|
||||
|
||||
type ISettingRepo interface {
|
||||
List(opts ...global.DBOption) ([]model.Setting, error)
|
||||
Get(opts ...global.DBOption) (model.Setting, error)
|
||||
@@ -39,7 +47,11 @@ func (u *SettingRepo) Create(key, value string) error {
|
||||
Key: key,
|
||||
Value: value,
|
||||
}
|
||||
return global.DB.Create(setting).Error
|
||||
if err := global.DB.Create(setting).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) Get(opts ...global.DBOption) (model.Setting, error) {
|
||||
@@ -48,20 +60,33 @@ func (u *SettingRepo) Get(opts ...global.DBOption) (model.Setting, error) {
|
||||
for _, opt := range opts {
|
||||
db = opt(db)
|
||||
}
|
||||
|
||||
err := db.First(&settings).Error
|
||||
if err == nil && settings.Key != "" {
|
||||
settingCache.Set(settings.Key, settings.Value, settingTTL)
|
||||
}
|
||||
return settings, err
|
||||
}
|
||||
|
||||
func (u *SettingRepo) GetValueByKey(key string) (string, error) {
|
||||
if val, found := settingCache.Get(key); found {
|
||||
return val.(string), nil
|
||||
}
|
||||
|
||||
var setting model.Setting
|
||||
if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).First(&setting).Error; err != nil {
|
||||
return "", err
|
||||
}
|
||||
settingCache.Set(key, setting.Value, settingTTL)
|
||||
return setting.Value, nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) Update(key, value string) error {
|
||||
return global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error
|
||||
if err := global.DB.Model(&model.Setting{}).Where("key = ?", key).Updates(map[string]interface{}{"value": value}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
@@ -69,15 +94,28 @@ func (u *SettingRepo) UpdateOrCreate(key, value string) error {
|
||||
result := global.DB.Where("key = ?", key).First(&setting)
|
||||
if result.Error != nil {
|
||||
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
|
||||
return global.DB.Create(&model.Setting{Key: key, Value: value}).Error
|
||||
if err := global.DB.Create(&model.Setting{Key: key, Value: value}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
return result.Error
|
||||
}
|
||||
return global.DB.Model(&setting).UpdateColumn("value", value).Error
|
||||
if err := global.DB.Model(&setting).UpdateColumn("value", value).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set(key, value, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *SettingRepo) DefaultMenu() error {
|
||||
return global.DB.Model(&model.Setting{}).
|
||||
menus := helper.LoadMenus()
|
||||
if err := global.DB.Model(&model.Setting{}).
|
||||
Where("key = ?", "HideMenu").
|
||||
Update("value", helper.LoadMenus()).Error
|
||||
Update("value", menus).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
settingCache.Set("HideMenu", menus, settingTTL)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -62,7 +62,10 @@ var resetSSLCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "SSL", constant.StatusDisable)
|
||||
if err := setSettingByKey(db, "SSL", constant.StatusDisable); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
var resetEntranceCmd = &cobra.Command{
|
||||
@@ -94,7 +97,10 @@ var resetBindIpsCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "AllowIPs", "")
|
||||
if err := setSettingByKey(db, "AllowIPs", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
var resetDomainCmd = &cobra.Command{
|
||||
@@ -110,7 +116,10 @@ var resetDomainCmd = &cobra.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
return setSettingByKey(db, "BindDomain", "")
|
||||
if err := setSettingByKey(db, "BindDomain", ""); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -71,16 +71,16 @@ func checkSession(c *gin.Context) bool {
|
||||
return false
|
||||
}
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
setting, err := settingRepo.Get(repo.WithByKey("SessionTimeout"))
|
||||
sessionTimeout, err := settingRepo.GetValueByKey("SessionTimeout")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(setting.Value)
|
||||
httpsSetting, err := settingRepo.Get(repo.WithByKey("SSL"))
|
||||
lifeTime, _ := strconv.Atoi(sessionTimeout)
|
||||
ssl, err := settingRepo.GetValueByKey("SSL")
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_ = global.SESSION.Set(c, psession, httpsSetting.Value == constant.StatusEnable, lifeTime)
|
||||
_ = global.SESSION.Set(c, psession, ssl == constant.StatusEnable, lifeTime)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,12 @@ func BindDomain() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
status, err := settingRepo.Get(repo.WithByKey("BindDomain"))
|
||||
bindDomain, err := settingRepo.GetValueByKey("BindDomain")
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
if len(status.Value) == 0 {
|
||||
if len(bindDomain) == 0 {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func BindDomain() gin.HandlerFunc {
|
||||
domains = parts[0]
|
||||
}
|
||||
|
||||
if domains != status.Value {
|
||||
if domains != bindDomain {
|
||||
code := LoadErrCode()
|
||||
helper.ErrWithHtml(c, code, "err_domain")
|
||||
return
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
|
||||
func LoadErrCode() int {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
codeVal, err := settingRepo.Get(repo.WithByKey("NoAuthSetting"))
|
||||
codeVal, err := settingRepo.GetValueByKey("NoAuthSetting")
|
||||
if err != nil {
|
||||
return 500
|
||||
}
|
||||
|
||||
switch codeVal.Value {
|
||||
switch codeVal {
|
||||
case "400":
|
||||
return http.StatusBadRequest
|
||||
case "401":
|
||||
|
||||
@@ -24,17 +24,17 @@ func WhiteAllow() gin.HandlerFunc {
|
||||
}
|
||||
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
status, err := settingRepo.Get(repo.WithByKey("AllowIPs"))
|
||||
allowIPs, err := settingRepo.GetValueByKey("AllowIPs")
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if len(status.Value) == 0 {
|
||||
if len(allowIPs) == 0 {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
for _, ip := range strings.Split(status.Value, ",") {
|
||||
for _, ip := range strings.Split(allowIPs, ",") {
|
||||
if len(ip) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ import (
|
||||
func GlobalLoading() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
status, err := settingRepo.Get(repo.WithByKey("SystemStatus"))
|
||||
status, err := settingRepo.GetValueByKey("SystemStatus")
|
||||
if err != nil {
|
||||
helper.InternalServer(c, err)
|
||||
return
|
||||
}
|
||||
if status.Value != "Free" {
|
||||
helper.ErrorWithDetail(c, 407, status.Value, err)
|
||||
if status != "Free" {
|
||||
helper.ErrorWithDetail(c, 407, status, err)
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/1Panel-dev/1Panel/core/app/api/v2/helper"
|
||||
@@ -13,6 +14,11 @@ import (
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var (
|
||||
expiredLoc *time.Location
|
||||
expiredLocOnce sync.Once
|
||||
)
|
||||
|
||||
func PasswordExpired() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if strings.HasPrefix(c.Request.URL.Path, "/api/v2/core/auth") ||
|
||||
@@ -22,24 +28,23 @@ func PasswordExpired() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
setting, err := settingRepo.Get(repo.WithByKey("ExpirationDays"))
|
||||
expirationDays, err := settingRepo.GetValueByKey("ExpirationDays")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPasswordExpired", err)
|
||||
return
|
||||
}
|
||||
expiredDays, _ := strconv.Atoi(setting.Value)
|
||||
expiredDays, _ := strconv.Atoi(expirationDays)
|
||||
if expiredDays == 0 {
|
||||
c.Next()
|
||||
return
|
||||
}
|
||||
|
||||
extime, err := settingRepo.Get(repo.WithByKey("ExpirationTime"))
|
||||
expirationTime, err := settingRepo.GetValueByKey("ExpirationTime")
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, http.StatusInternalServerError, "ErrPasswordExpired", err)
|
||||
return
|
||||
}
|
||||
loc, _ := time.LoadLocation(common.LoadTimeZoneByCmd())
|
||||
expiredTime, err := time.ParseInLocation(constant.DateTimeLayout, extime.Value, loc)
|
||||
expiredTime, err := time.ParseInLocation(constant.DateTimeLayout, expirationTime, loadExpiredLocation())
|
||||
if err != nil {
|
||||
helper.ErrorWithDetail(c, 313, "ErrPasswordExpired", err)
|
||||
return
|
||||
@@ -51,3 +56,18 @@ func PasswordExpired() gin.HandlerFunc {
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func loadExpiredLocation() *time.Location {
|
||||
expiredLocOnce.Do(func() {
|
||||
loc, err := time.LoadLocation(common.LoadTimeZoneByCmd())
|
||||
if err != nil {
|
||||
expiredLoc = time.Local
|
||||
return
|
||||
}
|
||||
expiredLoc = loc
|
||||
})
|
||||
if expiredLoc == nil {
|
||||
return time.Local
|
||||
}
|
||||
return expiredLoc
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ func SetPasswordPublicKey() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
cookieKey, _ := c.Cookie("panel_public_key")
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
key, _ := settingRepo.Get(repo.WithByKey("PASSWORD_PUBLIC_KEY"))
|
||||
base64Key := base64.StdEncoding.EncodeToString([]byte(key.Value))
|
||||
key, _ := settingRepo.GetValueByKey("PASSWORD_PUBLIC_KEY")
|
||||
base64Key := base64.StdEncoding.EncodeToString([]byte(key))
|
||||
if base64Key == cookieKey {
|
||||
c.Next()
|
||||
return
|
||||
|
||||
@@ -31,18 +31,18 @@ func SessionAuth() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
settingRepo := repo.NewISettingRepo()
|
||||
setting, err := settingRepo.Get(repo.WithByKey("SessionTimeout"))
|
||||
sessionTimeout, err := settingRepo.GetValueByKey("SessionTimeout")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("create operation record failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
lifeTime, _ := strconv.Atoi(setting.Value)
|
||||
httpsSetting, err := settingRepo.Get(repo.WithByKey("SSL"))
|
||||
lifeTime, _ := strconv.Atoi(sessionTimeout)
|
||||
ssl, err := settingRepo.GetValueByKey("SSL")
|
||||
if err != nil {
|
||||
global.LOG.Errorf("create operation record failed, err: %v", err)
|
||||
return
|
||||
}
|
||||
_ = global.SESSION.Set(c, psession, httpsSetting.Value == constant.StatusEnable, lifeTime)
|
||||
_ = global.SESSION.Set(c, psession, ssl == constant.StatusEnable, lifeTime)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user