Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:节点清理显示清理详情 #1499 #1500

Merged
merged 6 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,17 @@ class UserNodeController(
return ResponseBuilder.success(nodeSizeInfo)
}

@ApiOperation("查询时间早于{date}的节点大小信息")
@Permission(type = ResourceType.NODE, action = PermissionAction.READ)
@GetMapping("/calculate/$DEFAULT_MAPPING_URI")
fun computeSizeBefore(
@ArtifactPathVariable artifactInfo: ArtifactInfo,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) date: LocalDateTime
): Response<NodeSizeInfo> {
val nodeSizeInfo = nodeService.computeSize(artifactInfo,false, date)
return ResponseBuilder.success(nodeSizeInfo)
}

@ApiOperation("分页查询节点")
@Permission(type = ResourceType.NODE, action = PermissionAction.READ)
@GetMapping("/page/$DEFAULT_MAPPING_URI")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ package com.tencent.bkrepo.repository.service.node
import com.tencent.bkrepo.common.artifact.api.ArtifactInfo
import com.tencent.bkrepo.repository.pojo.node.NodeSizeInfo
import org.springframework.data.mongodb.core.query.Criteria
import java.time.LocalDateTime

/**
* 节点重命名接口
Expand All @@ -43,7 +44,10 @@ interface NodeStatsOperation {
/**
* 计算文件或者文件夹大小
*/
fun computeSize(artifact: ArtifactInfo, estimated: Boolean = false): NodeSizeInfo
fun computeSize(artifact: ArtifactInfo,
estimated: Boolean = false,
before: LocalDateTime = LocalDateTime.now()
): NodeSizeInfo

/**
* 查询文件节点数量
Expand All @@ -54,4 +58,5 @@ interface NodeStatsOperation {
* 聚合查询节点大小
*/
fun aggregateComputeSize(criteria: Criteria): Long

}
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ class NodeServiceImpl(
servicePermissionClient,
) {

override fun computeSize(artifact: ArtifactInfo, estimated: Boolean): NodeSizeInfo {
return NodeStatsSupport(this).computeSize(artifact, estimated)
override fun computeSize(artifact: ArtifactInfo, estimated: Boolean, before: LocalDateTime): NodeSizeInfo {
return NodeStatsSupport(this).computeSize(artifact, estimated, before)
}

override fun aggregateComputeSize(criteria: Criteria): Long {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ import org.springframework.data.mongodb.core.aggregation.Aggregation.match
import org.springframework.data.mongodb.core.aggregation.Aggregation.newAggregation
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.data.mongodb.core.query.and
import java.time.LocalDateTime

/**
* 节点统计接口
Expand All @@ -56,7 +58,7 @@ open class NodeStatsSupport(

private val nodeDao: NodeDao = nodeBaseService.nodeDao

override fun computeSize(artifact: ArtifactInfo, estimated: Boolean): NodeSizeInfo {
override fun computeSize(artifact: ArtifactInfo, estimated: Boolean, before: LocalDateTime): NodeSizeInfo {
val projectId = artifact.projectId
val repoName = artifact.repoName
val fullPath = artifact.getArtifactFullPath()
Expand All @@ -71,11 +73,12 @@ open class NodeStatsSupport(
}
val listOption = NodeListOption(includeFolder = true, deep = true)
val criteria = NodeQueryHelper.nodeListCriteria(projectId, repoName, node.fullPath, listOption)
.and(TNode::lastModifiedDate).lt(before)
val count = nodeDao.count(Query(criteria))
val listOptionWithOutFolder = NodeListOption(includeFolder = false, deep = true)
val criteriaWithOutFolder = NodeQueryHelper.nodeListCriteria(
projectId, repoName, node.fullPath, listOptionWithOutFolder
)
).and(TNode::lastModifiedDate).lt(before)
val countWithOutFolder = nodeDao.count(Query(criteriaWithOutFolder))
val size = aggregateComputeSize(criteriaWithOutFolder)
nodeDao.setSizeAndNodeNumOfFolder(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ class EdgeNodeServiceImpl(
servicePermissionClient,
clusterProperties,
) {
override fun computeSize(artifact: ArtifactInfo, estimated: Boolean): NodeSizeInfo {
return NodeStatsSupport(this).computeSize(artifact, estimated)
override fun computeSize(artifact: ArtifactInfo, estimated: Boolean, before: LocalDateTime): NodeSizeInfo {
return NodeStatsSupport(this).computeSize(artifact, estimated, before)
}

override fun aggregateComputeSize(criteria: Criteria): Long {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
v-model="isShow">
<slot></slot>
<div v-if="backUp" class="mainBackUpBody">
<div>
<div class="iconBackUpBody">
<Icon v-if="!complete && !backUp" name="loading" size="20" class="svg-loading" />
<Icon v-else-if="!complete && backUp" name="circle-2-1" size="20" style="color: #3a84ff" class="svg-loading" />
<Icon v-else name="check" size="20" class="svg-complete" />
Expand All @@ -17,7 +17,7 @@
<span class="subMessage">{{ subMessage }}</span>
</div>
<div v-else class="mainBody">
<div>
<div class="iconBody">
<Icon v-if="!complete && !backUp" name="loading" size="20" class="svg-loading" />
<Icon v-else-if="!complete && backUp" name="circle-2-1" size="20" style="color: #3a84ff" class="svg-loading" />
<Icon v-else name="check" size="20" class="svg-complete" />
Expand Down Expand Up @@ -98,6 +98,11 @@ body .bk-dialog-wrapper .bk-dialog-body {
.svg-complete {
margin-right: 10px;
}
.iconBody{
display: flex;
align-items: center;
justify-content: center;
}
.mainMessage{
font-size: 16px;
}
Expand Down Expand Up @@ -128,6 +133,11 @@ body .bk-dialog-wrapper .bk-dialog-body {
.svg-complete {
margin-right: 10px;
}
.iconBackUpBody{
display: flex;
align-items: center;
justify-content: center;
}
.mainMessage{
font-size: 16px;
font-weight: bold;
Expand Down
11 changes: 11 additions & 0 deletions src/frontend/devops-repository/src/store/actions/repoGeneric.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,5 +380,16 @@ export default {
)
}
return request
},
// 统计时间早于{date}的文件节点信息
getFolderSizeBefore (_, { path, date }) {
return Vue.prototype.$ajax.get(
`${prefix}/node/calculate/${path}`,
{
params: {
date: date
}
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,38 @@
<bk-form-item :label="$t('cleanNode')" :required="true" property="path" error-display-type="normal">
<div v-if="displayPaths.length">
<div v-for="(item,index) in displayPaths " :key="index">
<bk-input v-model="item.path" style="margin-bottom: 10px; width: 260px" disabled="true" />
<bk-input v-if="item.isComplete" v-model="item.path" style="width: 260px" disabled="true" />
<bk-input v-else v-model="item.path" style="margin-bottom: 10px;width: 260px" disabled="true" />
<Icon name="right" v-if="item.isComplete" size="14" />
<div class="form-tip" v-if="item.isComplete" style="margin-bottom: 5px">{{ item.tip }}</div>
</div>
</div>
<div v-else>
<div v-for="(item,index) in paths " :key="index">
<bk-input v-model="item.path" style="margin-bottom: 10px; width: 260px" disabled="true" />
<bk-input v-if="item.isComplete" v-model="item.path" style="width: 260px" disabled="true" />
<bk-input v-else v-model="item.path" style="margin-bottom: 10px;width: 260px" disabled="true" />
<Icon name="right" v-if="item.isComplete" size="14" />
<div class="form-tip" v-if="item.isComplete" style="margin-bottom: 5px">{{ item.tip }}</div>
</div>
</div>
</bk-form-item>
<bk-form-item :label="$t('deadline')" :required="true" property="date" error-display-type="normal">
<bk-date-picker v-model="date" :clearable="false" :type="'datetime'"></bk-date-picker>
<bk-date-picker v-model="date" :clearable="false" :type="'datetime'" @change="resetStatus" :disabled="doing && !isComplete"></bk-date-picker>
<div class="form-tip">{{$t('cleanFolderTip')}}</div>
</bk-form-item>
</bk-form>
<template #footer>
<bk-button theme="default" @click="cancel" v-if="!isComplete">{{$t('cancel')}}</bk-button>
<bk-button class="ml10" :loading="loading" theme="primary" @click="submit" v-if="!isComplete" :disabled="doing">{{$t('confirm')}}</bk-button>
<bk-button class="ml10" :loading="loading" theme="primary" @click="calculateNode" v-if="!isComplete" :disabled="doing">{{$t('querySize')}}</bk-button>
<bk-button class="ml10" :loading="loading" theme="primary" @click="submit" v-if="!isComplete" :disabled="doing">{{$t('cleanRepo')}}</bk-button>
<bk-button class="ml10" theme="primary" @click="completeClean" v-if="isComplete">{{$t('complete')}}</bk-button>
</template>
</canway-dialog>
</template>

<script>
import { mapActions } from 'vuex'
import { convertFileSize } from '@repository/utils'
export default {
name: 'genericCleanDialog',
data () {
Expand All @@ -54,7 +60,8 @@
},
methods: {
...mapActions([
'cleanNode'
'cleanNode',
'getFolderSizeBefore'
]),
cancel () {
this.$emit('refresh')
Expand All @@ -72,23 +79,63 @@
await this.cleanNode({
path: path,
date: this.date instanceof Date ? this.date.toISOString() : undefined
}).then(() => {
}).then((res) => {
this.paths[i].isComplete = true
this.paths[i].tip = this.$t('cleanDetail', { 0: res.deletedNumber, 1: convertFileSize(res.deletedSize) })
if (this.displayPaths.length === this.paths.length) {
this.displayPaths[i].isComplete = true
this.displayPaths[i].tip = this.$t('cleanDetail', { 0: res.deletedNumber, 1: convertFileSize(res.deletedSize) })
}
completeNum++
})
}
if (completeNum === this.paths.length) {
this.isComplete = true
this.doing = false
this.$refs.genericForm.clearError()
}
},
async calculateNode () {
if (this.doing) {
return
}
this.doing = true
let completeNum = 0
for (let i = 0; i < this.paths.length; i++) {
const path = this.projectId + '/' + this.repoName + this.paths[i].path
await this.getFolderSizeBefore({
path: path,
date: this.date instanceof Date ? this.date.toISOString() : undefined
}).then((res) => {
this.paths[i].isComplete = true
this.paths[i].tip = this.$t('preCleanDetail', { 0: res.subNodeWithoutFolderCount, 1: convertFileSize(res.size) })
if (this.displayPaths.length === this.paths.length) {
this.displayPaths[i].isComplete = true
this.displayPaths[i].tip = this.$t('preCleanDetail', { 0: res.subNodeWithoutFolderCount, 1: convertFileSize(res.size) })
}
completeNum++
})
}
if (completeNum === this.paths.length) {
this.doing = false
this.$refs.genericForm.clearError()
}
},
completeClean () {
this.show = false
this.$emit('refresh')
this.doing = false
},
resetStatus () {
if (this.doing === false && this.isComplete === true) {
this.isComplete = false
for (let i = 0; i < this.paths.length; i++) {
this.paths[i].isComplete = false
if (this.displayPaths.length === this.paths.length) {
this.displayPaths[i].isComplete = false
}
}
}
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/frontend/locale/repository/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,7 @@
"backUpMessage": "{0} is an internal testing version and is being downloaded, please wait.",
"deadline": "Deadline",
"clean": "Clean",
"cleanNode": "Clean Folder",
"cleanNode": "Folders",
"cleanNodeTitle": "Clean Folder",
"complete": "Done",
"cleanFolderTip": "Files uploaded before the deadline will be cleared",
Expand Down Expand Up @@ -830,5 +830,8 @@
"roleName":"Name",
"addUserGroupTitle":"Create UserGroup",
"editUserGroupTitle": "Edit UserGroup",
"associatedUseGroup": "UserGroup"
"associatedUseGroup": "UserGroup",
"cleanDetail": "Cleaned {0} files in total, size {1}",
"preCleanDetail": "{0} files are expected to be cleaned, size {1}",
"querySize": "Query Size"
}
5 changes: 4 additions & 1 deletion src/frontend/locale/repository/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -831,5 +831,8 @@
"roleName":"用户组名称",
"addUserGroupTitle":"创建用户组",
"editUserGroupTitle": "编辑用户组",
"associatedUseGroup": "关联用户组"
"associatedUseGroup": "关联用户组",
"cleanDetail": "共清理文件{0}个,大小{1}",
"preCleanDetail": "预计清理文件{0}个,大小{1}",
"querySize": "查询大小"
}
Loading