Azure / azure-remote-rendering

SDK and samples for Azure Remote Rendering
MIT License
106 stars 38 forks source link

[Question][Bug?]Handling internet connection issues #81

Closed WouwWatts closed 2 years ago

WouwWatts commented 2 years ago

Hello

I have been working on an app that uses Azure Remote Rendering in Unity, and I have been trying to catch exceptions that would break the app when losing internet connection. If I understand it correctly no direct event/error is sent out when losing connection, only when trying to perform an action that requires an internet connection. This works fine, BUT if you lose internet connection during certain actions, like starting or connection to a session, no error gets thrown.

If you reconnect to the internet you will automatically continue starting a session and connecting to it, but this isn't very user friendly. I want to be able to notify users their connection is lost, and give them the option to cancel the task and do other stuff in the meantime (the app doesn't solely use ARR).

Two missing features(as I'm seeing) that are preventing this are:

  1. You can't give a cancel token to the start session or connect to session tasks, so you can't cancel these tasks.
  2. No event is send out, or exception is thrown when losing connection, only when performing actions that require a connection.

I have noticed an alert gets logged periodically when not connected to internet, but I don't see where this gets send from, and if I can hook onto it, in the first place.

noconnectionalert

It would be greatly appreciated if anybody could look into this, if I am mistaken, and missing some obvious way to correctly handle these errors, please let me now!

Sanakan8472 commented 2 years ago

Hi @WouwWatts ,

If you are connected to a session, you will be informed if the connection timed out, i.e. no UDP packets were received within 5 seconds. This is done via the RenderingSession.ConnectionStatusChanged event that you can register to.

Note that the 5sec timeout is a heuristic, there is no way to know that an internet connection is interupted at some point. Thus, if you don't have an active server connection, we can't inform you that your internet is down.

If you are not connected to a session yet and just executing REST calls, we will retry internally three times before returning the error to the user. Depending on the root cause of the internet outage various failure codes can be returned. For example, have a look at the return codes for ConnectAsync.

Regarding cancelation tokens, we don't support them right now. However, we will put it on our list for future feature development. In the meantime, you can use our .net Azure SDK that wraps the REST API and supports cancellation tokens. For the ConnectAsync call we don't have a workaround at this point.

As for the DomainUnreachable error you see in the logs: This is generated by the arrServiceUnity class which sends a REST call out every 20 seconds or so to query the state of the current session. It just calls RenderingSession.GetPropertiesAsync internally.

Could you go into more detail on what you want to achieve? How are you planning to figure out that your internet connection is down? Instead of canceling the API call, could you just leave the request running in the background to let the user do other things in the meantime?

Cheers, Christopher

WouwWatts commented 2 years ago

First of all thanks for answering!

Regarding cancelation tokens, we don't support them right now. However, we will put it on our list for future feature development.

Lovely to hear!

The main issue I have is that while it's correct I get exceptions thrown when trying to connect or to start a session without internet, but something that doesn't trigger an exception is when you are connected to the internet when starting a session, but lose your internet connection while starting a session.

I would like to be able to show a message saying: "oops you lost your connection to the internet" when that happens, and allow the user to cancel out of starting the session, and return to the rest of the app. I don't really want to just ignore starting a session, because if it does go through after reconnecting the user might already be doing other things.

jumeder commented 2 years ago

Hi @WouwWatts,

first of all, we use async patterns on pretty much anything that can't return immediately, so you should get a task object from the respective method which you can wait on or check periodically for completion or failure. Waiting on a task will also rethrow any exception that occurred inside of it. You can let these run in the background and return control to the user immediately.

For the following I'm assuming you are using our C# API directly (see Runtime/RemoteRenderingApiUnity.cs).

I'm guessing by "starting a session" you mean bringing it up to the point where one can connect to it. As our C# API mirrors our REST SDKs, this is actually a two-step process. You first create a session, which can fail but should do so after a maximum of 45 seconds, as we retry 3 times with a timeout of 15 seconds. After a session has been successfully created (the task that CreateNewRenderingSessionAsync returns completes successfully), you can find the Session object in the task's result.

You then need to wait until the session reports as 'Ready', so the session needs to be queried for its status using GetPropertiesAsync on the session object. Getting a session ready can take a couple of minutes at the worst, depending on whether you are requesting a standard or premium session, and general demand in that region. You could implement your failure logic based on the GetPropertiesAsync task failing a couple of times (a good indication that the remote end is not answering) and the session status jumping from 'Starting' to something other than 'Ready'. After the session is ready, it can be connected to.

Note that if the initial CreateNewRenderingSessionAsync succeeds the session will in all likelihood be readied, so it will run until the end of the configured provision time if not shut down. If you have to assume frequent internet outage, it would be prudent to provision a session with a small initial time and then update the session provision time in appropriate increments to keep it running.

In case you are using our convenience wrapper classes on top of the C# APIs, which are also included in the Unity package, then they might not give you the functionality you need for your specific use case. ArrServiceUnity for example implements the steps I outlined above, so you can use it to quickly start and update a session until it is ready, but it doesn't implement such a connection loss logic.

jakrams commented 2 years ago

@WouwWatts I'll close this ticket now. Please re-open it in case there are further questions.