This is an automated email from the ASF dual-hosted git repository.
guangning pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-manager.git
The following commit(s) were added to refs/heads/master by this push:
new 2cffa68 [Offload] Add offload threshold input (#375)
2cffa68 is described below
commit 2cffa68d3d9aebe77f8652abe30c447567ff57d3
Author: ran <[email protected]>
AuthorDate: Thu Mar 25 20:11:07 2021 +0800
[Offload] Add offload threshold input (#375)
Fixes #374
### Motivation
Currently, the offload operation lacks the offload threshold.
### Modifications
Add the offload threshold input for the offload operation.
### Verifying this change
- [ ] Make sure that the change passes the `./gradlew build` checks.
---
front-end/src/lang/en.js | 6 +-
front-end/src/lang/zh.js | 6 +-
front-end/src/utils/validate.js | 25 ++++++
front-end/src/views/management/topics/topic.vue | 113 +++++++++++++++++++-----
4 files changed, 125 insertions(+), 25 deletions(-)
diff --git a/front-end/src/lang/en.js b/front-end/src/lang/en.js
index 23f566e..f2c974f 100644
--- a/front-end/src/lang/en.js
+++ b/front-end/src/lang/en.js
@@ -619,11 +619,15 @@ export default {
unloadTopicSuccess: 'Successfully unload the topic!',
terminateTopicSuccess: 'Successfully terminate the topic!',
startCompactionSuccess: 'Successfully start compacting the topic!',
- startOffloadSuccess: 'Successfully start offloading the topic!',
+ startOffloadSuccess: 'Successfully start offloading the topic',
expireMessageSuccess: 'Successfully expire messages the topic!',
resetMessageSuccess: 'Successfully reset messages the topic!',
clearMessageSuccess: 'Successfully clear messages the topic'
},
+ errorLog: {
+ noOffloadData: 'Nothing to offload!',
+ invalidSizeStr: 'Invalid size string! (e.g 200K 50M 1G)'
+ },
info: 'INFO',
column: 'column',
data: 'data',
diff --git a/front-end/src/lang/zh.js b/front-end/src/lang/zh.js
index bbec239..db9b299 100644
--- a/front-end/src/lang/zh.js
+++ b/front-end/src/lang/zh.js
@@ -619,9 +619,13 @@ export default {
unloadTopicSuccess: 'Successfully unload the topic!',
terminateTopicSuccess: 'Successfully terminate the topic!',
startCompactionSuccess: 'Successfully start compacting the topic!',
- startOffloadSuccess: 'Successfully start offloading the topic!',
+ startOffloadSuccess: 'Successfully start offloading the topic',
expireMessageSuccess: 'Successfully expire messages the topic!'
},
+ errorLog: {
+ noOffloadData: 'Nothing to offload!',
+ invalidSizeStr: 'Invalid size string! (e.g 200K 50M 1G)'
+ },
info: 'INFO',
column: 'column',
data: 'data',
diff --git a/front-end/src/utils/validate.js b/front-end/src/utils/validate.js
index c45458a..751bb12 100644
--- a/front-end/src/utils/validate.js
+++ b/front-end/src/utils/validate.js
@@ -86,3 +86,28 @@ export function validateServiceUrl(expectedProtocol,
allowEmpty) {
}
}
}
+
+export function validateSizeString(str) {
+ var last = str.charAt(str.length - 1)
+ var subStr = str.substring(0, str.length - 1)
+ switch (last) {
+ case 'k':
+ case 'K':
+ return Number(subStr) * 1024
+
+ case 'm':
+ case 'M':
+ return Number(subStr) * 1024 * 1024
+
+ case 'g':
+ case 'G':
+ return Number(subStr) * 1024 * 1024 * 1024
+
+ case 't':
+ case 'T':
+ return Number(subStr) * 1024 * 1024 * 1024 * 1024
+
+ default:
+ return Number(str)
+ }
+}
diff --git a/front-end/src/views/management/topics/topic.vue
b/front-end/src/views/management/topics/topic.vue
index 1d211c9..f45b53b 100644
--- a/front-end/src/views/management/topics/topic.vue
+++ b/front-end/src/views/management/topics/topic.vue
@@ -185,23 +185,29 @@
class="circle">
<span class="circle-font">{{ offload }}</span>
</el-button>
- <el-button
- v-if="offload !== 'RUNNING'"
- type="primary"
-
style="display:block;margin-top:15px;margin-left:auto;margin-right:auto;"
- icon="el-icon-refresh"
- @click="handleOffload">
- {{ $t('topic.offload') }}
- </el-button>
- <el-button
- v-if="offload === 'RUNNING'"
- type="success"
-
style="display:block;margin-top:15px;margin-left:auto;margin-right:auto;"
- icon="el-icon-refresh"
- disabled
- @click="handleOffload">
- {{ $t('topic.offload') }}
- </el-button>
+ <el-row type="flex" justify="center" style="margin-top:15px;">
+ <el-col :span="16">
+ <el-button
+ :disabled="offloadDisabled"
+ type="primary"
+ icon="el-icon-refresh"
+ @click="handleOffload">
+ {{ $t('topic.offload') }}
+ </el-button>
+ </el-col>
+ <el-col :span="8">
+ <el-tooltip
+ class="item"
+ effect="dark"
+ content="offload threshold (e.g 200k 50m 1g)"
+ placement="top-start">
+ <el-input
+ v-model="offloadThreshold"
+ :disabled="offloadDisabled"
+ style="display:block;"/>
+ </el-tooltip>
+ </el-col>
+ </el-row>
</el-card>
</el-col>
</el-row>
@@ -554,6 +560,7 @@ import Pagination from '@/components/Pagination' //
Secondary package based on e
import { formatBytes } from '@/utils/index'
import { numberFormatter } from '@/filters/index'
import { putSubscriptionOnCluster, deleteSubscriptionOnCluster } from
'@/api/subscriptions'
+import { validateSizeString } from '@/utils/validate'
const defaultForm = {
persistent: '',
@@ -645,7 +652,9 @@ export default {
routeTopic: '',
routeTopicPartition: -1,
routeCluster: '',
- loaded: false
+ loaded: false,
+ offloadThreshold: '0K',
+ offloadDisabled: true
}
},
created() {
@@ -739,6 +748,7 @@ export default {
offloadStatusOnCluster(this.getCurrentCluster(),
this.postForm.persistent, this.getFullTopic()).then(response => {
if (!response.data) return
this.offload = response.data.status
+ this.offloadDisabled = this.offload === 'RUNNING'
})
},
getCompactionStatus() {
@@ -1026,15 +1036,72 @@ export default {
})
},
handleOffload() {
- offloadOnCluster(this.getCurrentCluster(), this.postForm.persistent,
this.getFullTopic()).then(response => {
+ var threshold = validateSizeString(this.offloadThreshold)
+ if (isNaN(threshold) || threshold < 0) {
this.$notify({
- title: 'success',
- message: this.$i18n.t('topic.notification.startOffloadSuccess'),
- type: 'success',
+ title: 'error',
+ message: this.$i18n.t('topic.errorLog.invalidSizeStr'),
+ type: 'error',
duration: 3000
})
+ return
+ }
+
+ fetchTopicStatsInternal(this.postForm.persistent,
this.getFullTopic()).then(response => {
+ let ledgers = response.data.ledgers
+
+ if (!ledgers || ledgers.length <= 1) {
+ this.$notify({
+ title: 'warn',
+ message: this.$i18n.t('topic.errorLog.noOffloadData'),
+ type: 'warn',
+ duration: 3000
+ })
+ return
+ }
+
+ ledgers[ledgers.length - 1].size = response.data.currentLedgerSize
+ ledgers = ledgers.reverse()
+
+ var totalSize = 0
+ var preLedgerId = ledgers[0].ledgerId
+ var messageId
+ for (var i = 0; i < ledgers.length; i++) {
+ totalSize += ledgers[i].size
+ if (totalSize > threshold) {
+ messageId = {
+ ledgerId: preLedgerId,
+ entryId: 0,
+ partitionIndex: -1
+ }
+ break
+ }
+ preLedgerId = ledgers[i].ledgerId
+ }
+
+ if (!messageId) {
+ this.$notify({
+ title: 'warn',
+ message: this.$i18n.t('topic.errorLog.noOffloadData'),
+ type: 'warn',
+ duration: 3000
+ })
+ return
+ }
+
+ offloadOnCluster(this.getCurrentCluster(), this.postForm.persistent,
this.getFullTopic(), messageId)
+ .then(response => {
+ var msg = this.$i18n.t('topic.notification.startOffloadSuccess') +
+ ' before ' + messageId['ledgerId'] + ':' +
messageId['entryId'] + ' !'
+ this.$notify({
+ title: 'success',
+ message: msg,
+ type: 'success',
+ duration: 3000
+ })
+ })
+ this.getOffloadStatus()
})
- this.getOffloadStatus()
},
handleDeleteTopic() {
this.dialogStatus = 'delete'