perf: set status auto refresh on by default and save to connection profile

This commit is contained in:
Lykin 2024-01-18 11:21:58 +08:00
parent 6538313da8
commit 9402af2433
11 changed files with 194 additions and 125 deletions

View File

@ -367,11 +367,31 @@ func (c *connectionService) SaveLastDB(name string, db int) (resp types.JSResp)
return return
} }
if param.LastDB != db {
param.LastDB = db param.LastDB = db
if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil { if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil {
resp.Msg = "save connection fail:" + err.Error() resp.Msg = "save connection fail:" + err.Error()
return return
} }
}
resp.Success = true
return
}
// SaveRefreshInterval save auto refresh interval
func (c *connectionService) SaveRefreshInterval(name string, interval int) (resp types.JSResp) {
param := c.conns.GetConnection(name)
if param == nil {
resp.Msg = "no connection named \"" + name + "\""
return
}
if param.RefreshInterval != interval {
param.RefreshInterval = interval
if err := c.conns.UpdateConnection(name, param.ConnectionConfig); err != nil {
resp.Msg = "save connection fail:" + err.Error()
return
}
}
resp.Success = true resp.Success = true
return return
} }

View File

@ -39,6 +39,7 @@ func (c *ConnectionsStorage) defaultConnectionItem() types.ConnectionConfig {
DBFilterList: []int{}, DBFilterList: []int{},
LoadSize: consts.DEFAULT_LOAD_SIZE, LoadSize: consts.DEFAULT_LOAD_SIZE,
MarkColor: "", MarkColor: "",
RefreshInterval: 5,
Sentinel: types.ConnectionSentinel{ Sentinel: types.ConnectionSentinel{
Master: "mymaster", Master: "mymaster",
}, },

View File

@ -19,6 +19,7 @@ type ConnectionConfig struct {
KeyView int `json:"keyView,omitempty" yaml:"key_view,omitempty"` KeyView int `json:"keyView,omitempty" yaml:"key_view,omitempty"`
LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"` LoadSize int `json:"loadSize,omitempty" yaml:"load_size,omitempty"`
MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"` MarkColor string `json:"markColor,omitempty" yaml:"mark_color,omitempty"`
RefreshInterval int `json:"refreshInterval,omitempty" yaml:"refreshInterval,omitempty"`
SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"` SSL ConnectionSSL `json:"ssl,omitempty" yaml:"ssl,omitempty"`
SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"` SSH ConnectionSSH `json:"ssh,omitempty" yaml:"ssh,omitempty"`
Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"` Sentinel ConnectionSentinel `json:"sentinel,omitempty" yaml:"sentinel,omitempty"`

View File

@ -1 +1 @@
0024a462d0c3d76d35aeb433518d8b5e c2681c210327633ae1a043d772209dc7

View File

@ -124,7 +124,9 @@ watch(
<span>{{ $t('interface.sub_tab.status') }}</span> <span>{{ $t('interface.sub_tab.status') }}</span>
</n-space> </n-space>
</template> </template>
<content-server-status :server="props.server" /> <content-server-status
:pause="selectedSubTab !== BrowserTabType.Status.toString()"
:server="props.server" />
</n-tab-pane> </n-tab-pane>
<!-- key detail pane --> <!-- key detail pane -->

View File

@ -13,13 +13,16 @@ import dayjs from 'dayjs'
import { convertBytes, formatBytes } from '@/utils/byte_convert.js' import { convertBytes, formatBytes } from '@/utils/byte_convert.js'
import usePreferencesStore from 'stores/preferences.js' import usePreferencesStore from 'stores/preferences.js'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import useConnectionStore from 'stores/connections.js'
const props = defineProps({ const props = defineProps({
server: String, server: String,
pause: Boolean,
}) })
const browserStore = useBrowserStore() const browserStore = useBrowserStore()
const prefStore = usePreferencesStore() const prefStore = usePreferencesStore()
const connectionStore = useConnectionStore()
const i18n = useI18n() const i18n = useI18n()
const themeVars = useThemeVars() const themeVars = useThemeVars()
const serverInfo = ref({}) const serverInfo = ref({})
@ -125,13 +128,19 @@ const isLoading = computed(() => {
}) })
const startAutoRefresh = async () => { const startAutoRefresh = async () => {
// connectionStore.getRefreshInterval()
let lastExec = Date.now() let lastExec = Date.now()
do { do {
if (!pageState.autoRefresh) { if (!pageState.autoRefresh) {
break break
} }
await timeout(100) await timeout(100)
if (pageState.loading || pageState.autoLoading || Date.now() - lastExec < pageState.refreshInterval * 1000) { if (
props.pause ||
pageState.loading ||
pageState.autoLoading ||
Date.now() - lastExec < pageState.refreshInterval * 1000
) {
continue continue
} }
lastExec = Date.now() lastExec = Date.now()
@ -147,13 +156,23 @@ const stopAutoRefresh = () => {
const onToggleRefresh = (on) => { const onToggleRefresh = (on) => {
if (on) { if (on) {
tabVal.value = 'activity' tabVal.value = 'activity'
connectionStore.saveRefreshInterval(props.server, pageState.refreshInterval || 5)
startAutoRefresh() startAutoRefresh()
} else { } else {
connectionStore.saveRefreshInterval(props.server, -1)
stopAutoRefresh() stopAutoRefresh()
} }
} }
onMounted(() => { onMounted(() => {
const interval = connectionStore.getRefreshInterval(props.server)
if (interval >= 0) {
pageState.autoRefresh = true
pageState.refreshInterval = interval === 0 ? 5 : interval
onToggleRefresh(true)
} else {
setTimeout(refreshInfo, 5000)
}
refreshInfo() refreshInfo()
}) })
@ -208,15 +227,15 @@ const totalKeys = computed(() => {
return sum(toArray(nums)) return sum(toArray(nums))
}) })
const tabVal = ref('info') const tabVal = ref('activity')
const envFilter = reactive({ const infoFilter = reactive({
keyword: '', keyword: '',
group: 'CPU', group: 'CPU',
}) })
const env = computed(() => { const info = computed(() => {
if (!isEmpty(envFilter.group)) { if (!isEmpty(infoFilter.group)) {
const val = serverInfo.value[envFilter.group] const val = serverInfo.value[infoFilter.group]
if (!isEmpty(val)) { if (!isEmpty(val)) {
return map(val, (v, k) => ({ return map(val, (v, k) => ({
key: k, key: k,
@ -235,10 +254,10 @@ const env = computed(() => {
}) })
const onFilterGroup = (group) => { const onFilterGroup = (group) => {
if (group === envFilter.group) { if (group === infoFilter.group) {
envFilter.group = '' infoFilter.group = ''
} else { } else {
envFilter.group = group infoFilter.group = group
} }
} }
@ -345,6 +364,7 @@ const chartOption = {
scales: { scales: {
y: { y: {
beginAtZero: true, beginAtZero: true,
stepSize: 1024,
suggestedMin: 0, suggestedMin: 0,
ticks: { ticks: {
precision: 0, precision: 0,
@ -365,7 +385,7 @@ const byteChartOption = {
precision: 0, precision: 0,
// format display y axios tag // format display y axios tag
callback: function (value, index, values) { callback: function (value, index, values) {
return formatBytes(value, 0) return formatBytes(value, 1)
}, },
}, },
}, },
@ -429,7 +449,6 @@ const byteChartOption = {
@toggle="onToggleRefresh" /> @toggle="onToggleRefresh" />
</n-popover> </n-popover>
</template> </template>
<n-spin :show="pageState.loading">
<n-grid style="min-width: 500px" x-gap="5"> <n-grid style="min-width: 500px" x-gap="5">
<n-gi :span="6"> <n-gi :span="6">
<n-statistic :label="$t('status.uptime')" :value="uptime.value"> <n-statistic :label="$t('status.uptime')" :value="uptime.value">
@ -454,7 +473,6 @@ const byteChartOption = {
</n-statistic> </n-statistic>
</n-gi> </n-gi>
</n-grid> </n-grid>
</n-spin>
</n-card> </n-card>
<n-card class="flex-item-expand" content-style="padding: 0; height: 100%;" embedded style="overflow: hidden"> <n-card class="flex-item-expand" content-style="padding: 0; height: 100%;" embedded style="overflow: hidden">
<n-tabs <n-tabs
@ -466,7 +484,7 @@ const byteChartOption = {
type="line"> type="line">
<template #suffix> <template #suffix>
<div v-if="tabVal === 'info'" style="padding-right: 10px"> <div v-if="tabVal === 'info'" style="padding-right: 10px">
<n-input v-model:value="envFilter.keyword" clearable placeholder=""> <n-input v-model:value="infoFilter.keyword" clearable placeholder="">
<template #prefix> <template #prefix>
<icon-button :icon="Filter" size="18" /> <icon-button :icon="Filter" size="18" />
</template> </template>
@ -474,46 +492,6 @@ const byteChartOption = {
</div> </div>
</template> </template>
<!-- environment tab pane -->
<n-tab-pane :tab="$t('status.env_info')" name="info">
<n-space :wrap="false" :wrap-item="false" class="flex-item-expand">
<n-space align="end" item-style="padding: 0 5px;" vertical>
<n-button
v-for="(v, k) in serverInfo"
:key="k"
:disabled="isEmpty(v)"
:focusable="false"
:type="envFilter.group === k ? 'primary' : 'default'"
secondary
size="small"
@click="onFilterGroup(k)">
<span style="min-width: 80px">{{ k }}</span>
</n-button>
</n-space>
<n-data-table
:columns="[
{
title: $t('common.key'),
key: 'key',
defaultSortOrder: 'ascend',
minWidth: 80,
titleAlign: 'center',
filterOptionValue: envFilter.keyword,
filter(value, row) {
return !!~row.key.indexOf(value.toString())
},
},
{ title: $t('common.value'), titleAlign: 'center', key: 'value' },
]"
:data="env"
:loading="pageState.loading"
:single-line="false"
class="flex-item-expand"
flex-height
striped />
</n-space>
</n-tab-pane>
<!-- activity tab pane --> <!-- activity tab pane -->
<n-tab-pane <n-tab-pane
:tab="$t('status.activity_status')" :tab="$t('status.activity_status')"
@ -535,6 +513,46 @@ const byteChartOption = {
</div> </div>
</div> </div>
</n-tab-pane> </n-tab-pane>
<!-- info tab pane -->
<n-tab-pane :tab="$t('status.server_info')" name="info">
<n-space :wrap="false" :wrap-item="false" class="flex-item-expand">
<n-space align="end" item-style="padding: 0 5px;" vertical>
<n-button
v-for="(v, k) in serverInfo"
:key="k"
:disabled="isEmpty(v)"
:focusable="false"
:type="infoFilter.group === k ? 'primary' : 'default'"
secondary
size="small"
@click="onFilterGroup(k)">
<span style="min-width: 80px">{{ k }}</span>
</n-button>
</n-space>
<n-data-table
:columns="[
{
title: $t('common.key'),
key: 'key',
defaultSortOrder: 'ascend',
minWidth: 80,
titleAlign: 'center',
filterOptionValue: infoFilter.keyword,
filter(value, row) {
return !!~row.key.indexOf(value.toString())
},
},
{ title: $t('common.value'), titleAlign: 'center', key: 'value' },
]"
:data="info"
:loading="pageState.loading"
:single-line="false"
class="flex-item-expand"
flex-height
striped />
</n-space>
</n-tab-pane>
</n-tabs> </n-tabs>
</n-card> </n-card>
</n-space> </n-space>

View File

@ -359,8 +359,7 @@
"connected_clients": "Clients", "connected_clients": "Clients",
"total_keys": "Keys", "total_keys": "Keys",
"memory_used": "Memory", "memory_used": "Memory",
"all_info": "Information", "server_info": "Server Info",
"env_info": "Environment",
"activity_status": "Activity", "activity_status": "Activity",
"act_cmd": "Commands Per Second", "act_cmd": "Commands Per Second",
"act_network_input": "Network Input", "act_network_input": "Network Input",

View File

@ -359,8 +359,7 @@
"connected_clients": "已连客户端", "connected_clients": "已连客户端",
"total_keys": "键总数", "total_keys": "键总数",
"memory_used": "内存使用", "memory_used": "内存使用",
"all_info": "全部信息", "server_info": "状态信息",
"env_info": "运行环境",
"activity_status": "活动状态", "activity_status": "活动状态",
"act_cmd": "命令执行数/秒", "act_cmd": "命令执行数/秒",
"act_network_input": "网络输入", "act_network_input": "网络输入",

View File

@ -9,6 +9,7 @@ import {
RenameGroup, RenameGroup,
SaveConnection, SaveConnection,
SaveLastDB, SaveLastDB,
SaveRefreshInterval,
SaveSortedConnection, SaveSortedConnection,
} from 'wailsjs/go/services/connectionService.js' } from 'wailsjs/go/services/connectionService.js'
import { ConnectionType } from '@/consts/connection_type.js' import { ConnectionType } from '@/consts/connection_type.js'
@ -31,6 +32,7 @@ const useConnectionStore = defineStore('connections', {
* @property {string} defaultFilter * @property {string} defaultFilter
* @property {string} keySeparator * @property {string} keySeparator
* @property {string} markColor * @property {string} markColor
* @property {number} refreshInterval
*/ */
/** /**
@ -63,7 +65,7 @@ const useConnectionStore = defineStore('connections', {
const conns = [] const conns = []
const groups = [] const groups = []
const profiles = {} const profiles = {}
const { data = [{ groupName: '', connections: [] }] } = await ListConnection() const { data = [{ groupName: '', connections: [], refreshInterval: 5 }] } = await ListConnection()
for (const conn of data) { for (const conn of data) {
if (conn.type !== 'group') { if (conn.type !== 'group') {
// top level // top level
@ -79,6 +81,7 @@ const useConnectionStore = defineStore('connections', {
defaultFilter: conn.defaultFilter, defaultFilter: conn.defaultFilter,
keySeparator: conn.keySeparator, keySeparator: conn.keySeparator,
markColor: conn.markColor, markColor: conn.markColor,
refreshInterval: conn.refreshInterval,
} }
} else { } else {
// custom group // custom group
@ -99,6 +102,7 @@ const useConnectionStore = defineStore('connections', {
defaultFilter: item.defaultFilter, defaultFilter: item.defaultFilter,
keySeparator: item.keySeparator, keySeparator: item.keySeparator,
markColor: item.markColor, markColor: item.markColor,
refreshInterval: conn.refreshInterval,
} }
} }
conns.push({ conns.push({
@ -369,6 +373,32 @@ const useConnectionStore = defineStore('connections', {
const { keySeparator = ':' } = this.serverProfile[name] || {} const { keySeparator = ':' } = this.serverProfile[name] || {}
return keySeparator return keySeparator
}, },
/**
* get default status refresh interval by server name
* @param {string} name
* @return {number}
*/
getRefreshInterval(name) {
const { refreshInterval = 5 } = this.serverProfile[name] || {}
return refreshInterval
},
/**
* set and save default refresh interval
* @param {string} name
* @param {number} interval
* @return {Promise<{success: boolean}|{msg: undefined, success: boolean}>}
*/
async saveRefreshInterval(name, interval) {
const profile = this.serverProfile[name] || {}
profile.refreshInterval = interval
const { success, msg } = await SaveRefreshInterval(name, interval)
if (!success) {
return { success: false, msg }
}
return { success: true }
},
}, },
}) })

View File

@ -277,10 +277,6 @@ const usePreferencesStore = defineStore('preferences', {
return false return false
}, },
setAsideWidth(width) {
this.behavior.asideWidth = Math.max(width, 300)
},
async checkForUpdate(manual = false) { async checkForUpdate(manual = false) {
let msgRef = null let msgRef = null
if (manual) { if (manual) {

View File

@ -71,6 +71,9 @@ export const themeOverrides = {
optionTextColorHover: '#FFF', optionTextColorHover: '#FFF',
optionHeightMedium: '28px', optionHeightMedium: '28px',
}, },
Divider: {
color: '#AAAAAB',
},
} }
/** /**