Skip to content

Commit e11c308

Browse files
Merge pull request #2711 from devtron-labs/fix/external-app-polling-cleanup
fix: polling cleanup in external apps
2 parents c5dfd7a + 237aa63 commit e11c308

File tree

4 files changed

+83
-35
lines changed

4 files changed

+83
-35
lines changed

src/Pages/App/Details/ExternalFlux/ExternalFluxAppDetails.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,12 @@ const ExternalFluxAppDetails = () => {
6969
setAppDetailsError(null)
7070
}
7171

72+
/**
73+
* Throws error in case request is aborted
74+
*/
7275
const handleFetchExternalFluxCDAppDetails = () =>
7376
// NOTE: returning a promise so that we can trigger the next timeout after this api call completes
74-
new Promise<void>((resolve) => {
77+
new Promise<void>((resolve, reject) => {
7578
setIsReloadResourceTreeInProgress(true)
7679

7780
abortPreviousRequests(
@@ -87,6 +90,8 @@ const ExternalFluxAppDetails = () => {
8790
} else {
8891
setAppDetailsError(error)
8992
}
93+
} else {
94+
reject(error)
9095
}
9196
})
9297
.finally(() => {
@@ -107,7 +112,11 @@ const ExternalFluxAppDetails = () => {
107112
}
108113

109114
const handleReloadResourceTree = async () => {
110-
await handleFetchExternalFluxCDAppDetails()
115+
try {
116+
await handleFetchExternalFluxCDAppDetails()
117+
} catch {
118+
// do nothing
119+
}
111120
}
112121

113122
useEffect(() => {

src/components/externalArgoApps/ExternalArgoAppDetail.tsx

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,15 @@ import { AppDetails, AppType } from '../v2/appDetails/appDetails.type'
3232
import IndexStore from '../v2/appDetails/index.store'
3333
import { ExternalArgoAppDetailType } from './externalArgoApp.type'
3434

35+
let initTimer = null
36+
3537
const ExternalArgoAppDetail = ({ appName, clusterId, isExternalApp, namespace }: ExternalArgoAppDetailType) => {
3638
const location = useLocation()
3739
const history = useHistory()
3840
const [isLoading, setIsLoading] = useState(true)
3941
const [isReloadResourceTreeInProgress, setIsReloadResourceTreeInProgress] = useState(false)
4042
const [errorResponseCode, setErrorResponseCode] = useState(undefined)
4143

42-
let initTimer = null
4344
let isAPICallInProgress = false
4445

4546
const abortControllerRef = useRef<AbortController>(new AbortController())
@@ -68,11 +69,21 @@ const ExternalArgoAppDetail = ({ appName, clusterId, isExternalApp, namespace }:
6869

6970
const _init = () => {
7071
if (!isAPICallInProgress) {
71-
_getAndSetAppDetail(true)
72+
_getAndSetAppDetail()
7273
}
7374
}
7475

75-
const _getAndSetAppDetail = async (shouldTriggerPolling: boolean = false) => {
76+
const handleInitiatePolling = () => {
77+
if (initTimer) {
78+
clearTimeout(initTimer)
79+
}
80+
81+
initTimer = setTimeout(() => {
82+
_init()
83+
}, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
84+
}
85+
86+
const _getAndSetAppDetail = async () => {
7687
isAPICallInProgress = true
7788
setIsReloadResourceTreeInProgress(true)
7889

@@ -85,25 +96,25 @@ const ExternalArgoAppDetail = ({ appName, clusterId, isExternalApp, namespace }:
8596
...appDetailResponse.result,
8697
deploymentAppType: DeploymentAppTypes.GITOPS,
8798
}
99+
100+
isAPICallInProgress = false
101+
handleInitiatePolling()
102+
88103
IndexStore.publishAppDetails(genericAppDetail, AppType.EXTERNAL_ARGO_APP)
89104
setErrorResponseCode(undefined)
90105
})
91106
.catch((errors: ServerErrors) => {
92107
if (!getIsRequestAborted(errors)) {
93108
showError(errors)
94109
setErrorResponseCode(errors.code)
110+
isAPICallInProgress = false
111+
handleInitiatePolling()
95112
}
96113
})
97114
.finally(() => {
98115
setIsLoading(false)
99116
isAPICallInProgress = false
100117
setIsReloadResourceTreeInProgress(false)
101-
102-
if (shouldTriggerPolling) {
103-
initTimer = setTimeout(() => {
104-
_init()
105-
}, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
106-
}
107118
})
108119
}
109120

src/components/v2/appDetails/ea/EAAppDetail.component.tsx

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import { getExternalLinks } from '../../../externalLinks/ExternalLinks.service'
4040
import { ExternalLinkIdentifierType, ExternalLinksAndToolsType } from '../../../externalLinks/ExternalLinks.type'
4141
import { sortByUpdatedOn } from '../../../externalLinks/ExternalLinks.utils'
4242

43+
let initTimer = null
44+
4345
const ExternalAppDetail = ({ appId, appName, isExternalApp }) => {
4446
const location = useLocation()
4547
const history = useHistory()
@@ -53,7 +55,6 @@ const ExternalAppDetail = ({ appId, appName, isExternalApp }) => {
5355

5456
const abortControllerRef = useRef<AbortController>(new AbortController())
5557

56-
let initTimer = null
5758
let isAPICallInProgress = false
5859

5960
// component load
@@ -80,7 +81,7 @@ const ExternalAppDetail = ({ appId, appName, isExternalApp }) => {
8081

8182
const _init = () => {
8283
if (!isAPICallInProgress) {
83-
_getAndSetAppDetail(true)
84+
_getAndSetAppDetail()
8485
}
8586
}
8687

@@ -120,7 +121,17 @@ const ExternalAppDetail = ({ appId, appName, isExternalApp }) => {
120121
return genericAppDetail
121122
}
122123

123-
const _getAndSetAppDetail = (shouldTriggerPolling: boolean = false) => {
124+
const handleInitiatePolling = () => {
125+
if (initTimer) {
126+
clearTimeout(initTimer)
127+
}
128+
129+
initTimer = setTimeout(() => {
130+
_init()
131+
}, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
132+
}
133+
134+
const _getAndSetAppDetail = () => {
124135
isAPICallInProgress = true
125136
setIsReloadResourceTreeInProgress(true)
126137

@@ -161,24 +172,21 @@ const ExternalAppDetail = ({ appId, appName, isExternalApp }) => {
161172
}
162173

163174
setErrorResponseCode(undefined)
175+
176+
handleInitiatePolling()
164177
})
165178
.catch((errors: ServerErrors) => {
179+
setIsLoading(false)
180+
isAPICallInProgress = false
181+
166182
if (!getIsRequestAborted(errors)) {
167183
showError(errors)
168184
setErrorResponseCode(errors.code)
185+
handleInitiatePolling()
169186
}
170-
171-
setIsLoading(false)
172-
isAPICallInProgress = false
173187
})
174188
.finally(() => {
175189
setIsReloadResourceTreeInProgress(false)
176-
177-
if (shouldTriggerPolling) {
178-
initTimer = setTimeout(() => {
179-
_init()
180-
}, window._env_.EA_APP_DETAILS_POLLING_INTERVAL || 30000)
181-
}
182190
})
183191
}
184192

src/components/v2/index.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ const RouterComponent = ({ envType }) => {
116116
}, [location.search])
117117

118118
const _init = (fetchExternalLinks?: boolean) => {
119-
abortPreviousRequests(() => _getAndSetAppDetail(fetchExternalLinks, true), abortControllerRef)
119+
abortPreviousRequests(() => _getAndSetAppDetail(fetchExternalLinks), abortControllerRef)
120120
}
121121

122122
const handleAppDetailsCallError = (e: any) => {
@@ -141,12 +141,16 @@ const RouterComponent = ({ envType }) => {
141141
}
142142

143143
const handleInitiatePolling = () => {
144+
if (initTimer) {
145+
clearTimeout(initTimer)
146+
}
147+
144148
initTimer = setTimeout(() => {
145149
_init()
146150
}, window._env_.HELM_APP_DETAILS_POLLING_INTERVAL || 30000)
147151
}
148152

149-
const handleFetchAppDetails = async (fetchExternalLinks: boolean) => {
153+
const handleFetchAppDetails = async (fetchExternalLinks: boolean): Promise<{ isAborted: boolean }> => {
150154
try {
151155
const response = await getInstalledChartDetail(+params.appId, +params.envId, abortControllerRef)
152156
handlePublishAppDetails(response)
@@ -155,32 +159,49 @@ const RouterComponent = ({ envType }) => {
155159
if (fetchExternalLinks) {
156160
getExternalLinksAndTools(response.result?.clusterId)
157161
}
162+
setLoadingDetails(false)
158163
} catch (error) {
159-
handleAppDetailsCallError(error)
160-
} finally {
164+
const isAborted = getIsRequestAborted(error)
165+
166+
if (!isAborted) {
167+
handleAppDetailsCallError(error)
168+
}
161169
setLoadingDetails(false)
170+
171+
return { isAborted }
162172
}
173+
174+
return { isAborted: false }
163175
}
164176

165177
const handleFetchResourceTree = async () => {
166178
try {
167179
const response = await getInstalledChartResourceTree(+params.appId, +params.envId, abortControllerRef)
168180
handlePublishAppDetails(response)
181+
setLoadingResourceTree(false)
169182
} catch (error) {
170-
handleAppDetailsCallError(error)
171-
} finally {
183+
const isAborted = getIsRequestAborted(error)
184+
185+
if (!isAborted) {
186+
handleAppDetailsCallError(error)
187+
}
172188
setLoadingResourceTree(false)
189+
190+
return { isAborted }
173191
}
192+
193+
return { isAborted: false }
174194
}
175195

176-
const _getAndSetAppDetail = async (fetchExternalLinks: boolean, shouldTriggerPolling: boolean = false) => {
196+
const _getAndSetAppDetail = async (fetchExternalLinks: boolean) => {
177197
if (envType === EnvType.CHART) {
178198
// Intentionally not setting await since it was not awaited earlier when in thens as well
179199
Promise.allSettled([
180200
handleFetchAppDetails(fetchExternalLinks),
181201
handleFetchResourceTree(),
182-
]).finally(() => {
183-
if (shouldTriggerPolling) {
202+
]).then((results) => {
203+
const isAborted = results.some((result) => result.status === 'fulfilled' && result.value.isAborted)
204+
if (!isAborted) {
184205
handleInitiatePolling()
185206
}
186207
})
@@ -195,9 +216,8 @@ const RouterComponent = ({ envType }) => {
195216
setErrorResponseCode(e.code)
196217
}
197218
} finally {
198-
if (shouldTriggerPolling) {
199-
handleInitiatePolling()
200-
}
219+
// BTW This is a dead block BTW should be removed
220+
handleInitiatePolling()
201221
}
202222
}
203223
}

0 commit comments

Comments
 (0)