Skip to content

Commit 92d6500

Browse files
committed
Replace manual team loading delay with waitWhile helper and add reusable timer utility
1 parent 0e0dc51 commit 92d6500

3 files changed

Lines changed: 51 additions & 6 deletions

File tree

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
export default function useTimerHelper () {
2+
/**
3+
* Asynchronously waits while a condition remains true, checking at regular intervals.
4+
*
5+
* @param {boolean|Function} condition - A boolean value or a function that returns a boolean.
6+
* The waiting continues while this evaluates to true.
7+
* @param {Object} options - Configuration options for the waiting behavior.
8+
* @param {number} [options.cutoffTries=Infinity] - Maximum number of attempts before throwing an error.
9+
* Must be a non-negative finite number.
10+
* @param {number} [options.intervalMs=1000] - Time in milliseconds to wait between condition checks.
11+
* Must be a non-negative finite number.
12+
* @returns {Promise<void>} Resolves when the condition becomes false.
13+
* @throws {Error} If intervalMs or cutoffTries are invalid (negative or non-finite).
14+
* @throws {Error} If the maximum number of tries (cutoffTries) is reached before condition becomes false.
15+
*/
16+
async function waitWhile (condition, { cutoffTries = Infinity, intervalMs = 1000 } = {}) {
17+
const predicate = (typeof condition === 'function')
18+
? condition
19+
: () => Boolean(condition)
20+
21+
const delayMs = Number(intervalMs)
22+
if (!Number.isFinite(delayMs) || delayMs < 0) {
23+
throw new Error(`waitWhile: intervalMs must be a non-negative number, got ${intervalMs}`)
24+
}
25+
26+
const maxTries = Number(cutoffTries)
27+
if (!Number.isFinite(maxTries) || maxTries < 0) {
28+
throw new Error(`waitWhile: cutoffTries must be a non-negative number, got ${cutoffTries}`)
29+
}
30+
31+
let tries = 0
32+
while (predicate()) {
33+
if (tries >= maxTries) {
34+
throw new Error(`waitWhile: cutoffTries (${maxTries}) reached`)
35+
}
36+
tries++
37+
await new Promise(resolve => setTimeout(resolve, delayMs))
38+
}
39+
}
40+
41+
return {
42+
waitWhile
43+
}
44+
}

frontend/src/store/modules/product/expert/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { markRaw } from 'vue'
33

44
import expertApi from '../../../../api/expert.js'
55
import ExpertDrawer from '../../../../components/drawers/expert/ExpertDrawer.vue'
6+
import useTimerHelper from '../../../../composables/TimersHelper.js'
67

78
import { FF_AGENT, OPERATOR_AGENT } from './agents.js'
89

@@ -258,9 +259,8 @@ const actions = {
258259
// todo this need to be removed when we have https://github.com/FlowFuse/flowfuse/issues/6520 part of
259260
// https://github.com/FlowFuse/flowfuse/issues/6519 as it's a hacky workaround to the expert drawer opening up
260261
// before we have a team loaded
261-
while (!rootGetters['account/team']) {
262-
await new Promise(resolve => setTimeout(resolve, 1000))
263-
}
262+
const { waitWhile } = useTimerHelper()
263+
await waitWhile(() => !rootGetters['account/team'], { cutoffTries: 60 })
264264

265265
return expertApi
266266
.chat({

frontend/src/store/modules/product/expert/operator-agent/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import expertApi from '../../../../../api/expert.js'
2+
import useTimerHelper from '../../../../../composables/TimersHelper.js'
23

34
const initialState = () => ({
45
sessionId: null,
@@ -58,15 +59,15 @@ const actions = {
5859
// todo this need to be removed when we have https://github.com/FlowFuse/flowfuse/issues/6520 part of
5960
// https://github.com/FlowFuse/flowfuse/issues/6519 as it's a hacky workaround to the expert drawer opening up
6061
// before we have a team loaded
61-
while (!rootGetters['account/team']) {
62-
await new Promise(resolve => setTimeout(resolve, 1000))
63-
}
62+
const { waitWhile } = useTimerHelper()
63+
await waitWhile(() => !rootGetters['account/team'], { cutoffTries: 60 })
6464

6565
const payload = {
6666
context: {
6767
teamId: rootGetters['account/team'].id
6868
}
6969
}
70+
7071
return expertApi.getCapabilities(payload)
7172
.then(data => {
7273
commit('SET_CAPABILITIES', data.servers || [])

0 commit comments

Comments
 (0)