yangdx commited on
Commit
3ab8571
·
1 Parent(s): f56f204

Fix duplicate api requuests for graph fetching

Browse files

- Optimize graph data fetching conditions
- Add isFetching state to prevent duplicate requests
- Improve label selection handling

lightrag/api/webui/assets/{index-B9TRs-Wk.js → index-fJflQM9b.js} RENAMED
Binary files a/lightrag/api/webui/assets/index-B9TRs-Wk.js and b/lightrag/api/webui/assets/index-fJflQM9b.js differ
 
lightrag/api/webui/index.html CHANGED
Binary files a/lightrag/api/webui/index.html and b/lightrag/api/webui/index.html differ
 
lightrag_webui/src/components/graph/GraphControl.tsx CHANGED
@@ -1,10 +1,11 @@
1
  import { useLoadGraph, useRegisterEvents, useSetSettings, useSigma } from '@react-sigma/core'
 
2
  // import { useLayoutCircular } from '@react-sigma/layout-circular'
3
  import { useLayoutForceAtlas2 } from '@react-sigma/layout-forceatlas2'
4
  import { useEffect } from 'react'
5
 
6
  // import useRandomGraph, { EdgeType, NodeType } from '@/hooks/useRandomGraph'
7
- import useLightragGraph, { EdgeType, NodeType } from '@/hooks/useLightragGraph'
8
  import useTheme from '@/hooks/useTheme'
9
  import * as Constants from '@/lib/constants'
10
 
@@ -21,7 +22,6 @@ const isButtonPressed = (ev: MouseEvent | TouchEvent) => {
21
  }
22
 
23
  const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean }) => {
24
- const { lightrageGraph } = useLightragGraph()
25
  const sigma = useSigma<NodeType, EdgeType>()
26
  const registerEvents = useRegisterEvents<NodeType, EdgeType>()
27
  const setSettings = useSetSettings<NodeType, EdgeType>()
@@ -38,17 +38,18 @@ const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean })
38
  const focusedNode = useGraphStore.use.focusedNode()
39
  const selectedEdge = useGraphStore.use.selectedEdge()
40
  const focusedEdge = useGraphStore.use.focusedEdge()
 
41
 
42
  /**
43
  * When component mount or maxIterations changes
44
  * => load the graph and apply layout
45
  */
46
  useEffect(() => {
47
- // Create & load the graph
48
- const graph = lightrageGraph()
49
- loadGraph(graph)
50
- assignLayout()
51
- }, [assignLayout, loadGraph, lightrageGraph, maxIterations])
52
 
53
  /**
54
  * When component mount
 
1
  import { useLoadGraph, useRegisterEvents, useSetSettings, useSigma } from '@react-sigma/core'
2
+ import Graph from 'graphology'
3
  // import { useLayoutCircular } from '@react-sigma/layout-circular'
4
  import { useLayoutForceAtlas2 } from '@react-sigma/layout-forceatlas2'
5
  import { useEffect } from 'react'
6
 
7
  // import useRandomGraph, { EdgeType, NodeType } from '@/hooks/useRandomGraph'
8
+ import { EdgeType, NodeType } from '@/hooks/useLightragGraph'
9
  import useTheme from '@/hooks/useTheme'
10
  import * as Constants from '@/lib/constants'
11
 
 
22
  }
23
 
24
  const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean }) => {
 
25
  const sigma = useSigma<NodeType, EdgeType>()
26
  const registerEvents = useRegisterEvents<NodeType, EdgeType>()
27
  const setSettings = useSetSettings<NodeType, EdgeType>()
 
38
  const focusedNode = useGraphStore.use.focusedNode()
39
  const selectedEdge = useGraphStore.use.selectedEdge()
40
  const focusedEdge = useGraphStore.use.focusedEdge()
41
+ const sigmaGraph = useGraphStore.use.sigmaGraph()
42
 
43
  /**
44
  * When component mount or maxIterations changes
45
  * => load the graph and apply layout
46
  */
47
  useEffect(() => {
48
+ if (sigmaGraph) {
49
+ loadGraph(sigmaGraph as unknown as Graph<NodeType, EdgeType>)
50
+ assignLayout()
51
+ }
52
+ }, [assignLayout, loadGraph, sigmaGraph, maxIterations])
53
 
54
  /**
55
  * When component mount
lightrag_webui/src/components/graph/GraphLabels.tsx CHANGED
@@ -57,8 +57,11 @@ const GraphLabels = () => {
57
 
58
  const currentLabel = useSettingsStore.getState().queryLabel
59
 
60
- // When selecting the same label (except '*'), switch to '*'
61
- if (newLabel === currentLabel && newLabel !== '*') {
 
 
 
62
  useSettingsStore.getState().setQueryLabel('*')
63
  } else {
64
  useSettingsStore.getState().setQueryLabel(newLabel)
 
57
 
58
  const currentLabel = useSettingsStore.getState().queryLabel
59
 
60
+ if (newLabel === '*' && currentLabel === '*') {
61
+ // When reselecting '*', just set it again to trigger a new fetch
62
+ useSettingsStore.getState().setQueryLabel('*')
63
+ } else if (newLabel === currentLabel && newLabel !== '*') {
64
+ // When selecting the same label (except '*'), switch to '*'
65
  useSettingsStore.getState().setQueryLabel('*')
66
  } else {
67
  useSettingsStore.getState().setQueryLabel(newLabel)
lightrag_webui/src/hooks/useLightragGraph.tsx CHANGED
@@ -162,13 +162,32 @@ const createSigmaGraph = (rawGraph: RawGraph | null) => {
162
  }
163
 
164
  const useLightrangeGraph = () => {
165
- // Use useRef to maintain lastQueryLabel state between renders
166
- const lastQueryLabelRef = useRef({ label: '', maxQueryDepth: 0, minDegree: 0 })
167
  const queryLabel = useSettingsStore.use.queryLabel()
168
  const rawGraph = useGraphStore.use.rawGraph()
169
  const sigmaGraph = useGraphStore.use.sigmaGraph()
170
  const maxQueryDepth = useSettingsStore.use.graphQueryMaxDepth()
171
  const minDegree = useSettingsStore.use.graphMinDegree()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
 
173
  const getNode = useCallback(
174
  (nodeId: string) => {
@@ -186,17 +205,12 @@ const useLightrangeGraph = () => {
186
 
187
  useEffect(() => {
188
  if (queryLabel) {
189
- // Always fetch data for "*" label
190
- // For other labels, only fetch when parameters change
191
- const shouldUpdate = true;
192
-
193
- if (shouldUpdate) {
194
- lastQueryLabelRef.current = {
195
- label: queryLabel,
196
- maxQueryDepth,
197
- minDegree
198
- }
199
-
200
  fetchGraph(queryLabel, maxQueryDepth, minDegree).then((data) => {
201
  const state = useGraphStore.getState()
202
  const newSigmaGraph = createSigmaGraph(data)
@@ -227,6 +241,16 @@ const useLightrangeGraph = () => {
227
  // Ensure * is there eventhough there is no graph data
228
  state.setGraphLabels(['*']);
229
  }
 
 
 
 
 
 
 
 
 
 
230
  })
231
  }
232
  } else {
 
162
  }
163
 
164
  const useLightrangeGraph = () => {
 
 
165
  const queryLabel = useSettingsStore.use.queryLabel()
166
  const rawGraph = useGraphStore.use.rawGraph()
167
  const sigmaGraph = useGraphStore.use.sigmaGraph()
168
  const maxQueryDepth = useSettingsStore.use.graphQueryMaxDepth()
169
  const minDegree = useSettingsStore.use.graphMinDegree()
170
+ const isFetching = useGraphStore.use.isFetching()
171
+
172
+ // Use ref to track fetch status
173
+ const fetchStatusRef = useRef<Record<string, boolean>>({});
174
+
175
+ // Track previous parameters to detect actual changes
176
+ const prevParamsRef = useRef({ queryLabel, maxQueryDepth, minDegree });
177
+
178
+ // Reset fetch status only when parameters actually change
179
+ useEffect(() => {
180
+ const prevParams = prevParamsRef.current;
181
+ if (prevParams.queryLabel !== queryLabel ||
182
+ prevParams.maxQueryDepth !== maxQueryDepth ||
183
+ prevParams.minDegree !== minDegree) {
184
+ useGraphStore.getState().setIsFetching(false);
185
+ // Reset fetch status for new parameters
186
+ fetchStatusRef.current = {};
187
+ // Update previous parameters
188
+ prevParamsRef.current = { queryLabel, maxQueryDepth, minDegree };
189
+ }
190
+ }, [queryLabel, maxQueryDepth, minDegree])
191
 
192
  const getNode = useCallback(
193
  (nodeId: string) => {
 
205
 
206
  useEffect(() => {
207
  if (queryLabel) {
208
+ const fetchKey = `${queryLabel}-${maxQueryDepth}-${minDegree}`;
209
+
210
+ // Only fetch if we haven't fetched this combination in the current component lifecycle
211
+ if (!isFetching && !fetchStatusRef.current[fetchKey]) {
212
+ useGraphStore.getState().setIsFetching(true);
213
+ fetchStatusRef.current[fetchKey] = true;
 
 
 
 
 
214
  fetchGraph(queryLabel, maxQueryDepth, minDegree).then((data) => {
215
  const state = useGraphStore.getState()
216
  const newSigmaGraph = createSigmaGraph(data)
 
241
  // Ensure * is there eventhough there is no graph data
242
  state.setGraphLabels(['*']);
243
  }
244
+ if (!data) {
245
+ // If data is invalid, remove the fetch flag to allow retry
246
+ delete fetchStatusRef.current[fetchKey];
247
+ }
248
+ // Reset fetching state after all updates are complete
249
+ state.setIsFetching(false);
250
+ }).catch(() => {
251
+ // Reset fetching state and remove flag in case of error
252
+ useGraphStore.getState().setIsFetching(false);
253
+ delete fetchStatusRef.current[fetchKey];
254
  })
255
  }
256
  } else {
lightrag_webui/src/stores/graph.ts CHANGED
@@ -68,6 +68,7 @@ interface GraphState {
68
  graphLabels: string[]
69
 
70
  moveToSelectedNode: boolean
 
71
 
72
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) => void
73
  setFocusedNode: (nodeId: string | null) => void
@@ -81,6 +82,7 @@ interface GraphState {
81
  setRawGraph: (rawGraph: RawGraph | null) => void
82
  setSigmaGraph: (sigmaGraph: DirectedGraph | null) => void
83
  setGraphLabels: (labels: string[]) => void
 
84
  }
85
 
86
  const useGraphStoreBase = create<GraphState>()((set) => ({
@@ -90,11 +92,13 @@ const useGraphStoreBase = create<GraphState>()((set) => ({
90
  focusedEdge: null,
91
 
92
  moveToSelectedNode: false,
 
93
 
94
  rawGraph: null,
95
  sigmaGraph: null,
96
  graphLabels: ['*'],
97
 
 
98
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) =>
99
  set({ selectedNode: nodeId, moveToSelectedNode }),
100
  setFocusedNode: (nodeId: string | null) => set({ focusedNode: nodeId }),
 
68
  graphLabels: string[]
69
 
70
  moveToSelectedNode: boolean
71
+ isFetching: boolean
72
 
73
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) => void
74
  setFocusedNode: (nodeId: string | null) => void
 
82
  setRawGraph: (rawGraph: RawGraph | null) => void
83
  setSigmaGraph: (sigmaGraph: DirectedGraph | null) => void
84
  setGraphLabels: (labels: string[]) => void
85
+ setIsFetching: (isFetching: boolean) => void
86
  }
87
 
88
  const useGraphStoreBase = create<GraphState>()((set) => ({
 
92
  focusedEdge: null,
93
 
94
  moveToSelectedNode: false,
95
+ isFetching: false,
96
 
97
  rawGraph: null,
98
  sigmaGraph: null,
99
  graphLabels: ['*'],
100
 
101
+ setIsFetching: (isFetching: boolean) => set({ isFetching }),
102
  setSelectedNode: (nodeId: string | null, moveToSelectedNode?: boolean) =>
103
  set({ selectedNode: nodeId, moveToSelectedNode }),
104
  setFocusedNode: (nodeId: string | null) => set({ focusedNode: nodeId }),