Browse Source

chore: replace all set interval (#3411)

Joel 1 year ago
parent
commit
4d54637921

+ 6 - 6
web/app/components/base/auto-height-textarea/index.tsx

@@ -1,5 +1,6 @@
 import { forwardRef, useEffect, useRef } from 'react'
 import cn from 'classnames'
+import { sleep } from '@/utils'
 
 type IProps = {
   placeholder?: string
@@ -32,14 +33,13 @@ const AutoHeightTextarea = forwardRef(
       return false
     }
 
-    const focus = () => {
+    const focus = async () => {
       if (!doFocus()) {
         let hasFocus = false
-        const runId = setInterval(() => {
-          hasFocus = doFocus()
-          if (hasFocus)
-            clearInterval(runId)
-        }, 100)
+        await sleep(100)
+        hasFocus = doFocus()
+        if (!hasFocus)
+          focus()
       }
     }
 

+ 23 - 19
web/app/components/datasets/create/embedding-process/index.tsx

@@ -21,6 +21,7 @@ import UpgradeBtn from '@/app/components/billing/upgrade-btn'
 import { useProviderContext } from '@/context/provider-context'
 import TooltipPlus from '@/app/components/base/tooltip-plus'
 import { AlertCircle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
+import { sleep } from '@/utils'
 
 type Props = {
   datasetId: string
@@ -95,38 +96,41 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
     return status.data
   }
 
-  // const [_, setRunId, getRunId] = useGetState<ReturnType<typeof setInterval>>()
-  const [runId, setRunId] = useState<ReturnType<typeof setInterval>>()
-  const runIdRef = useRef(runId)
-  const getRunId = () => runIdRef.current
+  const [isStopQuery, setIsStopQuery] = useState(false)
+  const isStopQueryRef = useRef(isStopQuery)
   useEffect(() => {
-    runIdRef.current = runId
-  }, [runId])
+    isStopQueryRef.current = isStopQuery
+  }, [isStopQuery])
   const stopQueryStatus = () => {
-    clearInterval(getRunId())
-    setRunId(undefined)
+    setIsStopQuery(true)
   }
 
-  const startQueryStatus = () => {
-    const runId = setInterval(async () => {
-      // It's so strange that the interval can't be cleared after the clearInterval called. And the runId is current.
-      if (!getRunId())
-        return
+  const startQueryStatus = async () => {
+    if (isStopQueryRef.current)
+      return
 
+    try {
       const indexingStatusBatchDetail = await fetchIndexingStatus()
-      const isCompleted = indexingStatusBatchDetail.every(indexingStatusDetail => ['completed', 'error'].includes(indexingStatusDetail.indexing_status))
-      if (isCompleted)
+      const isCompleted = indexingStatusBatchDetail.every(indexingStatusDetail => ['completed', 'error', 'paused'].includes(indexingStatusDetail.indexing_status))
+      if (isCompleted) {
         stopQueryStatus()
-    }, 2500)
-    setRunId(runId)
+        return
+      }
+      await sleep(2500)
+      await startQueryStatus()
+    }
+    catch (e) {
+      await sleep(2500)
+      await startQueryStatus()
+    }
   }
 
   useEffect(() => {
-    fetchIndexingStatus()
     startQueryStatus()
     return () => {
       stopQueryStatus()
     }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [])
 
   // get rule
@@ -154,7 +158,7 @@ const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], index
     return indexingStatusBatchDetail.some(indexingStatusDetail => ['indexing', 'splitting', 'parsing', 'cleaning'].includes(indexingStatusDetail?.indexing_status || ''))
   }, [indexingStatusBatchDetail])
   const isEmbeddingCompleted = useMemo(() => {
-    return indexingStatusBatchDetail.every(indexingStatusDetail => ['completed', 'error'].includes(indexingStatusDetail?.indexing_status || ''))
+    return indexingStatusBatchDetail.every(indexingStatusDetail => ['completed', 'error', 'paused'].includes(indexingStatusDetail?.indexing_status || ''))
   }, [indexingStatusBatchDetail])
 
   const getSourceName = (id: string) => {

+ 30 - 27
web/app/components/datasets/documents/detail/embedding/index.tsx

@@ -1,12 +1,11 @@
 import type { FC, SVGProps } from 'react'
-import React, { useCallback, useEffect, useMemo, useState } from 'react'
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
 import useSWR from 'swr'
 import { useRouter } from 'next/navigation'
 import { useContext } from 'use-context-selector'
 import { useTranslation } from 'react-i18next'
 import { omit } from 'lodash-es'
 import { ArrowRightIcon } from '@heroicons/react/24/solid'
-import { useGetState } from 'ahooks'
 import cn from 'classnames'
 import SegmentCard from '../completed/SegmentCard'
 import { FieldInfo } from '../metadata'
@@ -18,7 +17,7 @@ import Divider from '@/app/components/base/divider'
 import { ToastContext } from '@/app/components/base/toast'
 import type { FullDocumentDetail, ProcessRuleResponse } from '@/models/datasets'
 import type { CommonResponse } from '@/models/common'
-import { asyncRunSafe } from '@/utils'
+import { asyncRunSafe, sleep } from '@/utils'
 import { formatNumber } from '@/utils/format'
 import { fetchIndexingStatus as doFetchIndexingStatus, fetchIndexingEstimate, fetchProcessRule, pauseDocIndexing, resumeDocIndexing } from '@/service/datasets'
 import DatasetDetailContext from '@/context/dataset-detail'
@@ -120,45 +119,49 @@ const EmbeddingDetail: FC<Props> = ({ detail, stopPosition = 'top', datasetId: d
   const localDocumentId = docId ?? documentId
   const localIndexingTechnique = indexingType ?? indexingTechnique
 
-  const [indexingStatusDetail, setIndexingStatusDetail, getIndexingStatusDetail] = useGetState<any>(null)
+  const [indexingStatusDetail, setIndexingStatusDetail] = useState<any>(null)
   const fetchIndexingStatus = async () => {
-    try {
-      const status = await doFetchIndexingStatus({ datasetId: localDatasetId, documentId: localDocumentId })
-      setIndexingStatusDetail(status)
-      // eslint-disable-next-line @typescript-eslint/no-use-before-define
-      startQueryStatus()
-    }
-    catch (err) {
-      // eslint-disable-next-line @typescript-eslint/no-use-before-define
-      stopQueryStatus()
-      notify({ type: 'error', message: `error: ${err}` })
-    }
+    const status = await doFetchIndexingStatus({ datasetId: localDatasetId, documentId: localDocumentId })
+    setIndexingStatusDetail(status)
+    return status
   }
 
-  const [runId, setRunId, getRunId] = useGetState<any>(null)
-
+  const [isStopQuery, setIsStopQuery] = useState(false)
+  const isStopQueryRef = useRef(isStopQuery)
+  useEffect(() => {
+    isStopQueryRef.current = isStopQuery
+  }, [isStopQuery])
   const stopQueryStatus = () => {
-    clearInterval(getRunId())
+    setIsStopQuery(true)
   }
 
-  const startQueryStatus = () => {
-    const runId = setInterval(() => {
-      const indexingStatusDetail = getIndexingStatusDetail()
-      if (indexingStatusDetail?.indexing_status === 'completed') {
+  const startQueryStatus = async () => {
+    if (isStopQueryRef.current)
+      return
+
+    try {
+      const indexingStatusDetail = await fetchIndexingStatus()
+      if (['completed', 'error', 'paused'].includes(indexingStatusDetail?.indexing_status)) {
         stopQueryStatus()
         detailUpdate()
         return
       }
-      fetchIndexingStatus()
-    }, 2500)
-    setRunId(runId)
+      await sleep(2500)
+      await startQueryStatus()
+    }
+    catch (e) {
+      await sleep(2500)
+      await startQueryStatus()
+    }
   }
 
   useEffect(() => {
-    fetchIndexingStatus()
+    setIsStopQuery(false)
+    startQueryStatus()
     return () => {
       stopQueryStatus()
     }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [])
 
   const { data: indexingEstimateDetail, error: indexingEstimateErr } = useSWR({
@@ -300,4 +303,4 @@ const EmbeddingDetail: FC<Props> = ({ detail, stopPosition = 'top', datasetId: d
   )
 }
 
-export default EmbeddingDetail
+export default React.memo(EmbeddingDetail)

+ 11 - 10
web/app/components/share/text-generation/result/index.tsx

@@ -17,6 +17,7 @@ import type { ModerationService } from '@/models/common'
 import { TransferMethod, type VisionFile, type VisionSettings } from '@/types/app'
 import { NodeRunningStatus, WorkflowRunningStatus } from '@/app/components/workflow/types'
 import type { WorkflowProcess } from '@/app/components/base/chat/types'
+import { sleep } from '@/utils'
 
 export type IResultProps = {
   isWorkflow: boolean
@@ -179,16 +180,16 @@ const Result: FC<IResultProps> = ({
       onShowRes()
 
     setRespondingTrue()
-    const startTime = Date.now()
-    let isTimeout = false
-    const runId = setInterval(() => {
-      if (Date.now() - startTime > 1000 * 60) { // 1min timeout
-        clearInterval(runId)
+    let isEnd = false
+    let isTimeout = false;
+    (async () => {
+      await sleep(1000 * 60) // 1min timeout
+      if (!isEnd) {
         setRespondingFalse()
         onCompleted(getCompletionRes(), taskId, false)
         isTimeout = true
       }
-    }, 1000)
+    })()
 
     if (isWorkflow) {
       sendWorkflowMessage(
@@ -234,7 +235,7 @@ const Result: FC<IResultProps> = ({
               notify({ type: 'error', message: data.error })
               setRespondingFalse()
               onCompleted(getCompletionRes(), taskId, false)
-              clearInterval(runId)
+              isEnd = true
               return
             }
             setWorkflowProccessData(produce(getWorkflowProccessData()!, (draft) => {
@@ -249,7 +250,7 @@ const Result: FC<IResultProps> = ({
             setRespondingFalse()
             setMessageId(tempMessageId)
             onCompleted(getCompletionRes(), taskId, true)
-            clearInterval(runId)
+            isEnd = true
           },
         },
         isInstalledApp,
@@ -269,7 +270,7 @@ const Result: FC<IResultProps> = ({
           setRespondingFalse()
           setMessageId(tempMessageId)
           onCompleted(getCompletionRes(), taskId, true)
-          clearInterval(runId)
+          isEnd = true
         },
         onMessageReplace: (messageReplace) => {
           res = [messageReplace.answer]
@@ -280,7 +281,7 @@ const Result: FC<IResultProps> = ({
             return
           setRespondingFalse()
           onCompleted(getCompletionRes(), taskId, false)
-          clearInterval(runId)
+          isEnd = true
         },
       }, isInstalledApp, installedAppInfo?.id)
     }