@@ -6,6 +6,7 @@ import type ReplayReader from 'sentry/utils/replays/replayReader';
6
6
import useApi from 'sentry/utils/useApi' ;
7
7
import useOrganization from 'sentry/utils/useOrganization' ;
8
8
import useProjectFromId from 'sentry/utils/useProjectFromId' ;
9
+ import useTimeout from 'sentry/utils/useTimeout' ;
9
10
import {
10
11
ReplaySummaryStatus ,
11
12
ReplaySummaryTemp ,
@@ -22,7 +23,7 @@ export interface UseFetchReplaySummaryResult {
22
23
*/
23
24
isError : boolean ;
24
25
/**
25
- * Whether the summary is still processing after the last start request.
26
+ * Whether the summary is still processing after the last start request. Does not account for timeouts.
26
27
*/
27
28
isPending : boolean ;
28
29
/**
@@ -42,35 +43,26 @@ export interface UseFetchReplaySummaryResult {
42
43
43
44
const shouldPoll = (
44
45
summaryData : SummaryResponse | undefined ,
45
- isStartSummaryRequestPending : boolean ,
46
+ startRequestFailed : boolean ,
46
47
didTimeout : boolean
47
48
) => {
48
- // If timeout occurred, stop polling regardless of status
49
- if ( didTimeout ) {
49
+ if ( startRequestFailed || didTimeout ) {
50
50
return false ;
51
51
}
52
52
53
53
if ( ! summaryData ) {
54
- // No data yet - poll if we've started a request
55
- return isStartSummaryRequestPending ;
54
+ return true ;
56
55
}
57
56
58
57
switch ( summaryData . status ) {
59
58
case ReplaySummaryStatus . NOT_STARTED :
60
- // Not started - poll if we've started a request
61
- return isStartSummaryRequestPending ;
62
-
63
59
case ReplaySummaryStatus . PROCESSING :
64
- // Currently processing - poll
65
60
return true ;
66
61
62
+ // Final states
67
63
case ReplaySummaryStatus . COMPLETED :
68
64
case ReplaySummaryStatus . ERROR :
69
- // Final states - no need to poll
70
- return false ;
71
-
72
65
default :
73
- // Unknown status - don't poll
74
66
return false ;
75
67
}
76
68
} ;
@@ -101,22 +93,15 @@ export function useFetchReplaySummary(
101
93
// summary data query and 2) we have the stale version of the summary data. The consuming
102
94
// component will briefly show a completed state before the summary data query updates.
103
95
const startSummaryRequestTime = useRef < number > ( 0 ) ;
96
+ const hasMadeStartRequest = useRef < boolean > ( false ) ;
104
97
105
- const pollingTimeoutRef = useRef < number | null > ( null ) ;
106
- const clearPollingTimeout = ( ) => {
107
- if ( pollingTimeoutRef . current ) {
108
- clearTimeout ( pollingTimeoutRef . current ) ;
109
- pollingTimeoutRef . current = null ;
110
- }
111
- } ;
112
98
const [ didTimeout , setDidTimeout ] = useState ( false ) ;
113
-
114
- // Cleanup polling timeout on unmount
115
- useEffect ( ( ) => {
116
- return ( ) => {
117
- clearPollingTimeout ( ) ;
118
- } ;
119
- } , [ ] ) ;
99
+ const { start : startPollingTimeout , cancel : cancelPollingTimeout } = useTimeout ( {
100
+ timeMs : POLL_TIMEOUT_MS ,
101
+ onTimeout : ( ) => {
102
+ setDidTimeout ( true ) ;
103
+ } ,
104
+ } ) ;
120
105
121
106
const {
122
107
mutate : startSummaryRequestMutate ,
@@ -157,15 +142,12 @@ export function useFetchReplaySummary(
157
142
return ;
158
143
}
159
144
startSummaryRequestMutate ( ) ;
145
+ hasMadeStartRequest . current = true ;
160
146
161
- // Clear timeout, if any, and start a new one .
147
+ // Start a new timeout .
162
148
setDidTimeout ( false ) ;
163
- clearPollingTimeout ( ) ;
164
- pollingTimeoutRef . current = window . setTimeout ( ( ) => {
165
- setDidTimeout ( true ) ;
166
- clearPollingTimeout ( ) ;
167
- } , POLL_TIMEOUT_MS ) ;
168
- } , [ options ?. enabled , startSummaryRequestMutate ] ) ;
149
+ startPollingTimeout ( ) ;
150
+ } , [ options ?. enabled , startSummaryRequestMutate , startPollingTimeout ] ) ;
169
151
170
152
const {
171
153
data : summaryData ,
@@ -178,7 +160,7 @@ export function useFetchReplaySummary(
178
160
staleTime : 0 ,
179
161
retry : false ,
180
162
refetchInterval : query => {
181
- if ( shouldPoll ( query . state . data ?. [ 0 ] , isStartSummaryRequestPending , didTimeout ) ) {
163
+ if ( shouldPoll ( query . state . data ?. [ 0 ] , isStartSummaryRequestError , didTimeout ) ) {
182
164
return POLL_INTERVAL_MS ;
183
165
}
184
166
return false ;
@@ -188,49 +170,42 @@ export function useFetchReplaySummary(
188
170
}
189
171
) ;
190
172
173
+ // Auto-start logic. Triggered at most once per page load.
174
+ const segmentsIncreased =
175
+ summaryData ?. num_segments !== null &&
176
+ summaryData ?. num_segments !== undefined &&
177
+ segmentCount > summaryData . num_segments ;
178
+
179
+ useEffect ( ( ) => {
180
+ if (
181
+ ! hasMadeStartRequest . current &&
182
+ ( segmentsIncreased || summaryData ?. status === ReplaySummaryStatus . NOT_STARTED )
183
+ ) {
184
+ startSummaryRequest ( ) ;
185
+ }
186
+ } , [ segmentsIncreased , startSummaryRequest , summaryData ?. status ] ) ;
187
+
191
188
const isPendingRet =
192
189
dataUpdatedAt < startSummaryRequestTime . current ||
193
190
isStartSummaryRequestPending ||
194
191
isPending ||
192
+ summaryData ?. status === ReplaySummaryStatus . NOT_STARTED ||
195
193
summaryData ?. status === ReplaySummaryStatus . PROCESSING ;
196
- const isErrorRet =
197
- isStartSummaryRequestError ||
198
- isError ||
199
- summaryData ?. status === ReplaySummaryStatus . ERROR ;
200
194
195
+ // Clears the polling timeout when we get valid summary results.
201
196
useEffect ( ( ) => {
202
- // Clears the polling timeout when we get valid summary results.
203
197
if ( ! isPendingRet ) {
204
- clearPollingTimeout ( ) ;
198
+ cancelPollingTimeout ( ) ;
205
199
}
206
- } , [ isPendingRet ] ) ;
207
-
208
- // Auto-start logic.
209
- // TODO: remove the condition segmentCount <= 100
210
- // when BE is able to process more than 100 segments. Without this, generation will loop.
211
- const segmentsIncreased =
212
- summaryData ?. num_segments !== null &&
213
- summaryData ?. num_segments !== undefined &&
214
- segmentCount <= 100 &&
215
- segmentCount > summaryData . num_segments ;
216
- const needsInitialGeneration = summaryData ?. status === ReplaySummaryStatus . NOT_STARTED ;
217
-
218
- useEffect ( ( ) => {
219
- if ( ( segmentsIncreased || needsInitialGeneration ) && ! isPendingRet && ! isErrorRet ) {
220
- startSummaryRequest ( ) ;
221
- }
222
- } , [
223
- segmentsIncreased ,
224
- needsInitialGeneration ,
225
- isPendingRet ,
226
- startSummaryRequest ,
227
- isErrorRet ,
228
- ] ) ;
200
+ } , [ isPendingRet , cancelPollingTimeout ] ) ;
229
201
230
202
return {
231
203
summaryData,
232
204
isPending : isPendingRet ,
233
- isError : isErrorRet ,
205
+ isError :
206
+ isStartSummaryRequestError ||
207
+ isError ||
208
+ summaryData ?. status === ReplaySummaryStatus . ERROR ,
234
209
isTimedOut : didTimeout ,
235
210
startSummaryRequest,
236
211
isStartSummaryRequestPending,
0 commit comments