Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+161
View File
@@ -0,0 +1,161 @@
package sysconfdata
import (
"strconv"
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/common/localcache"
"91porn-server/models"
"91porn-server/models/v/sysconfmod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// GetIntsFromSharedCache reads integer settings from the shared cache without
// the process-local one-minute layer, so management changes take effect at once.
func GetIntsFromSharedCache(defaults map[sysconfmod.VCode]int) (map[sysconfmod.VCode]int, error) {
configure, err := getAllFromSharedCache()
if err != nil {
return nil, err
}
values := make(map[sysconfmod.VCode]int, len(defaults))
for code, fallback := range defaults {
values[code] = fallback
if raw, ok := configure[string(code)]; ok {
if parsed, parseErr := strconv.Atoi(raw); parseErr == nil {
values[code] = parsed
}
}
}
return values, nil
}
const (
tmpLocalCacheKey = "AllSysConfTmpKey"
// DefaultTotalWatchCount preserves the legacy free-trial behavior when the
// shared configuration is absent or temporarily unavailable.
DefaultTotalWatchCount uint64 = 3
)
// GetAllFromCache 获取全部配置项
func GetAllFromCache() (res sysconfmod.ConfMap, err error) {
// 频繁访问 从本地进程内缓存中获取,对象不存在则从redis中获取
r, _ := localcache.C.Get(tmpLocalCacheKey)
if r != nil {
return r.(sysconfmod.ConfMap), nil
}
defer func() {
localcache.C.Set(tmpLocalCacheKey, res, 1*time.Minute)
}()
return getAllFromSharedCache()
}
// GetTotalWatchCount returns the configured non-VIP free-trial count from the
// existing bounded configuration cache and falls back to the legacy default.
func GetTotalWatchCount() uint64 {
configure, err := GetAllFromCache()
if err != nil {
return DefaultTotalWatchCount
}
return totalWatchCount(configure)
}
func totalWatchCount(configure sysconfmod.ConfMap) uint64 {
raw, ok := configure[string(sysconfmod.VCodeTotalWatchCount)]
if !ok {
return DefaultTotalWatchCount
}
value, err := strconv.ParseUint(raw, 10, 64)
if err != nil {
return DefaultTotalWatchCount
}
return value
}
func getAllFromSharedCache() (res sysconfmod.ConfMap, err error) {
_, err = cachev2.Classes().CacheTime(5 * time.Minute).AutoListKey(models.SysConf).ResBind(&res).Cache(sysconfmod.GetAllConfig)
return
}
// GetBoolFromSharedCache 绕过进程内缓存读取布尔配置,后台修改并清理 Redis 后可立即生效。
func GetBoolFromSharedCache(code sysconfmod.VCode) (bool, error) {
values, err := GetBoolsFromSharedCache(code)
if err != nil {
return false, err
}
return values[code], nil
}
// GetBoolsFromSharedCache reads several switches from one shared-cache
// snapshot. This keeps request paths that need related switches from fetching
// and decoding the same configuration map repeatedly.
func GetBoolsFromSharedCache(codes ...sysconfmod.VCode) (map[sysconfmod.VCode]bool, error) {
configure, err := getAllFromSharedCache()
if err != nil {
return nil, err
}
values := make(map[sysconfmod.VCode]bool, len(codes))
for _, code := range codes {
if _, exists := configure[string(code)]; !exists {
continue
}
values[code] = configure.GetBool(code)
}
return values, nil
}
func clearAllCache() error {
localcache.C.Delete(tmpLocalCacheKey)
_, err := cachev2.Classes().AutoListKey(models.SysConf).DeleteCurrent()
return err
}
// GetByGpCodeFromCache 获取分组配置数据
func GetByGpCodeFromCache(code sysconfmod.GPCode) (res sysconfmod.ConfMap, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.SysConf).ResBind(&res).Cache(sysconfmod.GetByGpCode, code)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data sysconfmod.SysConf) (primitive.ObjectID, error) {
newID, err := sysconfmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
if err = clearAllCache(); err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := sysconfmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
if err = clearAllCache(); err != nil {
return affect, err
}
return affect, nil
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = sysconfmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
return clearAllCache()
}
+27
View File
@@ -0,0 +1,27 @@
package sysconfdata
import (
"testing"
"91porn-server/models/v/sysconfmod"
)
func TestTotalWatchCount(t *testing.T) {
tests := []struct {
name string
config sysconfmod.ConfMap
want uint64
}{
{name: "configured", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "5"}, want: 5},
{name: "zero is allowed", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "0"}, want: 0},
{name: "missing", config: sysconfmod.ConfMap{}, want: DefaultTotalWatchCount},
{name: "invalid", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "invalid"}, want: DefaultTotalWatchCount},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := totalWatchCount(tt.config); got != tt.want {
t.Fatalf("totalWatchCount() = %d, want %d", got, tt.want)
}
})
}
}