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 058d7aa0..f7f0bfab 100644 --- a/internal/web/actions/default/servers/server/settings/cache/init.go +++ b/internal/web/actions/default/servers/server/settings/cache/init.go @@ -15,6 +15,8 @@ func init() { Prefix("/servers/server/settings/cache"). GetPost("", new(IndexAction)). GetPost("/createPopup", new(CreatePopupAction)). + GetPost("/purge", new(PurgeAction)). + GetPost("/preheat", new(PreheatAction)). EndAll() }) } diff --git a/internal/web/actions/default/servers/server/settings/cache/preheat.go b/internal/web/actions/default/servers/server/settings/cache/preheat.go new file mode 100644 index 00000000..b9099d73 --- /dev/null +++ b/internal/web/actions/default/servers/server/settings/cache/preheat.go @@ -0,0 +1,143 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +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/EdgeCommon/pkg/rpc/dao" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "strings" +) + +type PreheatAction struct { + actionutils.ParentAction +} + +func (this *PreheatAction) Init() { + this.Nav("", "setting", "preheat") + this.SecondMenu("cache") +} + +func (this *PreheatAction) RunGet(params struct { + ServerId int64 +}) { + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["webId"] = webConfig.Id + this.Data["webConfig"] = webConfig + + this.Show() +} + +func (this *PreheatAction) RunPost(params struct { + ServerId int64 + WebId int64 + Keys string + + Must *actions.Must +}) { + + // 创建日志 + defer this.CreateLog(oplogs.LevelInfo, "预热服务 %d 缓存", params.ServerId) + + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId) + if err != nil { + this.ErrorPage(err) + return + } + if webConfig == nil { + this.NotFound("httpWeb", params.WebId) + return + } + var cache = webConfig.Cache + if cache == nil || !cache.IsOn { + this.Fail("当前没有开启缓存") + } + + serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId}) + if err != nil { + this.ErrorPage(err) + return + } + var server = serverResp.Server + if server == nil || server.NodeCluster == nil { + this.NotFound("server", params.ServerId) + return + } + + var clusterId = server.NodeCluster.Id + + clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var cluster = clusterResp.NodeCluster + if cluster == nil { + this.NotFound("nodeCluster", clusterId) + return + } + var cachePolicyId = cluster.HttpCachePolicyId + if cachePolicyId == 0 { + this.Fail("当前集群没有设置缓存策略") + } + + cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON + if len(cachePolicyJSON) == 0 { + this.Fail("找不到要操作的缓存策略") + } + + if len(params.Keys) == 0 { + this.Fail("请输入要预热的Key列表") + } + + 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) + } + + // 发送命令 + msg := &messageconfigs.PreheatCacheMessage{ + CachePolicyJSON: cachePolicyJSON, + Keys: realKeys, + } + results, err := nodeutils.SendMessageToCluster(this.AdminContext(), clusterId, messageconfigs.MessageCodePreheatCache, msg, 300) + if err != nil { + this.ErrorPage(err) + return + } + + isAllOk := true + for _, result := range results { + if !result.IsOK { + isAllOk = false + break + } + } + + this.Data["isAllOk"] = isAllOk + this.Data["results"] = results + + this.Success() +} diff --git a/internal/web/actions/default/servers/server/settings/cache/purge.go b/internal/web/actions/default/servers/server/settings/cache/purge.go new file mode 100644 index 00000000..e18fe292 --- /dev/null +++ b/internal/web/actions/default/servers/server/settings/cache/purge.go @@ -0,0 +1,149 @@ +// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved. + +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/EdgeCommon/pkg/rpc/dao" + "github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb" + "github.com/iwind/TeaGo/actions" + "github.com/iwind/TeaGo/lists" + "strings" +) + +type PurgeAction struct { + actionutils.ParentAction +} + +func (this *PurgeAction) Init() { + this.Nav("", "setting", "purge") + this.SecondMenu("cache") +} + +func (this *PurgeAction) RunGet(params struct { + ServerId int64 +}) { + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithServerId(this.AdminContext(), params.ServerId) + if err != nil { + this.ErrorPage(err) + return + } + + this.Data["webId"] = webConfig.Id + this.Data["webConfig"] = webConfig + + this.Show() +} + +func (this *PurgeAction) RunPost(params struct { + ServerId int64 + WebId int64 + Type string + Keys string + + Must *actions.Must +}) { + + // 创建日志 + defer this.CreateLog(oplogs.LevelInfo, "删除服务 %d 缓存", params.ServerId) + + webConfig, err := dao.SharedHTTPWebDAO.FindWebConfigWithId(this.AdminContext(), params.WebId) + if err != nil { + this.ErrorPage(err) + return + } + if webConfig == nil { + this.NotFound("httpWeb", params.WebId) + return + } + var cache = webConfig.Cache + if cache == nil || !cache.IsOn { + this.Fail("当前没有开启缓存") + } + + serverResp, err := this.RPC().ServerRPC().FindEnabledUserServerBasic(this.AdminContext(), &pb.FindEnabledUserServerBasicRequest{ServerId: params.ServerId}) + if err != nil { + this.ErrorPage(err) + return + } + var server = serverResp.Server + if server == nil || server.NodeCluster == nil { + this.NotFound("server", params.ServerId) + return + } + + var clusterId = server.NodeCluster.Id + + clusterResp, err := this.RPC().NodeClusterRPC().FindEnabledNodeCluster(this.AdminContext(), &pb.FindEnabledNodeClusterRequest{NodeClusterId: clusterId}) + if err != nil { + this.ErrorPage(err) + return + } + var cluster = clusterResp.NodeCluster + if cluster == nil { + this.NotFound("nodeCluster", clusterId) + return + } + var cachePolicyId = cluster.HttpCachePolicyId + if cachePolicyId == 0 { + this.Fail("当前集群没有设置缓存策略") + } + + cachePolicyResp, err := this.RPC().HTTPCachePolicyRPC().FindEnabledHTTPCachePolicyConfig(this.AdminContext(), &pb.FindEnabledHTTPCachePolicyConfigRequest{HttpCachePolicyId: cachePolicyId}) + if err != nil { + this.ErrorPage(err) + return + } + cachePolicyJSON := cachePolicyResp.HttpCachePolicyJSON + if len(cachePolicyJSON) == 0 { + this.Fail("找不到要操作的缓存策略") + } + + if len(params.Keys) == 0 { + this.Fail("请输入要删除的Key列表") + } + + 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) + } + + // 发送命令 + 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) + if err != nil { + this.ErrorPage(err) + return + } + + isAllOk := true + for _, result := range results { + if !result.IsOK { + isAllOk = false + break + } + } + + this.Data["isAllOk"] = isAllOk + this.Data["results"] = results + + this.Success() +} diff --git a/internal/web/helpers/user_must_auth.go b/internal/web/helpers/user_must_auth.go index 38ae75b8..9a01a7e1 100644 --- a/internal/web/helpers/user_must_auth.go +++ b/internal/web/helpers/user_must_auth.go @@ -180,21 +180,16 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map { "subtitle": "服务列表", "icon": "clone outsize", "subItems": []maps.Map{ + { + "name": "证书管理", + "url": "/servers/certs", + "code": "cert", + }, { "name": "访问日志", "url": "/servers/logs", "code": "log", }, - { - "name": "通用设置", - "url": "/servers/components", - "code": "global", - }, - { - "name": "服务分组", - "url": "/servers/components/groups", - "code": "group", - }, { "name": "缓存策略", "url": "/servers/components/cache", @@ -216,16 +211,21 @@ func (this *userMustAuth) modules(adminId int64) []maps.Map { "url": "/servers/iplists", "code": "iplist", }, - { - "name": "证书管理", - "url": "/servers/certs", - "code": "cert", - }, { "name": "统计指标", "url": "/servers/metrics", "code": "metric", }, + { + "name": "服务分组", + "url": "/servers/components/groups", + "code": "group", + }, + { + "name": "通用设置", + "url": "/servers/components", + "code": "global", + }, }, }, { diff --git a/web/views/@default/servers/components/cache/purge.html b/web/views/@default/servers/components/cache/purge.html index 5abd3889..fcb5d9d2 100644 --- a/web/views/@default/servers/components/cache/purge.html +++ b/web/views/@default/servers/components/cache/purge.html @@ -8,7 +8,7 @@

批量删除

-

可以批量删除一组Key。

+

可以在这里批量删除一组Key。

diff --git a/web/views/@default/servers/server/settings/cache/@menu.html b/web/views/@default/servers/server/settings/cache/@menu.html new file mode 100644 index 00000000..ebb46566 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/@menu.html @@ -0,0 +1,5 @@ + + 设置 + 清理 + 预热 + \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/index.html b/web/views/@default/servers/server/settings/cache/index.html index 5defa80b..655a5505 100644 --- a/web/views/@default/servers/server/settings/cache/index.html +++ b/web/views/@default/servers/server/settings/cache/index.html @@ -1,8 +1,9 @@ {$layout} - {$template "/left_menu"}
+ {$template "menu"} + diff --git a/web/views/@default/servers/server/settings/cache/preheat.html b/web/views/@default/servers/server/settings/cache/preheat.html new file mode 100644 index 00000000..c01baa93 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/preheat.html @@ -0,0 +1,39 @@ +{$layout} +{$template "/left_menu"} + +
+ {$template "menu"} + +
+
+

没有开启缓存,不需要清理。

+
+
+

可以在这里批量预热一组Key。

+ + + + + + + + + + + + +
Key列表 + +

每行一个Key。

+
操作结果 +
数据发送中...
+ 失败:{{message}} +
+ 此集群下没有任何可用的节点。 +
{{one.nodeName}}:{{one.message}}
+
+
+ 提交 + +
+
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/preheat.js b/web/views/@default/servers/server/settings/cache/preheat.js new file mode 100644 index 00000000..121c5489 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/preheat.js @@ -0,0 +1,26 @@ +Tea.context(function () { + this.isRequesting = false + this.isOk = false + this.message = "" + this.results = [] + + this.before = function () { + this.isRequesting = true + this.isOk = false + this.message = "" + this.results = [] + } + + this.success = function (resp) { + this.isOk = true + this.results = resp.data.results + } + + this.fail = function (resp) { + this.message = resp.message + } + + this.done = function () { + this.isRequesting = false + } +}); \ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/purge.html b/web/views/@default/servers/server/settings/cache/purge.html new file mode 100644 index 00000000..54912971 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/purge.html @@ -0,0 +1,51 @@ +{$layout} +{$template "/left_menu"} + +
+ {$template "menu"} + +
+
+

没有开启缓存,不需要清理。

+
+
+

可以在这里批量删除一组Key。

+ +
+ + + + + + + + + + + + + + + +
操作类型 + 根据Key   + 根据前缀 +
+ Key列表 + Key前缀列表 + + +

每行一个Key,比如是一个完整的URLhttps://example.com/hello/world.html

+

每行一个Key前缀,比如是一个URL前缀https://example.com/hello/

+
操作结果 +
数据发送中...
+ 失败:{{message}} +
+ 此集群下没有任何可用的节点。 +
{{one.nodeName}}:{{one.message}}
+
+
+ 提交 +
+
+
\ No newline at end of file diff --git a/web/views/@default/servers/server/settings/cache/purge.js b/web/views/@default/servers/server/settings/cache/purge.js new file mode 100644 index 00000000..69899cf0 --- /dev/null +++ b/web/views/@default/servers/server/settings/cache/purge.js @@ -0,0 +1,31 @@ +Tea.context(function () { + this.isRequesting = false + this.isOk = false + this.message = "" + this.results = [] + + this.before = function () { + this.isRequesting = true + this.isOk = false + this.message = "" + this.results = [] + } + + this.success = function (resp) { + this.isOk = true + this.results = resp.data.results + } + + this.fail = function (resp) { + this.message = resp.message + } + + this.done = function () { + this.isRequesting = false + } + + /** + * 操作类型 + */ + this.type = "key" // key | prefix +}) \ No newline at end of file