Anvil default App timeout length?

Does anyone know the default length of the Anvil app inactivity timeout that requires you to refresh the app.
The reason I ask is; as part of my code to ensure that the same user cannot login more than once I have a true/false ‘is_logged-in’ column in my users data table and I have to account for cases where they don’t physically log out, so that that column is reset to false. In order to accomplish that I have a ‘session_start’ and ‘session_expiry’ column to check for inactivity. However, if the app refreshes before the length of time difference between those 2 columns, the ‘is_logged_in’ column wont be reset to false and they wont be ale to log in as it will think they are still logged in. So I would like to either; syncronise my session active columns with the Anvil default inactivity period or have some method to have the Anvil default refresh set my ‘is_logged_in’ column to false?

Any help is much appreciated!
Adam

I think it is 30 minutes.

2 Likes

I can recall other forum threads on this topic in the past. It might take some experimentation with different keyword searches to find them, but you should be able to find some suggestions.

1 Like

In my experience, if you’re using mobile devices then the timeout question gets a bit harder. Due to a myriad of reasons, mostly commonly being split second loss of internet, the app is trying and failing to make a server call, so then just assuming its offline. Once offline, unless you manually catch that at the right point and ‘re-sign in’, the app just gets a bit dumb. There are ways to do offline app stuff, like anvil_extras.storage, but I’m yet to fully test that myself

3 Likes

I’m only interested in desktop applications, my app doesn’t lend itself to mobile apps due to it’s graphical nature, but thank you for the input.

1 Like

The easiest way I would recommend is to have a timer on the front end which triggers a server call every, say 1 minute, this server call updates the “logged in” column to true every time it’s run while logging the datetime of the activity in another column.
Then have a background task which runs, again for example, every 1 min and checks to see if the time difference between the last logged activity and the current time is greater than 3 minutes and if so mark the “logged in” as false.

I used this same logic to limit the number of users which can log in concurrently on one of my apps.

2 Likes

Hello @mail,

If I’m understanding you correctly, I’d like to break your post into two parts:

  1. What’s Anvil’s default behaviour for inactivity?
  2. How do you prevent duplicate logins?

1. What’s Anvil’s default behaviour for inactivity?

@stefano is correct, an Anvil session will stay open as long as an operation has been performed in the last 30 minutes.

If a user’s session expires, the next server operation will cause the following dialog to appear:

An alert informing the user that the session has timed out, with a button to refresh now.

Note that a “server operation” isn’t always a call to anvil.server.call(). It could be a data table search or a Google Drive query.

Here’s the documentation for this, including some information on catching the timeout error:


2. How do you prevent duplicate logins?

This is a devilishly tricky problem as there can be a lot of edge cases to think about but at a high level:
The basic thing that you need to notice is if a session just goes away entirely - because if someone drops off the end of the world (e.g. losing signal, running out of battery, pulling out a network cable) your system shouldn’t allow them to get “stuck”.

One high level solution would look like:

  • Start by generating a unique client ID when the page loads
  • Store the current client ID in user’s DB row
  • Also store the last time the client ID was seen
  • Use a timer on the client side to call a “keep-alive” function every X seconds to update the “last_seen_logged_in” column
  • When a user logs out clear the client ID (optional)
  • When a user logs in check the client ID against the client ID in the table
    • If the client ID doesn’t match and a sufficient arbitrary time has passed, assume the old session must have gone away and clear the old ID. Then, add the new client ID and treat it as the current session from then on.
  • Each time you try to execute a server-side operation, you check whether the session is the “officially” logged-in session for that user. If you’re not, then anvil.users.logout() and refuse to perform the operation.

Hope that helps :slightly_smiling_face:

2 Likes

Hi Ryan,
Thank you very much for the comprehensive reply. I should probably expand on what I have currently, as I notice my original post is actually inaccurate:

I have a ‘is_logged_in’ (true/flase) column, a ‘sessions_start’ (date and time) and a ‘session_expiry’ (date and time) column. These get correctly populated when a user logs in. If a user then tries to log in more than once they correctly get told they are already logged in. If they manually log out the ‘is_logged_in’ column correctly gets set to false. If the Anvil session expires due to inactivity and a refresh is requested, the ‘is_logged_in’ column correctly gets set to false, this was the error I made in my original post… However, if they just kill the app without manually logging out or the the Anvil request to refresh the app is yet to trigger it still thinks they’re logged in

Your suggestion to use a timer seems like the correct path to take. I was going to consider to try using a background task, but the timer function would have less overhead I would think.

Thank you again.

The difference between a timer and a background task is not the overhead, it’s that the timer runs on the client, while the background task runs on the server.

A background task cannot contact the client, while a timer running on the client can call a server function to update a timestamp.

A background task, as suggested by @turnip12144, could be used to check if the client contacted the server in the past few seconds and log the session out.

In my opinion, I would keep things simpler: no timer, no background task. I would set the timestamp every time the app calls a server function. If the server call comes from a different session, then, if the timestamp is older than x minutes, I would log out the older session, otherwise I would show a dialog asking whether to log out the older session or cancel the current operation.

1 Like

That makes sense. Thank you Stefano!