From baba6a46a485f0e40c1f8aae7c1f4d9685f2a236 Mon Sep 17 00:00:00 2001 From: Alf Eaton Date: Wed, 19 Feb 2025 09:32:23 +0000 Subject: [PATCH] Use refs and timeout for editor heartbeat events (#23340) GitOrigin-RevId: 4eb7697fb40c9aaf523765c256c870a21afb0844 --- .../hooks/use-editing-session-heartbeat.ts | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts b/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts index a30b1790ae..d264766d76 100644 --- a/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts +++ b/services/web/frontend/js/features/ide-react/hooks/use-editing-session-heartbeat.ts @@ -3,8 +3,7 @@ import { useEditorManagerContext } from '@/features/ide-react/context/editor-man import { EditorType } from '@/features/ide-react/editor/types/editor-type' import { putJSON } from '@/infrastructure/fetch-json' import { debugConsole } from '@/utils/debugging' -import moment from 'moment' -import { useCallback, useState } from 'react' +import { useCallback, useEffect, useRef } from 'react' import useEventListener from '@/shared/hooks/use-event-listener' import useDomEventListener from '@/shared/hooks/use-dom-event-listener' @@ -28,9 +27,18 @@ export function useEditingSessionHeartbeat() { const { getEditorType } = useEditorManagerContext() // Keep track of how many heartbeats we've sent so that we can calculate how - // long wait until the next one - const [heartbeatsSent, setHeartbeatsSent] = useState(0) - const [nextHeartbeatAt, setNextHeartbeatAt] = useState(() => new Date()) + // long to wait until the next one + const heartBeatsSentRef = useRef(0) + + const heartBeatSentRecentlyRef = useRef(false) + + const heartBeatResetTimerRef = useRef() + + useEffect(() => { + return () => { + window.clearTimeout(heartBeatResetTimerRef.current) + } + }, []) const editingSessionHeartbeat = useCallback(() => { debugConsole.log('[Event] heartbeat trigger') @@ -38,15 +46,18 @@ export function useEditingSessionHeartbeat() { const editorType = getEditorType() if (editorType === null) return - // If the next heartbeat is in the future, stop - if (nextHeartbeatAt > new Date()) return + // Heartbeat already sent recently + if (heartBeatSentRecentlyRef.current) return + + heartBeatSentRecentlyRef.current = true const segmentation = createEditingSessionHeartbeatData(editorType) debugConsole.log('[Event] send heartbeat request', segmentation) sendEditingSessionHeartbeat(projectId, segmentation) - setHeartbeatsSent(heartbeatsSent => heartbeatsSent + 1) + const heartbeatsSent = heartBeatsSentRef.current + heartBeatsSentRef.current++ // Send two first heartbeats at 0 and 30s then increase the backoff time // 1min per call until we reach 5 min @@ -57,8 +68,10 @@ export function useEditingSessionHeartbeat() { ? (heartbeatsSent - 2) * 60 : 300 - setNextHeartbeatAt(moment().add(backoffSecs, 'seconds').toDate()) - }, [getEditorType, heartbeatsSent, nextHeartbeatAt, projectId]) + heartBeatResetTimerRef.current = window.setTimeout(() => { + heartBeatSentRecentlyRef.current = false + }, backoffSecs * 1000) + }, [getEditorType, projectId]) // Hook the heartbeat up to editor events useEventListener('cursor:editor:update', editingSessionHeartbeat)