增加刷新、预热缓存任务管理

This commit is contained in:
GoEdgeLab
2022-06-05 17:12:54 +08:00
parent 091dfed996
commit 1aefd2e92b
63 changed files with 1196 additions and 270 deletions

View File

@@ -6,6 +6,6 @@
<menu-item :href="'/servers/components/cache/stat?cachePolicyId=' + cachePolicyId" code="stat">统计</menu-item>
<menu-item :href="'/servers/components/cache/clean?cachePolicyId=' + cachePolicyId" code="clean">清理</menu-item>
<menu-item :href="'/servers/components/cache/purge?cachePolicyId=' + cachePolicyId" code="purge">删除</menu-item>
<menu-item :href="'/servers/components/cache/preheat?cachePolicyId=' + cachePolicyId" code="preheat">预热</menu-item>
<menu-item :href="'/servers/components/cache/fetch?cachePolicyId=' + cachePolicyId" code="fetch">预热</menu-item>
<menu-item :href="'/servers/components/cache/update?cachePolicyId=' + cachePolicyId" code="update">修改</menu-item>
</second-menu>

View File

@@ -0,0 +1,6 @@
<first-menu>
<menu-item href="." code="purge">刷新缓存</menu-item>
<menu-item href=".fetch" code="fetch">预热缓存</menu-item>
<span class="item disabled">|</span>
<menu-item href=".tasks" code="task">所有任务<span v-if="countDoingTasks > 0" class="grey">({{countDoingTasks}})</span></menu-item>
</first-menu>

View File

@@ -0,0 +1,28 @@
{$layout}
{$template "menu"}
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
<csrf-token></csrf-token>
<table class="ui table definition selectable">
<tr>
<td>要预热的Key列表</td>
<td>
<textarea name="keys" rows="10" ref="focus"></textarea>
<p class="comment">每行一个Key。</p>
</td>
</tr>
<tr>
<td class="title">操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>

View File

@@ -1,31 +1,29 @@
Tea.context(function () {
if (this.clusterId == null) {
if (this.clusters.length > 0) {
this.clusterId = this.clusters[0].id
} else {
this.clusterId = 0
}
}
this.isRequesting = false
this.isOk = false
this.message = ""
this.results = []
this.failKeys = []
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.results = []
this.failKeys = []
}
this.success = function (resp) {
this.isOk = true
this.results = resp.data.results
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {

View File

@@ -0,0 +1,8 @@
.fail-keys-box {
max-height: 10em;
overflow-y: auto;
}
.fail-keys-box::-webkit-scrollbar {
width: 6px;
}
/*# sourceMappingURL=index.css.map */

View File

@@ -0,0 +1 @@
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;EACA,gBAAA;;AAGD,cAAc;EACb,UAAA","file":"index.css"}

View File

@@ -0,0 +1,41 @@
{$layout}
{$template "menu"}
<div class="margin"></div>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
<csrf-token></csrf-token>
<table class="ui table definition selectable">
<tr>
<td class="title">缓存Key类型</td>
<td>
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio> &nbsp;
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
</td>
</tr>
<tr>
<td>
<span v-if="keyType == 'key'">要刷新的Key列表</span>
<span v-if="keyType == 'prefix'">要刷新的Key前缀列表</span>
</td>
<td>
<textarea name="keys" rows="10" ref="keysBox"></textarea>
<p class="comment" v-if="keyType == 'key'">每行一个Key比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label></p>
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀比如是一个URL前缀<code-label>https://example.com/hello/</code-label></p>
</td>
</tr>
<tr>
<td>操作结果</td>
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>
</table>
<submit-btn v-if="!isRequesting">提交</submit-btn>
</form>

View File

@@ -0,0 +1,43 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.failKeys = []
this.$delay(function () {
this.$refs.keysBox.focus()
this.$watch("keyType", function () {
this.$refs.keysBox.focus()
})
})
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.failKeys = []
}
this.success = function () {
this.isOk = true
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {
this.isRequesting = false
}
/**
* 操作类型
*/
this.keyType = "key" // key | prefix
})

View File

@@ -0,0 +1,8 @@
.fail-keys-box {
max-height: 10em;
overflow-y: auto;
}
.fail-keys-box::-webkit-scrollbar {
width: 6px;
}

View File

@@ -0,0 +1,94 @@
{$layout}
{$template "menu"}
<second-menu>
<menu-item href=".tasks">所有任务</menu-item>
<span class="disabled item" style="padding: 0">&raquo;</span>
<span class="item">任务详情</span>
</second-menu>
<table class="ui table definition selectable">
<tr>
<td class="title">任务编号</td>
<td>{{task.id}}</td>
</tr>
<tr>
<td>任务类型</td>
<td>
<span v-if="task.type == 'purge'">刷新</span>
<span v-if="task.type == 'fetch'">预热</span>
</td>
</tr>
<tr>
<td>Key类型</td>
<td>
<span v-if="task.keyType == 'key'">URL</span>
<span v-if="task.keyType == 'prefix'">前缀</span>
</td>
</tr>
<tr>
<td>创建时间</td>
<td>
{{task.createdTime}}
</td>
</tr>
<tr>
<td>完成时间</td>
<td>
<span v-if="task.isDone">{{task.doneTime}}</span>
<span v-else class="disabled">尚未完成</span>
</td>
</tr>
<tr>
<td>所属用户</td>
<td>
<span v-if="task.user != null && task.user.id > 0"><user-link :v-user="task.user"></user-link></span>
<span v-else="" class="disabled">-</span>
</td>
</tr>
<tr>
<td>任务状态</td>
<td>
<span v-if="task.isOk" class="green">已完成</span>
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id" v-else-if="task.isDone" class="red"><span class="red">失败</span></a>
<span v-else-if="!task.isDone" class="grey">等待执行</span>
</td>
</tr>
<tr>
<td>操作</td>
<td>
<a href="" @click.prevent="deleteTask(task.id)">[删除]</a> &nbsp; &nbsp;
<a href="" @click.prevent="resetTask(task.id)">[重置状态]</a>
</td>
</tr>
</table>
<h4>要操作的缓存Key</h4>
<table class="ui table selectable celled">
<thead>
<tr>
<th>
<span v-if="task.keyType == 'key'">URL</span>
<span v-if="task.keyType == 'prefix'">前缀</span>
</th>
<th class="width5">状态</th>
</tr>
</thead>
<tbody v-for="key in task.keys">
<tr>
<td>{{key.key}}
<div v-if="key.errors.length > 0" style="margin-top: 0.5em">
<a :href="'/clusters/cluster/node?nodeId=' + err.nodeId" v-for="err in key.errors" class="ui label basic tiny red">
节点{{err.nodeId}}{{err.error}}
</a>
</div>
</td>
<td>
<span v-if="key.isDone && key.errors.length == 0" class="green">完成</span>
<span v-if="key.isDone && key.errors.length > 0" class="red">失败</span>
<span v-if="!key.isDone" class="grey">未执行</span>
</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,23 @@
Tea.context(function () {
this.deleteTask = function (taskId) {
teaweb.confirm("确定要删除此任务吗?", function () {
this.$post(".deleteTask")
.params({
taskId: taskId
})
.success(function () {
window.location = Tea.url(".tasks")
})
})
}
this.resetTask = function (taskId) {
teaweb.confirm("确定要重置任务状态吗?", function () {
this.$post(".resetTask")
.params({
taskId: taskId
})
.refresh()
})
}
})

View File

@@ -0,0 +1,48 @@
{$layout}
{$template "menu"}
<p class="comment" v-if="tasks.length == 0">暂时还没有任务。</p>
<table class="ui table selectable celled" v-if="tasks.length > 0">
<thead>
<tr>
<th style="width: 7em">任务编号</th>
<th>任务类型</th>
<th>Key类型</th>
<th>创建时间</th>
<th class="four wide">所属用户</th>
<th class="two wide">任务状态</th>
<th class="two op">操作</th>
</tr>
</thead>
<tbody v-for="task in tasks">
<tr>
<td><a :href="'/servers/components/cache/batch/task?taskId=' + task.id">{{task.id}}</a></td>
<td>
<span v-if="task.type == 'purge'">刷新</span>
<span v-if="task.type == 'fetch'">预热</span>
</td>
<td>
<span v-if="task.keyType == 'key'">URL</span>
<span v-if="task.keyType == 'prefix'">前缀</span>
</td>
<td>{{task.createdTime}}</td>
<td>
<span v-if="task.user != null && task.user.id > 0"><user-link :v-user="task.user"></user-link></span>
<span v-if="task.description.length > 0" class="grey">{{task.description}}</span>
<span v-else="" class="disabled">-</span>
</td>
<td>
<span v-if="task.isOk" class="green">已完成</span>
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id" v-else-if="task.isDone" class="red"><span class="red">失败</span></a>
<span v-else-if="!task.isDone" class="grey">等待执行</span>
</td>
<td>
<a :href="'/servers/components/cache/batch/task?taskId=' + task.id">详情</a> &nbsp;
<a href="" @click.prevent="deleteTask(task.id)">删除</a>
</td>
</tr>
</tbody>
</table>
<page-box></page-box>

View File

@@ -0,0 +1,11 @@
Tea.context(function () {
this.deleteTask = function (taskId) {
teaweb.confirm("确定要删除此任务吗?", function () {
this.$post(".deleteTask")
.params({
taskId: taskId
})
.refresh()
})
}
})

View File

@@ -1,15 +1,8 @@
{$layout}
{$template "policy_menu"}
<h3>选择集群</h3>
<select class="ui dropdown auto-width" v-model="clusterId">
<option v-for="cluster in clusters" :value="cluster.id">{{cluster.name}}</option>
</select>
<div class="ui divider"></div>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="3600">
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
<input type="hidden" name="clusterId" :value="clusterId"/>
<table class="ui table definition selectable">
<tr>
<td>Key列表</td>
@@ -23,9 +16,10 @@
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && isOk">
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}{{one.message}}</div>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>

View File

@@ -0,0 +1,32 @@
Tea.context(function () {
this.isRequesting = false
this.isOk = false
this.message = ""
this.failKeys = []
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.failKeys = []
}
this.success = function (resp) {
this.isOk = true
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {
this.isRequesting = false
}
});

View File

@@ -1,34 +1,26 @@
{$layout}
{$template "policy_menu"}
<h3>选择集群</h3>
<select class="ui dropdown auto-width" v-model="clusterId">
<option v-for="cluster in clusters" :value="cluster.id">{{cluster.name}}</option>
</select>
<div class="ui divider"></div>
<h3>批量删除</h3>
<p class="comment">可以在这里批量删除一组Key。</p>
<form method="post" class="ui form" data-tea-action="$" data-tea-before="before" data-tea-success="success" data-tea-fail="fail" data-tea-done="done" data-tea-timeout="300">
<input type="hidden" name="cachePolicyId" :value="cachePolicyId"/>
<input type="hidden" name="clusterId" :value="clusterId"/>
<table class="ui table definition selectable">
<tr>
<td class="title">操作类型</td>
<td>
<radio name="type" :v-value="'key'" v-model="type">根据Key</radio> &nbsp;
<radio name="type" :v-value="'prefix'" v-model="type">根据前缀</radio>
<radio name="keyType" :v-value="'key'" v-model="keyType">根据Key</radio> &nbsp;
<radio name="keyType" :v-value="'prefix'" v-model="keyType">根据前缀</radio>
</td>
</tr>
<tr>
<td>
<span v-if="type == 'key'">Key列表</span>
<span v-if="type == 'prefix'">Key前缀列表</span>
<span v-if="keyType == 'key'">Key列表</span>
<span v-if="keyType == 'prefix'">Key前缀列表</span>
</td>
<td>
<textarea name="keys" rows="10" ref="focus"></textarea>
<p class="comment" v-if="type == 'key'">每行一个Key比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label></p>
<p class="comment" v-if="type == 'prefix'">每行一个Key前缀比如是一个URL前缀<code-label>https://example.com/hello/</code-label></p>
<textarea name="keys" rows="10" ref="keysBox"></textarea>
<p class="comment" v-if="keyType == 'key'">每行一个Key比如是一个完整的URL<code-label>https://example.com/hello/world.html</code-label></p>
<p class="comment" v-if="keyType == 'prefix'">每行一个Key前缀比如是一个URL前缀<code-label>https://example.com/hello/</code-label></p>
</td>
</tr>
<tr>
@@ -36,9 +28,10 @@
<td>
<div v-if="isRequesting">数据发送中...</div>
<span class="red" v-if="!isRequesting && !isOk && message.length > 0">失败:{{message}}</span>
<div v-if="!isRequesting && isOk">
<span v-if="results.length == 0" class="red">此集群下没有任何可用的节点。</span>
<div class="ui label tiny" v-for="one in results" :class="{green:one.isOk, red:!one.isOk}" style="margin-bottom: 0.5em">{{one.nodeName}}{{one.message}}</div>
<div v-if="!isRequesting && !isOk && failKeys.length > 0" class="fail-keys-box">
<div v-for="failKey in failKeys">
<span class="red">{{failKey.key}}: {{failKey.reason}}</span>
</div>
</div>
</td>
</tr>

View File

@@ -1,31 +1,35 @@
Tea.context(function () {
if (this.clusterId == null) {
if (this.clusters.length > 0) {
this.clusterId = this.clusters[0].id
} else {
this.clusterId = 0
}
}
this.isRequesting = false
this.isOk = false
this.message = ""
this.results = []
this.failKeys = []
this.$delay(function () {
this.$refs.keysBox.focus()
this.$watch("keyType", function () {
this.$refs.keysBox.focus()
})
})
this.before = function () {
this.isRequesting = true
this.isOk = false
this.message = ""
this.results = []
this.failKeys = []
}
this.success = function (resp) {
this.success = function () {
this.isOk = true
this.results = resp.data.results
let f = NotifyReloadSuccess("任务提交成功")
f()
}
this.fail = function (resp) {
this.message = resp.message
if (resp.data.failKeys != null) {
this.failKeys = resp.data.failKeys
}
}
this.done = function () {
@@ -35,5 +39,5 @@ Tea.context(function () {
/**
* 操作类型
*/
this.type = "key" // key | prefix
this.keyType = "key" // key | prefix
})