mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 02:15:48 +02:00
feat(index-status): add composable for monitoring cache index status using SSE
This commit is contained in:
parent
d815e292db
commit
2d3a5e2a16
8 changed files with 75 additions and 107 deletions
49
app/src/composables/useIndexStatus.ts
Normal file
49
app/src/composables/useIndexStatus.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import cacheIndex from '@/api/cache_index'
|
||||
import { SSE } from 'sse.js'
|
||||
import { useSSE } from './useSSE'
|
||||
|
||||
/**
|
||||
* Composable for monitoring cache index status
|
||||
* Provides a way to track indexing/scanning status through SSE
|
||||
*/
|
||||
|
||||
export interface IndexStatus {
|
||||
isScanning: Ref<boolean>
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup SSE connection to monitor indexing status
|
||||
*/
|
||||
export function setupIndexStatus() {
|
||||
const { connect, disconnect, sseInstance } = useSSE()
|
||||
|
||||
const isScanning = ref(false)
|
||||
|
||||
disconnect()
|
||||
|
||||
const sse = cacheIndex.index_status()
|
||||
|
||||
if (sse instanceof SSE) {
|
||||
connect({
|
||||
url: '', // Not needed as we already have the SSE instance
|
||||
token: '', // Not needed as we already have the SSE instance
|
||||
onMessage: data => {
|
||||
isScanning.value = data.scanning
|
||||
},
|
||||
onError: () => {
|
||||
// Reconnection is handled by useSSE
|
||||
},
|
||||
})
|
||||
|
||||
// Manually assign the SSE instance since we're using a pre-created one
|
||||
sseInstance.value = sse
|
||||
}
|
||||
|
||||
provide('indexStatus', {
|
||||
isScanning,
|
||||
})
|
||||
}
|
||||
|
||||
export function useIndexStatus(): IndexStatus {
|
||||
return inject<IndexStatus>('indexStatus')!
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
import type { NginxPerformanceInfo } from '@/api/ngx'
|
||||
import type { Ref } from 'vue'
|
||||
import { computed } from 'vue'
|
||||
|
||||
export function usePerformanceMetrics(nginxInfo: Ref<NginxPerformanceInfo | undefined>) {
|
||||
// Format numbers to a more readable form
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import type { SSEvent } from 'sse.js'
|
||||
import { SSE } from 'sse.js'
|
||||
import { onUnmounted, shallowRef } from 'vue'
|
||||
|
||||
export interface SSEOptions {
|
||||
url: string
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import settings from '@/api/settings'
|
||||
import PageHeader from '@/components/PageHeader/PageHeader.vue'
|
||||
import { setupIndexStatus } from '@/composables/useIndexStatus'
|
||||
import { useSettingsStore } from '@/pinia'
|
||||
import _ from 'lodash'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
@ -41,6 +42,8 @@ settings.get_server_name().then(r => {
|
|||
server_name.value = r.name
|
||||
})
|
||||
|
||||
setupIndexStatus()
|
||||
|
||||
const breadList = ref([])
|
||||
|
||||
provide('breadList', breadList)
|
||||
|
|
|
@ -88,7 +88,7 @@ function handleCancel() {
|
|||
</AButton>
|
||||
|
||||
<AModal
|
||||
v-model:visible="modalVisible"
|
||||
v-model:open="modalVisible"
|
||||
:title="$gettext('Delete Certificate')"
|
||||
:confirm-loading="confirmLoading"
|
||||
:ok-button-props="{
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
<script setup lang="tsx">
|
||||
import type { CustomRender } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { SSE, SSEvent } from 'sse.js'
|
||||
import cacheIndex from '@/api/cache_index'
|
||||
import nginxLog from '@/api/nginx_log'
|
||||
import StdCurd from '@/components/StdDesign/StdDataDisplay/StdCurd.vue'
|
||||
import { input, select } from '@/components/StdDesign/StdDataEntry'
|
||||
import { useIndexStatus } from '@/composables/useIndexStatus'
|
||||
import { CheckCircleOutlined, LoadingOutlined } from '@ant-design/icons-vue'
|
||||
import { Tag } from 'ant-design-vue'
|
||||
import { onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter()
|
||||
const isScanning = ref(false)
|
||||
const { isScanning } = useIndexStatus()
|
||||
const stdCurdRef = ref()
|
||||
const sse = ref<SSE>()
|
||||
|
||||
const columns: Column[] = [
|
||||
{
|
||||
|
@ -63,50 +59,6 @@ function viewLog(record: { type: string, path: string }) {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
// Connect to SSE endpoint and setup handlers
|
||||
async function setupSSE() {
|
||||
if (sse.value) {
|
||||
sse.value.close()
|
||||
}
|
||||
|
||||
sse.value = cacheIndex.index_status()
|
||||
|
||||
// Handle incoming messages
|
||||
if (sse.value) {
|
||||
sse.value.onmessage = (e: SSEvent) => {
|
||||
try {
|
||||
if (!e.data)
|
||||
return
|
||||
|
||||
const data = JSON.parse(e.data)
|
||||
isScanning.value = data.scanning
|
||||
|
||||
stdCurdRef.value.get_list()
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error parsing SSE message:', error)
|
||||
}
|
||||
}
|
||||
|
||||
sse.value.onerror = () => {
|
||||
// Reconnect on error
|
||||
setTimeout(() => {
|
||||
setupSSE()
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setupSSE()
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (sse.value) {
|
||||
sse.value.close()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
import type { EnvGroup } from '@/api/env_group'
|
||||
import type { Site } from '@/api/site'
|
||||
import type { Column } from '@/components/StdDesign/types'
|
||||
import type { SSE, SSEvent } from 'sse.js'
|
||||
import cacheIndex from '@/api/cache_index'
|
||||
import env_group from '@/api/env_group'
|
||||
import site from '@/api/site'
|
||||
import EnvGroupTabs from '@/components/EnvGroupTabs/EnvGroupTabs.vue'
|
||||
import StdBatchEdit from '@/components/StdDesign/StdDataDisplay/StdBatchEdit.vue'
|
||||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import { useIndexStatus } from '@/composables/useIndexStatus'
|
||||
import { ConfigStatus } from '@/constants'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import columns from '@/views/site/site_list/columns'
|
||||
|
@ -20,15 +19,15 @@ const route = useRoute()
|
|||
const router = useRouter()
|
||||
|
||||
const table = ref()
|
||||
const inspect_config = ref()
|
||||
const inspectConfig = ref()
|
||||
|
||||
const envGroupId = ref(Number.parseInt(route.query.env_group_id as string) || 0)
|
||||
const envGroups = ref([]) as Ref<EnvGroup[]>
|
||||
const isScanning = ref(false)
|
||||
const sse = ref<SSE>()
|
||||
|
||||
const { isScanning } = useIndexStatus()
|
||||
|
||||
watch(route, () => {
|
||||
inspect_config.value?.test()
|
||||
inspectConfig.value?.test()
|
||||
})
|
||||
|
||||
onMounted(async () => {
|
||||
|
@ -48,55 +47,11 @@ onMounted(async () => {
|
|||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
setupSSE()
|
||||
})
|
||||
|
||||
// Connect to SSE endpoint and setup handlers
|
||||
async function setupSSE() {
|
||||
if (sse.value) {
|
||||
sse.value.close()
|
||||
}
|
||||
|
||||
sse.value = cacheIndex.index_status()
|
||||
|
||||
// Handle incoming messages
|
||||
if (sse.value) {
|
||||
sse.value.onmessage = (e: SSEvent) => {
|
||||
try {
|
||||
if (!e.data)
|
||||
return
|
||||
|
||||
const data = JSON.parse(e.data)
|
||||
isScanning.value = data.scanning
|
||||
|
||||
table.value.get_list()
|
||||
}
|
||||
catch (error) {
|
||||
console.error('Error parsing SSE message:', error)
|
||||
}
|
||||
}
|
||||
|
||||
sse.value.onerror = () => {
|
||||
// Reconnect on error
|
||||
setTimeout(() => {
|
||||
setupSSE()
|
||||
}, 5000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
if (sse.value) {
|
||||
sse.value.close()
|
||||
}
|
||||
})
|
||||
|
||||
function destroy(site_name: string) {
|
||||
site.destroy(site_name).then(() => {
|
||||
table.value.get_list()
|
||||
message.success($gettext('Delete site: %{site_name}', { site_name }))
|
||||
inspect_config.value?.test()
|
||||
inspectConfig.value?.test()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -133,7 +88,7 @@ function handleBatchUpdated() {
|
|||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<InspectConfig ref="inspect_config" />
|
||||
<InspectConfig ref="inspectConfig" />
|
||||
|
||||
<EnvGroupTabs v-model:active-key="envGroupId" :env-groups="envGroups" />
|
||||
|
||||
|
|
|
@ -10,10 +10,12 @@ import StdBatchEdit from '@/components/StdDesign/StdDataDisplay/StdBatchEdit.vue
|
|||
import StdTable from '@/components/StdDesign/StdDataDisplay/StdTable.vue'
|
||||
import { actualValueRender, datetime } from '@/components/StdDesign/StdDataDisplay/StdTableTransformer'
|
||||
import { input, selector } from '@/components/StdDesign/StdDataEntry'
|
||||
import { useIndexStatus } from '@/composables/useIndexStatus'
|
||||
import { ConfigStatus } from '@/constants'
|
||||
import InspectConfig from '@/views/config/InspectConfig.vue'
|
||||
import envGroupColumns from '@/views/environments/group/columns'
|
||||
import StreamDuplicate from '@/views/stream/components/StreamDuplicate.vue'
|
||||
import { CheckCircleOutlined, LoadingOutlined } from '@ant-design/icons-vue'
|
||||
import { Badge, message } from 'ant-design-vue'
|
||||
|
||||
const columns: Column[] = [{
|
||||
|
@ -169,12 +171,22 @@ function handleBatchUpdated() {
|
|||
table.value?.get_list()
|
||||
table.value?.resetSelection()
|
||||
}
|
||||
|
||||
const { isScanning } = useIndexStatus()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ACard :title="$gettext('Manage Streams')">
|
||||
<template #extra>
|
||||
<a @click="add">{{ $gettext('Add') }}</a>
|
||||
<div class="flex items-center cursor-default">
|
||||
<a class="mr-4" @click="add">{{ $gettext('Add') }}</a>
|
||||
<template v-if="isScanning">
|
||||
<LoadingOutlined class="mr-2" spin />{{ $gettext('Indexing...') }}
|
||||
</template>
|
||||
<template v-else>
|
||||
<CheckCircleOutlined class="mr-2" />{{ $gettext('Indexed') }}
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<InspectConfig ref="inspect_config" />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue