diff --git a/internal/rpc/rpc_client.go b/internal/rpc/rpc_client.go index 11bdffc6..11a58728 100644 --- a/internal/rpc/rpc_client.go +++ b/internal/rpc/rpc_client.go @@ -219,6 +219,14 @@ func (this *RPCClient) HTTPCachePolicyRPC() pb.HTTPCachePolicyServiceClient { return pb.NewHTTPCachePolicyServiceClient(this.pickConn()) } +func (this *RPCClient) HTTPCacheTaskRPC() pb.HTTPCacheTaskServiceClient { + return pb.NewHTTPCacheTaskServiceClient(this.pickConn()) +} + +func (this *RPCClient) HTTPCacheTaskKeyRPC() pb.HTTPCacheTaskKeyServiceClient { + return pb.NewHTTPCacheTaskKeyServiceClient(this.pickConn()) +} + func (this *RPCClient) HTTPFirewallPolicyRPC() pb.HTTPFirewallPolicyServiceClient { return pb.NewHTTPFirewallPolicyServiceClient(this.pickConn()) } diff --git a/internal/web/actions/default/servers/components/cache/batch/deleteTask.go b/internal/web/actions/default/servers/components/cache/batch/deleteTask.go new file mode 100644 index 00000000..e3079033 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/deleteTask.go @@ -0,0 +1,28 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type DeleteTaskAction struct { + actionutils.ParentAction +} + +func (this *DeleteTaskAction) RunPost(params struct { + TaskId int64 +}) { + defer this.CreateLogInfo("删除缓存任务 %d", params.TaskId) + + _, err := this.RPC().HTTPCacheTaskRPC().DeleteHTTPCacheTask(this.AdminContext(), &pb.DeleteHTTPCacheTaskRequest{ + HttpCacheTaskId: params.TaskId, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/fetch.go b/internal/web/actions/default/servers/components/cache/batch/fetch.go new file mode 100644 index 00000000..e48192c5 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/fetch.go @@ -0,0 +1,96 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "strings" +) + +type FetchAction struct { + actionutils.ParentAction +} + +func (this *FetchAction) Init() { + this.Nav("", "", "fetch") +} + +func (this *FetchAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + this.Show() +} + +func (this *FetchAction) RunPost(params struct { + Keys string + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("批量预热缓存Key") + + if len(params.Keys) == 0 { + this.Fail("请输入要预热的Key列表") + } + + // 检查Key + var realKeys = []string{} + for _, key := range strings.Split(params.Keys, "\n") { + key = strings.TrimSpace(key) + if len(key) == 0 { + continue + } + if lists.ContainsString(realKeys, key) { + continue + } + realKeys = append(realKeys, key) + } + + if len(realKeys) == 0 { + this.Fail("请输入要预热的Key列表") + } + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) + if err != nil { + this.ErrorPage(err) + return + } + + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) + } + } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } + + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/index.go b/internal/web/actions/default/servers/components/cache/batch/index.go new file mode 100644 index 00000000..66c93d09 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/index.go @@ -0,0 +1,97 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" + "strings" +) + +type IndexAction struct { + actionutils.ParentAction +} + +func (this *IndexAction) Init() { + this.Nav("", "", "purge") +} + +func (this *IndexAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + this.Show() +} + +func (this *IndexAction) RunPost(params struct { + KeyType string + Keys string + + Must *actions.Must + CSRF *actionutils.CSRF +}) { + defer this.CreateLogInfo("批量刷新缓存Key") + + if len(params.Keys) == 0 { + this.Fail("请输入要刷新的Key列表") + } + + // 检查Key + var realKeys = []string{} + for _, key := range strings.Split(params.Keys, "\n") { + key = strings.TrimSpace(key) + if len(key) == 0 { + continue + } + if lists.ContainsString(realKeys, key) { + continue + } + realKeys = append(realKeys, key) + } + + if len(realKeys) == 0 { + this.Fail("请输入要刷新的Key列表") + } + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) + if err != nil { + this.ErrorPage(err) + return + } + + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) + } + } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } + + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/init.go b/internal/web/actions/default/servers/components/cache/batch/init.go new file mode 100644 index 00000000..e4695be9 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/init.go @@ -0,0 +1,24 @@ +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/configloaders" + "github.com/TeaOSLab/EdgeAdmin/internal/web/helpers" + "github.com/iwind/TeaGo" +) + +func init() { + TeaGo.BeforeStart(func(server *TeaGo.Server) { + server. + Helper(helpers.NewUserMustAuth(configloaders.AdminModuleCodeServer)). + Data("teaMenu", "servers"). + Data("teaSubMenu", "cacheBatch"). + Prefix("/servers/components/cache/batch"). + GetPost("", new(IndexAction)). + GetPost("/fetch", new(FetchAction)). + Get("/tasks", new(TasksAction)). + Get("/task", new(TaskAction)). + Post("/deleteTask", new(DeleteTaskAction)). + Post("/resetTask", new(ResetTaskAction)). + EndAll() + }) +} diff --git a/internal/web/actions/default/servers/components/cache/batch/resetTask.go b/internal/web/actions/default/servers/components/cache/batch/resetTask.go new file mode 100644 index 00000000..c41b579e --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/resetTask.go @@ -0,0 +1,26 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +type ResetTaskAction struct { + actionutils.ParentAction +} + +func (this *ResetTaskAction) RunPost(params struct { + TaskId int64 +}) { + this.CreateLogInfo("重置缓存任务 %d 状态", params.TaskId) + + _, err := this.RPC().HTTPCacheTaskRPC().ResetHTTPCacheTask(this.AdminContext(), &pb.ResetHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId}) + if err != nil { + this.ErrorPage(err) + return + } + + this.Success() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/task.go b/internal/web/actions/default/servers/components/cache/batch/task.go new file mode 100644 index 00000000..abd8018c --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/task.go @@ -0,0 +1,104 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "encoding/json" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" + "sort" +) + +type TaskAction struct { + actionutils.ParentAction +} + +func (this *TaskAction) Init() { + this.Nav("", "", "task") +} + +func (this *TaskAction) RunGet(params struct { + TaskId int64 +}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + return + } + + taskResp, err := this.RPC().HTTPCacheTaskRPC().FindEnabledHTTPCacheTask(this.AdminContext(), &pb.FindEnabledHTTPCacheTaskRequest{HttpCacheTaskId: params.TaskId}) + if err != nil { + this.ErrorPage(err) + return + } + var task = taskResp.HttpCacheTask + if task == nil { + this.NotFound("HTTPCacheTask", params.TaskId) + return + } + + // 用户 + var userMap = maps.Map{"id": 0, "username": "", "fullname": ""} + if task.User != nil { + userMap = maps.Map{ + "id": task.User.Id, + "username": task.User.Username, + "fullname": task.User.Fullname, + } + } + + // keys + var keyMaps = []maps.Map{} + for _, key := range task.HttpCacheTaskKeys { + // 错误信息 + var errorMaps = []maps.Map{} + + if len(key.ErrorsJSON) > 0 { + var m = map[int64]string{} + err = json.Unmarshal(key.ErrorsJSON, &m) + if err != nil { + this.ErrorPage(err) + return + } + for nodeId, errString := range m { + errorMaps = append(errorMaps, maps.Map{ + "nodeId": nodeId, + "error": errString, + }) + } + } + + // 错误信息排序 + if len(errorMaps) > 0 { + sort.Slice(errorMaps, func(i, j int) bool { + var m1 = errorMaps[i] + var m2 = errorMaps[j] + + return m1.GetInt64("nodeId") < m2.GetInt64("nodeId") + }) + } + + keyMaps = append(keyMaps, maps.Map{ + "key": key.Key, + "isDone": key.IsDone, + "errors": errorMaps, + }) + } + + this.Data["task"] = maps.Map{ + "id": task.Id, + "type": task.Type, + "keyType": task.KeyType, + "createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt), + "doneTime": timeutil.FormatTime("Y-m-d H:i:s", task.DoneAt), + "isDone": task.IsDone, + "isOk": task.IsOk, + "keys": keyMaps, + "user": userMap, + } + + this.Show() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/tasks.go b/internal/web/actions/default/servers/components/cache/batch/tasks.go new file mode 100644 index 00000000..b5b97255 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/tasks.go @@ -0,0 +1,72 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/maps" + timeutil "github.com/iwind/TeaGo/utils/time" +) + +type TasksAction struct { + actionutils.ParentAction +} + +func (this *TasksAction) Init() { + this.Nav("", "", "task") +} + +func (this *TasksAction) RunGet(params struct{}) { + // 初始化菜单数据 + err := InitMenu(this.Parent()) + if err != nil { + this.ErrorPage(err) + } + + // 任务数量 + countResp, err := this.RPC().HTTPCacheTaskRPC().CountHTTPCacheTasks(this.AdminContext(), &pb.CountHTTPCacheTasksRequest{}) + if err != nil { + this.ErrorPage(err) + return + } + var count = countResp.Count + var page = this.NewPage(count) + this.Data["page"] = page.AsHTML() + + // 任务列表 + var taskMaps = []maps.Map{} + tasksResp, err := this.RPC().HTTPCacheTaskRPC().ListHTTPCacheTasks(this.AdminContext(), &pb.ListHTTPCacheTasksRequest{ + Offset: page.Offset, + Size: page.Size, + }) + if err != nil { + this.ErrorPage(err) + return + } + for _, task := range tasksResp.HttpCacheTasks { + var userMap = maps.Map{"id": 0, "username": "", "fullname": ""} + if task.User != nil { + userMap = maps.Map{ + "id": task.User.Id, + "username": task.User.Username, + "fullname": task.User.Fullname, + } + } + + taskMaps = append(taskMaps, maps.Map{ + "id": task.Id, + "type": task.Type, + "keyType": task.KeyType, + "isDone": task.IsDone, + "isOk": task.IsOk, + "createdTime": timeutil.FormatTime("Y-m-d H:i:s", task.CreatedAt), + "description": task.Description, + "user": userMap, + }) + } + + this.Data["tasks"] = taskMaps + + this.Show() +} diff --git a/internal/web/actions/default/servers/components/cache/batch/utils.go b/internal/web/actions/default/servers/components/cache/batch/utils.go new file mode 100644 index 00000000..ff1e3d49 --- /dev/null +++ b/internal/web/actions/default/servers/components/cache/batch/utils.go @@ -0,0 +1,24 @@ +// Copyright 2022 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn . + +package cache + +import ( + "github.com/TeaOSLab/EdgeAdmin/internal/rpc" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" +) + +func InitMenu(parent *actionutils.ParentAction) error { + rpcClient, err := rpc.SharedRPC() + if err != nil { + return err + } + + countTasksResp, err := rpcClient.HTTPCacheTaskRPC().CountDoingHTTPCacheTasks(parent.AdminContext(), &pb.CountDoingHTTPCacheTasksRequest{}) + if err != nil { + return err + } + + parent.Data["countDoingTasks"] = countTasksResp.Count + return nil +} diff --git a/internal/web/actions/default/servers/components/cache/cacheutils/utils.go b/internal/web/actions/default/servers/components/cache/cacheutils/utils.go index d3fb9ab8..bef513b6 100644 --- a/internal/web/actions/default/servers/components/cache/cacheutils/utils.go +++ b/internal/web/actions/default/servers/components/cache/cacheutils/utils.go @@ -8,7 +8,7 @@ import ( "github.com/TeaOSLab/EdgeCommon/pkg/serverconfigs" ) -// 查找缓存策略名称并忽略错误 +// FindCachePolicyNameWithoutError 查找缓存策略名称并忽略错误 func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePolicyId int64) string { policy, err := FindCachePolicy(parent, cachePolicyId) if err != nil { @@ -20,7 +20,7 @@ func FindCachePolicyNameWithoutError(parent *actionutils.ParentAction, cachePoli return policy.Name } -// 查找缓存策略配置 +// FindCachePolicy 查找缓存策略配置 func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*serverconfigs.HTTPCachePolicy, error) { resp, err := parent.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(parent.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId}) if err != nil { @@ -36,3 +36,20 @@ func FindCachePolicy(parent *actionutils.ParentAction, cachePolicyId int64) (*se } return config, nil } + +// KeyFailReason Key相关失败原因 +func KeyFailReason(reasonCode string) string { + switch reasonCode { + case "requireKey": + return "空的Key" + case "requireDomain": + return "找不到Key对应的域名" + case "requireServer": + return "找不到Key对应的网站服务" + case "requireUser": + return "该域名不属于当前用户" + case "requireClusterId": + return "该网站没有部署到集群" + } + return "未知错误" +} diff --git a/internal/web/actions/default/servers/components/cache/preheat.go b/internal/web/actions/default/servers/components/cache/fetch.go similarity index 66% rename from internal/web/actions/default/servers/components/cache/preheat.go rename to internal/web/actions/default/servers/components/cache/fetch.go index 557a2d98..f87529cd 100644 --- a/internal/web/actions/default/servers/components/cache/preheat.go +++ b/internal/web/actions/default/servers/components/cache/fetch.go @@ -3,8 +3,7 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" @@ -15,15 +14,15 @@ import ( "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "", "fetch") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { CachePolicyId int64 }) { // 默认的集群ID @@ -50,7 +49,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { CachePolicyId int64 ClusterId int64 Keys string @@ -92,27 +91,38 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + // 校验Key + // 这里暂时不校验服务ID + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/components/cache/init.go b/internal/web/actions/default/servers/components/cache/init.go index 79b33b9a..1f85412e 100644 --- a/internal/web/actions/default/servers/components/cache/init.go +++ b/internal/web/actions/default/servers/components/cache/init.go @@ -19,7 +19,7 @@ func init() { Get("/policy", new(PolicyAction)). GetPost("/update", new(UpdateAction)). GetPost("/clean", new(CleanAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). GetPost("/purge", new(PurgeAction)). GetPost("/stat", new(StatAction)). GetPost("/test", new(TestAction)). diff --git a/internal/web/actions/default/servers/components/cache/purge.go b/internal/web/actions/default/servers/components/cache/purge.go index 191cdbe0..f9bdabf8 100644 --- a/internal/web/actions/default/servers/components/cache/purge.go +++ b/internal/web/actions/default/servers/components/cache/purge.go @@ -3,8 +3,7 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" @@ -53,7 +52,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { CachePolicyId int64 ClusterId int64 - Type string + KeyType string Keys string Must *actions.Must }) { @@ -91,33 +90,37 @@ func (this *PurgeAction) RunPost(params struct { } realKeys = append(realKeys, key) } - - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), params.ClusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/cache/preheat.go b/internal/web/actions/default/servers/groups/group/settings/cache/fetch.go similarity index 70% rename from internal/web/actions/default/servers/server/settings/cache/preheat.go rename to internal/web/actions/default/servers/groups/group/settings/cache/fetch.go index b9099d73..17b0b9f3 100644 --- a/internal/web/actions/default/servers/server/settings/cache/preheat.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/fetch.go @@ -5,25 +5,26 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "setting", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "setting", "fetch") this.SecondMenu("cache") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { ServerId int64 }) { webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) @@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { ServerId int64 WebId int64 Keys string @@ -117,27 +118,38 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/init.go b/internal/web/actions/default/servers/groups/group/settings/cache/init.go index 92a1347c..4b26eea6 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/init.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/init.go @@ -15,7 +15,7 @@ func init() { Prefix("/servers/groups/group/settings/cache"). GetPost("", new(IndexAction)). GetPost("/purge", new(PurgeAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). EndAll() }) } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/purge.go b/internal/web/actions/default/servers/groups/group/settings/cache/purge.go index e18fe292..59faf87c 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/purge.go +++ b/internal/web/actions/default/servers/groups/group/settings/cache/purge.go @@ -5,12 +5,13 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) @@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { ServerId int64 WebId int64 - Type string + KeyType string Keys string Must *actions.Must @@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/groups/group/settings/cache/preheat.go b/internal/web/actions/default/servers/server/settings/cache/fetch.go similarity index 70% rename from internal/web/actions/default/servers/groups/group/settings/cache/preheat.go rename to internal/web/actions/default/servers/server/settings/cache/fetch.go index b9099d73..7f6054ce 100644 --- a/internal/web/actions/default/servers/groups/group/settings/cache/preheat.go +++ b/internal/web/actions/default/servers/server/settings/cache/fetch.go @@ -5,25 +5,26 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) -type PreheatAction struct { +type FetchAction struct { actionutils.ParentAction } -func (this *PreheatAction) Init() { - this.Nav("", "setting", "preheat") +func (this *FetchAction) Init() { + this.Nav("", "setting", "fetch") this.SecondMenu("cache") } -func (this *PreheatAction) RunGet(params struct { +func (this *FetchAction) RunGet(params struct { ServerId int64 }) { webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) @@ -38,7 +39,7 @@ func (this *PreheatAction) RunGet(params struct { this.Show() } -func (this *PreheatAction) RunPost(params struct { +func (this *FetchAction) RunPost(params struct { ServerId int64 WebId int64 Keys string @@ -117,27 +118,37 @@ func (this *PreheatAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PreheatCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "fetch", + KeyType: "key", + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/actions/default/servers/server/settings/cache/init.go b/internal/web/actions/default/servers/server/settings/cache/init.go index 9a814079..68677088 100644 --- a/internal/web/actions/default/servers/server/settings/cache/init.go +++ b/internal/web/actions/default/servers/server/settings/cache/init.go @@ -16,7 +16,7 @@ func init() { GetPost("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). GetPost("/purge", new(PurgeAction)). - GetPost("/preheat", new(PreheatAction)). + GetPost("/fetch", new(FetchAction)). Post("/updateRefs", new(UpdateRefsAction)). EndAll() }) diff --git a/internal/web/actions/default/servers/server/settings/cache/purge.go b/internal/web/actions/default/servers/server/settings/cache/purge.go index e18fe292..59faf87c 100644 --- a/internal/web/actions/default/servers/server/settings/cache/purge.go +++ b/internal/web/actions/default/servers/server/settings/cache/purge.go @@ -5,12 +5,13 @@ package cache import ( "github.com/TeaOSLab/EdgeAdmin/internal/oplogs" "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils" - "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/nodes/nodeutils" - "github.com/TeaOSLab/EdgeCommon/pkg/messageconfigs" + "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/servers/components/cache/cacheutils" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/dao" "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" "github.com/iwind/TeaGo/actions" "github.com/iwind/TeaGo/lists" + "github.com/iwind/TeaGo/maps" + "github.com/iwind/TeaGo/types" "strings" ) @@ -41,7 +42,7 @@ func (this *PurgeAction) RunGet(params struct { func (this *PurgeAction) RunPost(params struct { ServerId int64 WebId int64 - Type string + KeyType string Keys string Must *actions.Must @@ -118,32 +119,37 @@ func (this *PurgeAction) RunPost(params struct { realKeys = append(realKeys, key) } - // 发送命令 - msg := &messageconfigs.PurgeCacheMessage{ - CachePolicyJSON: cachePolicyJSON, - Keys: realKeys, - } - if params.Type == "prefix" { - msg.Type = messageconfigs.PurgeCacheMessageTypeDir - } else { - msg.Type = messageconfigs.PurgeCacheMessageTypeFile - } - results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePurgeCache, msg, 10) + // 校验Key + validateResp, err := this.RPC().HTTPCacheTaskKeyRPC().ValidateHTTPCacheTaskKeys(this.AdminContext(), &pb.ValidateHTTPCacheTaskKeysRequest{Keys: realKeys}) if err != nil { this.ErrorPage(err) return } - isAllOk := true - for _, result := range results { - if !result.IsOK { - isAllOk = false - break + var failKeyMaps = []maps.Map{} + if len(validateResp.FailKeys) > 0 { + for _, key := range validateResp.FailKeys { + failKeyMaps = append(failKeyMaps, maps.Map{ + "key": key.Key, + "reason": cacheutils.KeyFailReason(key.ReasonCode), + }) } } + this.Data["failKeys"] = failKeyMaps + if len(failKeyMaps) > 0 { + this.Fail("有" + types.String(len(failKeyMaps)) + "个Key无法完成操作,请删除后重试") + } - this.Data["isAllOk"] = isAllOk - this.Data["results"] = results + // 提交任务 + _, err = this.RPC().HTTPCacheTaskRPC().CreateHTTPCacheTask(this.AdminContext(), &pb.CreateHTTPCacheTaskRequest{ + Type: "purge", + KeyType: params.KeyType, + Keys: realKeys, + }) + if err != nil { + this.ErrorPage(err) + return + } this.Success() } diff --git a/internal/web/helpers/menu.go b/internal/web/helpers/menu.go index 283a54a7..275fab03 100644 --- a/internal/web/helpers/menu.go +++ b/internal/web/helpers/menu.go @@ -34,11 +34,26 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread "url": "/servers/certs", "code": "cert", }, + { + "name": "服务分组", + "url": "/servers/groups", + "code": "group", + }, + { + "name": "-", + "url": "", + "code": "", + }, { "name": "缓存策略", "url": "/servers/components/cache", "code": "cache", }, + { + "name": "刷新预热", + "url": "/servers/components/cache/batch", + "code": "cacheBatch", + }, { "name": "-", "url": "", @@ -60,11 +75,6 @@ func FindAllMenuMaps(nodeLogsType string, countUnreadNodeLogs int64, countUnread "url": "", "code": "", }, - { - "name": "服务分组", - "url": "/servers/groups", - "code": "group", - }, { "name": "统计指标", "url": "/servers/metrics", diff --git a/web/public/js/components.js b/web/public/js/components.js index d4a03be6..d1fce1ba 100644 --- a/web/public/js/components.js +++ b/web/public/js/components.js @@ -333,7 +333,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
| 是否启用 | +启用 | 
 					 
 						
@@ -402,7 +402,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		 是否启用 | 
+				启用 | 
 				
 					 | 
@@ -1356,7 +1356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 				PURGE Key * | 
 				
 					
-					 | 
 			[随机生成]。需要在PURGE方法调用时加入 [随机生成]。需要在PURGE方法调用时加入 是否启用配置 | 
+				启用配置 | 
 				
 					 | 
 						
@@ -2356,7 +2356,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 					 是否开启 | 
+							开启 | 
 							
 								 | 
 									
@@ -2407,7 +2407,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		 是否启用 | 
+				启用 | 
 				
 					 | 
 						
@@ -2516,7 +2516,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		 是否启用 | 
+				启用 | 
 				
 					 | 
 						
@@ -2558,7 +2558,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		 是否启用 | 
+				启用 | 
 				 | 
@@ -2872,7 +2872,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		启用后,将会在响应的Header中添加 是否启用反向代理 | 
+				启用反向代理 | 
 				
 					 | 
 						
@@ -3377,7 +3377,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 		 是否启用配置 | 
+				启用配置 | 
 				
 					 | 
 						
@@ -3868,7 +3868,7 @@ Vue.component("traffic-map-box",{props:["v-stats","v-is-attack"],mounted:functio
 	
 	 
  |