Reduce ClientReset Timeout

I tried to simulate a client reset by doing a “Terminate Sync”, as I understand it, this will cause a client reset event to any connected clients.

I have a breakpoint in app.syncManager.errorHandler = { [weak self] error, _ in where the code is broadly similar to the code in the oft referenced example.

In my mobile app logs I see:

[Information] Connection[1]: Negotiated protocol version: 3
[Information] Connection[1]: Received: ERROR "sync is not enabled for this app - request logs URL: https://realm.mongodb.com/[snip]" (error_code=101, try_again=false, session_ident=0)
[Information] Connection[1]: Connection closed due to error reported by server: sync is not enabled for this app - request logs URL: https://realm.mongodb.com/[snip] (101)
[Information] Connection[1]: Allowing reconnection in 3356434 milliseconds

Is my understanding correct, that this happened because the sync wasn’t running again at the point the client tried to reconnect?

And so it will wait 1 hour to try to reconnect again? If this is correct, how might I reduce the reconnection wait time please?

Thanks

Hi @MagnifcoSpecifico

It’s probably better not to ignore the session parameter, as it’s used in identifying a few other configuration parameters needed further on in the code (like, the actual realm involved in the error), but that’s a different matter.

Yes, that’s indeed the cause.

Yes, the current session stays open, so that you can still work with the realm locally, but it will reconnect in an hour, that may or may not be ideal for your typical use. The delay for the case when the server sets try_again to false is fixed, so you can’t reduce it, if you look at the source code you’ll find the following comment

// Use a significantly longer delay in this case to avoid
// disturbing the server too much. It does make sense to try
// again eventually, because the server may get restarted in
// such a way the that problem goes away.

You can however force an attempt by closing the present session (i.e. deleting all references to the realm, and wait a bit for all background processes to wind down), and try to re-open it later, at an interval of your convenience, but while the session is down the realm isn’t accessible. As explained above, it’s not worth to try too often.

Hi @Paolo_Manna thanks for your reply.

What you say makes sense. In my use case, it’s ok for the realm to be inaccessible and to do a hard reload.

My use case should re-connect asap. I thought I would try to connect again after 30 seconds. Is there a reason why that might be too fast? Is there a reason why 1hr is a reasonable hardcode?

I noticed that when I terminated the sync, that my app.syncManager.errorHandler breakpoint didn’t trigger.

You can however force an attempt by closing the present session (i.e. deleting all references to the realm, and wait a bit for all background processes to wind down), and try to re-open it later, at an interval of your convenience, but while the session is down the realm isn’t accessible. As explained above, it’s not worth to try too often.

Could you offer a suggestion please as to where I could trigger this?

Hi @Paolo_Manna I should say, my initial expectation is that the syncManager.errorHandler block should be called when an error occurs (e.g. reset error or client reset while running).

But I’m not seeing the block getting triggered except when I restart the app. Unless I restart the app while sync is still terminated, in which case, I get no notifications.

I had a look at the underlying C++ code, and I don’t see a route to notification of failure apart from report_connection_state_change(ConnectionState::disconnected, &error_info); // Throws

But as far as I could see, the only way to see something might’ve gone wrong is by observing the connection state for a change from Connecting → Disconnected which I need a session for but if I use asyncOpen I don’t have a session?

I must have missed something?

Hi @MagnifcoSpecifico,

Correct: this is expected, there’s still no new server version to download, and the disconnection could be temporary (for example, it’s what happens when you Pause Sync - resuming it doesn’t trigger a Client Reset). The SDK just holds all the local modifications, periodically polling the server, until the connection is back.

In isolation, no, but think in terms of thousands of users active at any given time, that are trying to connect to a server down for whatever maintenance was needed (or just a data centre offline for a bit). The server will need to spend time just answering back with errors.

That’s correct, see my answer to a similar question.

Mmmm but periodically in this case is 1 hour?

Our use case is interesting because we have a limited number of clients, it’s ok to show an activity indicator if something were to go wrong on the server e.g. Sync crashes, but it is critically important that they reconnect asap. In our use case 1 hour is not appropriate. Which is why I’m so keen to restart asap.

The error handler is called with a valid session in other cases:

  • When sync is reset while the app is running, and you’ve a session opened already

From your reply, I understand that I should expect app.syncManager.errorHandler to be called if I do not have a session. And I would expect .failure(error) from the Realm.asyncOpen block if I have a valid session.

I placed breakpoints in both place and tried pausing and terminating syncing after a successfull connection as well as restarting the app while the pause and terminate conditions were true. But no breakpoints were hit. Only the logs gave an indication there was an issue.

I’m using v10.21.1 of Realm. Is there some set of configuration ot debug options that would cause this?

@Paolo_Manna looks like there is a not disimilar question here.

@Paolo_Manna any suggestions please?