api icon indicating copy to clipboard operation
api copied to clipboard

Add autoconnect to ScProvider

Open wirednkod opened this issue 2 years ago • 9 comments

Resolves issue mentioned in substrate connect repo - issues #1243 and #1141

wirednkod avatar Sep 14 '22 14:09 wirednkod

The objective is to add an equivalent of this block of code: https://github.com/polkadot-js/api/blob/12750bc83d8d7f01957896a80a7ba948ba3690b7/packages/rpc-provider/src/ws/index.ts#L450-L456 We want to automatically reconnect when we disconnect.

tomaka avatar Sep 14 '22 14:09 tomaka

So it's not that simple. The problem to solve is not what to do when the health checker says that we're not healthy. The problem to solve is what to do when the connection to the extension dies. In other words, you should try to reconnect when an error event happens. The problem is that there's no way right now from the API of the connect package to detect when the connection to the extension has died, other than the fact that the Chain.sendJsonRpc and Chain.remove functions throw an exception.

tomaka avatar Sep 15 '22 12:09 tomaka

So it's not that simple. The problem to solve is not what to do when the health checker says that we're not healthy. The problem to solve is what to do when the connection to the extension dies. In other words, you should try to reconnect when an error event happens. The problem is that there's no way right now from the API of the connect package to detect when the connection to the extension has died, other than the fact that the Chain.sendJsonRpc and Chain.remove functions throw an exception.

Im not sure why you refer to the extension. At the moment, When laptop goes to sleep and then resumes, the current code was cleaning up all subscriptions due to the emit of disconnect. The health checker continues to show that we are healthy, but since the subscription is cleared - there is no way to communicate something back to the App.
What is solved in this PR, is to avoid killing subscriptions when autoconnect is set to true (default and when a manual disconnect does not take place). This way when the computer resumes, the subscription still exists and receives all the messages.

wirednkod avatar Sep 15 '22 13:09 wirednkod

This PR "seems" wrong to me. It would mean that the provider can report a disconnected event, then later a connected event, without the active subscriptions being killed.

I can't strictly say that this is wrong because it depends on the small details of the API of the Provider interface, and these small details aren't written anywhere. But it definitely feels wrong to me.

tomaka avatar Sep 16 '22 13:09 tomaka

The way I approached it, is that the subscription should be cleaned only if disconnect is called. Everything else (emit connect - emit disconnect - emit connect) seems to me as a network failure (intentional through sleep mode or not), and IMO subscriptions should not be cleared).

wirednkod avatar Sep 16 '22 13:09 wirednkod

So the events handling would depend fully on the underlying layer. For instance in WS, when you get a disconnect, it would mean that the underlying transport is gone and dead, you will never receive anything on it again. In the WsProvider, after a network layer disconnect/re-connect, all subs that were existing re-created to ensure continuance. (Just continuing with the current ones will never have any data)

So in this case, if a disconnect/reconnect means that the existing subs are still ongoing, it would be fine. If not, it would mean you have subscriptions that won't get any data back.

jacogr avatar Sep 16 '22 14:09 jacogr

The entire and only reason why we have this health checker system and why we generate disconnected and connected events is precisely to prevent PolkadotJS from querying information at certain moments.

When we generate a "disconnected" event, we precisely mean "DO NOT USE THE CLIENT RIGHT NOW /!\ /!"

It feels extremely surprising to me that subscriptions would stay alive during this mode. We should, IMO, do it the same way as the WsProvider and treat "disconnected" as "the client is completely unaccessible", rather than in a mode where everything is unaccessible but subscriptions stay alive.

tomaka avatar Sep 16 '22 16:09 tomaka

The ScProvider is currently behaving the same way as the WsProvider, and this PR makes the ScProvider more tolerant in an attempt to fix a problem somewhere.

To me this indicates that this is not the correct fix. If things work fine with the WsProvider, and they do, then they should work fine with the ScProvider as well. And if necessary we should instead try to make the ScProvider behave more similarly to the WsProvider, rather than differently.

tomaka avatar Sep 16 '22 16:09 tomaka

Ok, read more, and the WsProvider re-subscribes: https://github.com/polkadot-js/api/blob/96a23bda503fc0065f38e7bbcd963c09347fc793/packages/rpc-provider/src/ws/index.ts#L540

I don't really understand why this is done in the WsProvider rather than a different layer, but this is what we should do in the ScProvider.

tomaka avatar Sep 16 '22 16:09 tomaka

could probably use an issue

As per your request: #5228

wirednkod avatar Sep 23 '22 07:09 wirednkod

It's missing a this.#resubscribeMethods.delete when you unsubscribe

tomaka avatar Sep 23 '22 10:09 tomaka

It's also not clear to me why resubscribeMethods needs to be a different map than subscriptions

tomaka avatar Sep 23 '22 10:09 tomaka

It's also not clear to me why resubscribeMethods needs to be a different map than subscriptions

Because subscriptions upon disconnect are cleared. Thats the initial source of the problem I described before. When disconnect occurs the cleanup empties the Map and thus reconnect cannot work.

I'll fix the .delete on a new PR.

wirednkod avatar Sep 23 '22 17:09 wirednkod

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

polkadot-js-bot avatar Sep 25 '22 19:09 polkadot-js-bot