optimize cache factory

This commit is contained in:
mc0814 2023-08-16 18:44:44 +08:00
parent f086ba5b36
commit 7bc6a27217
12 changed files with 84 additions and 105 deletions

View File

@ -16,7 +16,6 @@ import (
"github.com/zhenorzz/goploy/cmd/server/api/middleware"
"github.com/zhenorzz/goploy/config"
"github.com/zhenorzz/goploy/internal/cache"
"github.com/zhenorzz/goploy/internal/cache/factory"
"github.com/zhenorzz/goploy/internal/media"
"github.com/zhenorzz/goploy/internal/model"
"github.com/zhenorzz/goploy/internal/server"
@ -68,10 +67,10 @@ func (User) Login(gp *server.Goploy) server.Response {
return response.JSON{Code: response.IllegalParam, Message: err.Error()}
}
userCache := factory.GetUserCache()
userCache := cache.GetUserCache()
if config.Toml.Captcha.Enabled && userCache.IsShowCaptcha(reqData.Account) {
captchaCache := factory.GetCaptchaCache()
captchaCache := cache.GetCaptchaCache()
if !captchaCache.IsChecked(reqData.CaptchaKey) {
return response.JSON{Code: response.Error, Message: "Captcha error, please check captcha again"}
}
@ -131,10 +130,10 @@ func (User) Login(gp *server.Goploy) server.Response {
}
} else {
if err := userData.Validate(reqData.Password); err != nil {
errorTimes := userCache.IncErrorTimes(reqData.Account)
errorTimes := userCache.IncErrorTimes(reqData.Account, cache.UserCacheExpireTime, cache.UserCacheShowCaptchaTime)
// error times over 5 times, then lock the account 15 minutes
if errorTimes >= cache.UserCacheMaxErrorTimes {
userCache.LockAccount(reqData.Account)
userCache.LockAccount(reqData.Account, cache.UserCacheLockTime)
}
return response.JSON{Code: response.Deny, Message: err.Error()}
}
@ -631,7 +630,7 @@ func (User) GetCaptcha(gp *server.Goploy) server.Response {
return response.JSON{Code: response.AccountDisabled, Message: "generate captcha fail, error msg:" + err.Error()}
}
captchaCache := factory.GetCaptchaCache()
captchaCache := cache.GetCaptchaCache()
captchaCache.Set(key, dots, 2*time.Minute)
return response.JSON{
@ -659,7 +658,7 @@ func (User) CheckCaptcha(gp *server.Goploy) server.Response {
return response.JSON{Code: response.Error, Message: err.Error()}
}
captchaCache := factory.GetCaptchaCache()
captchaCache := cache.GetCaptchaCache()
dotsCache, ok := captchaCache.Get(reqData.Key)
if !ok {
return response.JSON{Code: response.Error, Message: "Illegal key, please refresh the captcha again"}

View File

@ -19,7 +19,6 @@ func Init() {
startProjectTask()
startServerMonitorTask()
startDeployTask()
startMemoryCacheTask()
}
func Shutdown(ctx context.Context) error {

View File

@ -50,4 +50,7 @@ appKey = ''
appSecret = ''
[captcha]
enabled = false
enabled = false
[cache]
type = 'memory'

View File

@ -8,7 +8,3 @@ type Captcha interface {
Delete(key string)
IsChecked(key string) bool
}
type CaptchaData struct {
Dots interface{}
}

View File

@ -6,7 +6,3 @@ type DingtalkAccessToken interface {
Get(key string) (string, bool)
Set(key string, value string, ttl time.Duration)
}
type AccessTokenData struct {
AccessToken string
}

37
internal/cache/factory.go vendored Normal file
View File

@ -0,0 +1,37 @@
package cache
import (
"github.com/zhenorzz/goploy/config"
"github.com/zhenorzz/goploy/internal/cache/memory"
)
const MemoryCache = "memory"
var cacheType = config.Toml.Cache.Type
func GetUserCache() User {
switch cacheType {
case MemoryCache:
return memory.GetUserCache()
default:
return memory.GetUserCache()
}
}
func GetCaptchaCache() Captcha {
switch cacheType {
case MemoryCache:
return memory.GetCaptchaCache()
default:
return memory.GetCaptchaCache()
}
}
func GetDingTalkAccessTokenCache() DingtalkAccessToken {
switch cacheType {
case MemoryCache:
return memory.GetDingTalkAccessTokenCache()
default:
return memory.GetDingTalkAccessTokenCache()
}
}

View File

@ -1,34 +0,0 @@
package factory
import (
"github.com/zhenorzz/goploy/config"
"github.com/zhenorzz/goploy/internal/cache"
"github.com/zhenorzz/goploy/internal/cache/memory"
)
func GetUserCache() cache.User {
cacheType := config.Toml.Cache.Type
if cacheType == "memory" {
return memory.GetUserCache()
} else {
return memory.GetUserCache()
}
}
func GetCaptchaCache() cache.Captcha {
cacheType := config.Toml.Cache.Type
if cacheType == "memory" {
return memory.GetCaptchaCache()
} else {
return memory.GetCaptchaCache()
}
}
func GetDingTalkAccessTokenCache() cache.DingtalkAccessToken {
cacheType := config.Toml.Cache.Type
if cacheType == "memory" {
return memory.GetDingTalkAccessTokenCache()
} else {
return memory.GetDingTalkAccessTokenCache()
}
}

View File

@ -1,7 +1,6 @@
package memory
import (
"github.com/zhenorzz/goploy/internal/cache"
"sync"
"time"
)
@ -12,7 +11,7 @@ type CaptchaCache struct {
}
type captcha struct {
cache.CaptchaData
dots interface{}
expireIn time.Time
}
@ -30,7 +29,7 @@ func (c *CaptchaCache) Get(key string) (interface{}, bool) {
}
if !v.expireIn.IsZero() && v.expireIn.After(time.Now()) {
return v.Dots, true
return v.dots, true
}
return nil, false
@ -47,9 +46,7 @@ func (c *CaptchaCache) Set(key string, value interface{}, ttl time.Duration) {
}
c.data[key] = captcha{
CaptchaData: cache.CaptchaData{
Dots: value,
},
dots: value,
expireIn: expireIn,
}

View File

@ -1,7 +1,6 @@
package memory
import (
"github.com/zhenorzz/goploy/internal/cache"
"sync"
"time"
)
@ -12,8 +11,8 @@ type AccessTokenCache struct {
}
type accessToken struct {
cache.AccessTokenData
expireIn time.Time
accessToken string
expireIn time.Time
}
var accessTokenCache = &AccessTokenCache{
@ -30,7 +29,7 @@ func (ac *AccessTokenCache) Get(key string) (string, bool) {
}
if !v.expireIn.IsZero() && v.expireIn.After(time.Now()) {
return v.AccessToken, true
return v.accessToken, true
}
return "", false
@ -47,10 +46,8 @@ func (ac *AccessTokenCache) Set(key string, value string, ttl time.Duration) {
}
ac.data[key] = accessToken{
AccessTokenData: cache.AccessTokenData{
AccessToken: value,
},
expireIn: expireIn,
accessToken: value,
expireIn: expireIn,
}
time.AfterFunc(ttl, func() {

View File

@ -1,18 +1,23 @@
package memory
import (
"github.com/zhenorzz/goploy/internal/cache"
"sync"
"time"
)
const (
UserCacheKey = "login_error_times_"
UserCacheLockKey = "login_lock_"
UserCacheShowCaptchaKey = "login_show_captcha_"
)
type UserCache struct {
data map[string]user
sync.RWMutex
}
type user struct {
cache.UserData
times int
expireIn time.Time
}
@ -20,7 +25,7 @@ var userCache = &UserCache{
data: make(map[string]user),
}
func (uc *UserCache) IncErrorTimes(account string) int {
func (uc *UserCache) IncErrorTimes(account string, expireTime time.Duration, showCaptchaTime time.Duration) int {
uc.Lock()
defer uc.Unlock()
@ -29,52 +34,44 @@ func (uc *UserCache) IncErrorTimes(account string) int {
times := 0
v, ok := uc.data[cacheKey]
if ok && !v.expireIn.IsZero() && v.expireIn.After(time.Now()) {
times = v.Times
times = v.times
}
times += 1
uc.data[cacheKey] = user{
UserData: cache.UserData{
Times: times,
},
expireIn: time.Now().Add(cache.UserCacheExpireTime),
times: times,
expireIn: time.Now().Add(expireTime),
}
time.AfterFunc(expireTime, func() {
delete(uc.data, cacheKey)
})
// show captcha
showCaptchaKey := getShowCaptchaKey(account)
uc.data[showCaptchaKey] = user{
UserData: cache.UserData{
Times: 1,
},
expireIn: time.Now().Add(cache.UserCacheShowCaptchaTime),
times: 1,
expireIn: time.Now().Add(showCaptchaTime),
}
time.AfterFunc(cache.UserCacheShowCaptchaTime, func() {
time.AfterFunc(showCaptchaTime, func() {
delete(uc.data, showCaptchaKey)
})
time.AfterFunc(cache.UserCacheExpireTime, func() {
delete(uc.data, cacheKey)
})
return times
}
func (uc *UserCache) LockAccount(account string) {
func (uc *UserCache) LockAccount(account string, lockTime time.Duration) {
uc.Lock()
defer uc.Unlock()
lockKey := getLockKey(account)
uc.data[lockKey] = user{
UserData: cache.UserData{
Times: 1,
},
expireIn: time.Now().Add(cache.UserCacheLockTime),
times: 1,
expireIn: time.Now().Add(lockTime),
}
time.AfterFunc(cache.UserCacheLockTime, func() {
time.AfterFunc(lockTime, func() {
delete(uc.data, lockKey)
})
@ -93,7 +90,7 @@ func (uc *UserCache) IsLock(account string) bool {
lockKey := getLockKey(account)
v, ok := uc.data[lockKey]
return ok && !v.expireIn.IsZero() && v.expireIn.After(time.Now()) && v.Times > 0
return ok && !v.expireIn.IsZero() && v.expireIn.After(time.Now()) && v.times > 0
}
func (uc *UserCache) IsShowCaptcha(account string) bool {
@ -103,7 +100,7 @@ func (uc *UserCache) IsShowCaptcha(account string) bool {
showCaptchaKey := getShowCaptchaKey(account)
v, ok := uc.data[showCaptchaKey]
return ok && !v.expireIn.IsZero() && v.expireIn.After(time.Now()) && v.Times > 0
return ok && !v.expireIn.IsZero() && v.expireIn.After(time.Now()) && v.times > 0
}
func (uc *UserCache) DeleteShowCaptcha(account string) {
@ -114,15 +111,15 @@ func (uc *UserCache) DeleteShowCaptcha(account string) {
}
func getCacheKey(account string) string {
return cache.UserCacheKey + account
return UserCacheKey + account
}
func getLockKey(account string) string {
return cache.UserCacheLockKey + account
return UserCacheLockKey + account
}
func getShowCaptchaKey(account string) string {
return cache.UserCacheShowCaptchaKey + account
return UserCacheShowCaptchaKey + account
}
func GetUserCache() *UserCache {

View File

@ -3,23 +3,16 @@ package cache
import "time"
type User interface {
IncErrorTimes(account string) int
LockAccount(account string)
IncErrorTimes(account string, expireTime time.Duration, showCaptchaTime time.Duration) int
LockAccount(account string, lockTime time.Duration)
IsLock(account string) bool
IsShowCaptcha(account string) bool
DeleteShowCaptcha(account string)
}
const (
UserCacheKey = "login_error_times_"
UserCacheLockKey = "login_lock_"
UserCacheShowCaptchaKey = "login_show_captcha_"
UserCacheMaxErrorTimes = 5
UserCacheExpireTime = 5 * time.Minute
UserCacheLockTime = 15 * time.Minute
UserCacheShowCaptchaTime = 15 * time.Minute
)
type UserData struct {
Times int
}

View File

@ -7,7 +7,6 @@ import (
"fmt"
"github.com/zhenorzz/goploy/config"
"github.com/zhenorzz/goploy/internal/cache"
"github.com/zhenorzz/goploy/internal/cache/factory"
"github.com/zhenorzz/goploy/internal/media/dingtalk/api"
"github.com/zhenorzz/goploy/internal/media/dingtalk/api/access_token"
"github.com/zhenorzz/goploy/internal/media/dingtalk/api/contact"
@ -35,7 +34,7 @@ func (d *Dingtalk) Login(authCode string, _ string) (string, error) {
d.Key = config.Toml.Dingtalk.AppKey
d.Secret = config.Toml.Dingtalk.AppSecret
d.Client = &http.Client{}
d.Cache = factory.GetDingTalkAccessTokenCache()
d.Cache = cache.GetDingTalkAccessTokenCache()
userAccessTokenInfo, err := d.GetUserAccessToken(authCode)
if err != nil {