Browse Source

feat(nginx): status monitoring via ws

Jacky 2 days ago
parent
commit
d6c29a6429
2 changed files with 45 additions and 152 deletions
  1. 0 126
      app/src/composables/useNginxWebSocket.ts
  2. 45 26
      app/src/views/dashboard/NginxDashBoard.vue

+ 0 - 126
app/src/composables/useNginxWebSocket.ts

@@ -1,126 +0,0 @@
-import ws from '@/lib/websocket'
-import type ReconnectingWebSocket from 'reconnecting-websocket'
-
-export interface NginxWebSocketOptions {
-  url: string
-  onMessage?: (data: any) => void
-  onError?: () => void
-  reconnectInterval?: number
-}
-
-/**
- * Nginx WebSocket Composable
- * Provide the ability to create, manage, and automatically clean up WebSocket connections for Nginx performance monitoring
- */
-export function useNginxWebSocket() {
-  const wsInstance = shallowRef<ReconnectingWebSocket | WebSocket>()
-  const isConnected = ref(false)
-  const isReconnecting = ref(false)
-  const currentOptions = shallowRef<NginxWebSocketOptions>()
-
-  /**
-   * Connect to WebSocket service
-   */
-  function connect(options: NginxWebSocketOptions) {
-    const {
-      url,
-      onMessage,
-      onError,
-    } = options
-
-    // Store current options for reconnection
-    currentOptions.value = options
-
-    // Disconnect existing connection before creating new one
-    if (wsInstance.value) {
-      disconnect()
-    }
-
-    try {
-      const wsConnection = ws(url, true) as ReconnectingWebSocket
-
-      // Handle connection open
-      wsConnection.onopen = () => {
-        isConnected.value = true
-        isReconnecting.value = false
-        console.log('WebSocket connected')
-      }
-
-      // Handle messages
-      wsConnection.onmessage = (event) => {
-        if (!event.data) {
-          return
-        }
-
-        // Reset reconnecting state on successful message
-        isReconnecting.value = false
-
-        try {
-          const parsedData = JSON.parse(event.data)
-          onMessage?.(parsedData)
-        }
-        catch (error) {
-          console.error('Error parsing WebSocket message:', error)
-        }
-      }
-
-      // Handle errors and connection close
-      wsConnection.onerror = (error) => {
-        console.error('WebSocket error:', error)
-        isConnected.value = false
-        isReconnecting.value = true
-        onError?.()
-      }
-
-      wsConnection.onclose = () => {
-        isConnected.value = false
-        console.log('WebSocket disconnected')
-      }
-
-      wsInstance.value = wsConnection
-      return wsConnection
-    }
-    catch (error) {
-      console.error('Failed to create WebSocket connection:', error)
-      onError?.()
-    }
-  }
-
-  /**
-   * Disconnect WebSocket connection
-   */
-  function disconnect() {
-    if (wsInstance.value) {
-      wsInstance.value.close()
-      wsInstance.value = undefined
-    }
-    isConnected.value = false
-    isReconnecting.value = false
-    currentOptions.value = undefined
-  }
-
-  /**
-   * Send message to WebSocket
-   */
-  function send(data: any) {
-    if (wsInstance.value && isConnected.value) {
-      wsInstance.value.send(JSON.stringify(data))
-    }
-  }
-
-  // Automatically disconnect when the component is unmounted
-  if (getCurrentInstance()) {
-    onUnmounted(() => {
-      disconnect()
-    })
-  }
-
-  return {
-    connect,
-    disconnect,
-    send,
-    wsInstance,
-    isConnected: readonly(isConnected),
-    isReconnecting: readonly(isReconnecting),
-  }
-} 

+ 45 - 26
app/src/views/dashboard/NginxDashBoard.vue

@@ -1,10 +1,11 @@
 <script setup lang="ts">
 <script setup lang="ts">
+import type ReconnectingWebSocket from 'reconnecting-websocket'
 import { ClockCircleOutlined, ReloadOutlined } from '@ant-design/icons-vue'
 import { ClockCircleOutlined, ReloadOutlined } from '@ant-design/icons-vue'
 import { storeToRefs } from 'pinia'
 import { storeToRefs } from 'pinia'
 import ngx from '@/api/ngx'
 import ngx from '@/api/ngx'
 import { useNginxPerformance } from '@/composables/useNginxPerformance'
 import { useNginxPerformance } from '@/composables/useNginxPerformance'
-import { useNginxWebSocket } from '@/composables/useNginxWebSocket'
 import { NginxStatus } from '@/constants'
 import { NginxStatus } from '@/constants'
+import ws from '@/lib/websocket'
 import { useGlobalStore } from '@/pinia'
 import { useGlobalStore } from '@/pinia'
 import ConnectionMetricsCard from './components/ConnectionMetricsCard.vue'
 import ConnectionMetricsCard from './components/ConnectionMetricsCard.vue'
 import ParamsOptimization from './components/ParamsOptimization.vue'
 import ParamsOptimization from './components/ParamsOptimization.vue'
@@ -31,7 +32,7 @@ const {
 } = useNginxPerformance()
 } = useNginxPerformance()
 
 
 // WebSocket connection
 // WebSocket connection
-const { connect, disconnect } = useNginxWebSocket()
+const wsInstance = shallowRef<WebSocket | ReconnectingWebSocket | null>(null)
 
 
 // Toggle stub_status module status
 // Toggle stub_status module status
 async function toggleStubStatus() {
 async function toggleStubStatus() {
@@ -62,37 +63,50 @@ async function toggleStubStatus() {
 
 
 // Connect WebSocket
 // Connect WebSocket
 function connectWebSocket() {
 function connectWebSocket() {
-  disconnect()
+  disconnectWebSocket()
   loading.value = true
   loading.value = true
 
 
-  connect({
-    url: 'api/nginx/detail_status/ws',
-    onMessage: data => {
+  try {
+    const wsConnection = ws('api/nginx/detail_status/ws')
+    wsInstance.value = wsConnection
+
+    wsConnection.onmessage = event => {
       loading.value = false
       loading.value = false
 
 
-      if (data.running) {
-        nginxInfo.value = data.info
-        updateLastUpdateTime()
-      }
-      else {
-        error.value = data.message || $gettext('Nginx is not running')
-      }
+      try {
+        const data = JSON.parse(event.data)
 
 
-      if (data.error) {
-        error.value = data.error
+        if (data.running) {
+          nginxInfo.value = data.info
+          updateLastUpdateTime()
+        }
+        else {
+          error.value = data.message || $gettext('Nginx is not running')
+        }
+
+        if (data.error) {
+          error.value = data.error
+        }
+
+        stubStatusEnabled.value = data.stub_status_enabled
       }
       }
+      catch (parseError) {
+        console.error('Error parsing WebSocket message:', parseError)
+      }
+    }
+  }
+  catch (err) {
+    console.error('Failed to create WebSocket connection:', err)
+    error.value = $gettext('Connection error, trying to reconnect...')
+  }
+}
 
 
-      stubStatusEnabled.value = data.stub_status_enabled
-    },
-    onError: () => {
-      error.value = $gettext('Connection error, trying to reconnect...')
-
-      // If the connection fails, try to get data using the traditional method
-      setTimeout(() => {
-        fetchInitialData()
-      }, 2000)
-    },
-  })
+// Disconnect WebSocket
+function disconnectWebSocket() {
+  if (wsInstance.value) {
+    wsInstance.value.close()
+    wsInstance.value = null
+  }
 }
 }
 
 
 // Manually refresh data
 // Manually refresh data
@@ -104,6 +118,11 @@ function refreshData() {
 onMounted(() => {
 onMounted(() => {
   fetchInitialData().then(connectWebSocket)
   fetchInitialData().then(connectWebSocket)
 })
 })
+
+// Clean up WebSocket connection when component is unmounted
+onUnmounted(() => {
+  disconnectWebSocket()
+})
 </script>
 </script>
 
 
 <template>
 <template>