Skip to content

Retry "Launch Simulation" on server failure #281

Description

@ezio-melotti

After clicking on the LAUNCH SIMULATION button in the config wizard, we might sometime get a 5xx error from the server. When that happens, instead of showing a popup with the error, it would be better to tell the user that our server are busy, and automatically retry the request after 10-15 seconds. If after a few attempts we still get an error, a regular popup should tell the user that all our server are busy.

Since we already have a timeout modal, it would be nice to reuse it for the countdown before the retry. I looked into it briefly, however the timeout is not-blocking and returns immediately, so it didn't work.

Click to see a diff of my (not-working) attempt, which outlines the implementation.
diff --git a/src/views/ConfigurationView.vue b/src/views/ConfigurationView.vue
index 96ccb69..a628fe5 100644
--- a/src/views/ConfigurationView.vue
+++ b/src/views/ConfigurationView.vue
@@ -167,7 +167,7 @@ export default {
     },
     methods: {
         ...mapMutations(['SETGAMEID']),
-        ...mapActions('modal', ['alert']),
+        ...mapActions('modal', ['alert', 'timeout']),
 
         toggleMenu() {
             this.menuActive = !this.menuActive
@@ -191,12 +191,19 @@ export default {
         },
 
         handleAxiosError(error) {
-            console.error(error)
+            //console.error(error)
             if (error.response && error.response.status === 401) {
                 this.alert('Please log in again to continue.')
                 this.$router.push('entry')
             } else {
-                this.alert(error)
+                console.log('showing timeout alert')
+                //this.alert('Our servers are currently busy.\nClick "Ok" to try again.')
+                this.timeout({
+                    message: ('Our servers are currently busy.\n' +
+                              'Retrying in 10'),
+                    secondsLeft: 10,
+                    timeoutCallback: () => console.log('timeout done'),
+                })
             }
         },
 
@@ -282,26 +289,30 @@ export default {
                 this.alert(err_msg)
                 return  // abort if there are any errors
             }
-            try {
-                this.awaiting_response = true
-                // Wait for the new game to be created
-                const response = await axios.post('/new_game', configParams)
-                // store the game ID and full game_config from the response
-                this.SETGAMEID(response.data.game_id)
-                this.setGameParams({
-                    game_config: response.data.game_config,
-                    currency_desc: response.data.currency_desc,
-                })
-                this.currentMode = this.currentMode !== 'kiosk' ? 'sim' : 'kiosk'
-                this.isLive = false
-                this.loadFromSimData = false
-                // If all is well then move the user to the dashboard screen
-                this.$router.push('dashboard')
-            } catch (error) {
-                this.handleAxiosError(error)
-            } finally {
-                this.awaiting_response = false
+            for (let attempt = 0; attempt < 3; attempt++) {
+                console.log(`attempt ${attempt}`)
+                try {
+                    this.awaiting_response = true
+                    // Wait for the new game to be created
+                    const response = await axios.post('/new_game', configParams)
+                    // store the game ID and full game_config from the response
+                    this.SETGAMEID(response.data.game_id)
+                    this.setGameParams({
+                        game_config: response.data.game_config,
+                        currency_desc: response.data.currency_desc,
+                    })
+                    this.currentMode = this.currentMode !== 'kiosk' ? 'sim' : 'kiosk'
+                    this.isLive = false
+                    this.loadFromSimData = false
+                    // If all is well then move the user to the dashboard screen
+                    this.$router.push('dashboard')
+                } catch (error) {
+                    this.handleAxiosError(error)
+                } finally {
+                    this.awaiting_response = false
+                }
             }
+            this.alert('All our servers are currently busy.\nPlease try again later.')
         },
     },
 }

This could be implemented in launchSimulation and/or handleAxiosError but, if possible, it should avoid duplicating code (both the one that handles the error, and the one that sends the request). It might also require an udpate to the timeout modal to make it async, so that you can await until the 10-15 pass before retrying and doing another iteration of the loop.

Metadata

Metadata

Assignees

Labels

enhancementA new enhancement or feature

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions