Skip to content

Commit 93ad7ee

Browse files
authored
Merge pull request #6748 from FlowFuse/6747_retry-setting-device-affinity-token-in-scaled-environment
Retry device api call when tunnel proxy returns 502 to re-set the device affinity token
2 parents 6a2bf39 + 0f744ff commit 93ad7ee

3 files changed

Lines changed: 54 additions & 7 deletions

File tree

frontend/src/api/devices.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,10 @@ const generateSnapshotDescription = async (deviceId, target) => {
242242
})
243243
}
244244

245+
const getDeviceEditorProxy = async (editorUrl) => {
246+
return client.get(editorUrl)
247+
}
248+
245249
export default {
246250
create,
247251
getDevice,
@@ -266,5 +270,6 @@ export default {
266270
suspendDevice,
267271
restartDevice,
268272
startDevice,
269-
generateSnapshotDescription
273+
generateSnapshotDescription,
274+
getDeviceEditorProxy
270275
}

frontend/src/composables/DeviceHelper.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,15 @@ export function useDeviceHelper () {
118118
if (shouldStartPolling) { startPolling() }
119119
}
120120

121-
async function fetchDevice (deviceId = null) {
121+
async function fetchDevice (deviceId = null, shouldSetDevice = true) {
122122
try {
123-
device.value = await deviceApi.getDevice(deviceId || device.value?.id)
123+
const response = await deviceApi.getDevice(deviceId || device.value?.id)
124+
125+
if (shouldSetDevice) {
126+
device.value = response
127+
}
128+
129+
return response
124130
} catch (err) {
125131
if (err.status === 403) {
126132
stopPolling()
@@ -149,6 +155,14 @@ export function useDeviceHelper () {
149155
})
150156
}
151157

158+
async function getDeviceEditorProxy (device) {
159+
if (device.editor.url) {
160+
return deviceApi.getDeviceEditorProxy(device.editor.url)
161+
}
162+
163+
return Promise.reject(Error('editor url unavailable'))
164+
}
165+
152166
return {
153167
agentSupportsDeviceAccess,
154168
agentSupportsActions,
@@ -162,6 +176,7 @@ export function useDeviceHelper () {
162176
resumePolling,
163177
restartDevice,
164178
fetchDevice,
165-
showDeleteDialog
179+
showDeleteDialog,
180+
getDeviceEditorProxy
166181
}
167182
}

frontend/src/pages/device/Editor/index.vue

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,8 @@ export default {
129129
startPolling,
130130
stopPolling,
131131
resumePolling,
132-
pausePolling
132+
pausePolling,
133+
getDeviceEditorProxy
133134
} = useDeviceHelper()
134135
135136
return {
@@ -157,7 +158,8 @@ export default {
157158
stopPolling,
158159
resumePolling,
159160
pausePolling,
160-
showDeleteDeviceDialog
161+
showDeleteDeviceDialog,
162+
getDeviceEditorProxy
161163
}
162164
},
163165
computed: {
@@ -312,7 +314,32 @@ export default {
312314
methods: {
313315
...mapActions('context', { setContextDevice: 'setDevice' }),
314316
loadDevice: async function () {
315-
await this.fetchDevice(this.$route.params.id)
317+
let tries = 0
318+
let device = await this.fetchDevice(this.$route.params.id, false)
319+
320+
// When running multiple replicas of the forge app, the affinity token may be missing if the request is routed to a
321+
// backend endpoint that didn't initiate the tunnel. If we receive a 502 from the device editor proxy,
322+
// we retry the editor API call until the correct affinity token is acquired (200/302).
323+
while (tries <= 5) {
324+
try {
325+
await this.getDeviceEditorProxy(device)
326+
break
327+
} catch (e) {
328+
if (e?.response?.status === 502) {
329+
tries += 1
330+
331+
// 1s interval timeout between tries
332+
await new Promise(resolve => setTimeout(resolve, 1000))
333+
334+
device = await this.fetchDevice(this.$route.params.id, false)
335+
continue
336+
}
337+
338+
break
339+
}
340+
}
341+
342+
this.device = device
316343
await this.$store.dispatch('account/setTeam', this.device.team.slug)
317344
},
318345
showConfirmDeleteDialog () {

0 commit comments

Comments
 (0)