py-substrate-interface icon indicating copy to clipboard operation
py-substrate-interface copied to clipboard

Transaction resubmitted if WS connection times out

Open gilmouta opened this issue 4 years ago • 3 comments

After submitting a transaction and waiting for inclusion, if the transaction takes longer than the WS timeout, the WS connection is closed which triggers a reconnection attempt. However, the author_submitAndWatchExtrinsic is also reattempted, leading to the same transaction being sent (with the same nonce) and failing.

DEBUG:substrateinterface.base:RPC request #11: "author_submitAndWatchExtrinsic"
DEBUG:substrateinterface.base:Websocket subscription [hFjzC9cE1bnz2c4z] created
DEBUG:substrateinterface.base:Websocket result [hFjzC9cE1bnz2c4z #0]: {'jsonrpc': '2.0', 'method': 'author_extrinsicUpdate', 'params': {'result': 'ready', 'subscription': 'hFjzC9cE1bnz2c4z'}}
DEBUG:substrateinterface.base:Connection Closed; Trying to reconnecting...
DEBUG:substrateinterface.base:Connecting to wss://wss.testnet.moonbeam.network ...
DEBUG:substrateinterface.base:RPC request #12: "author_submitAndWatchExtrinsic"
Failed to send: {'code': 1012, 'message': 'Transaction is temporarily banned'}

Would it be possible to implement some sort of keep-alive messages to the WS during subscriptions, or alternatively make it so only the "watch" part is retried, not the "submit"?

gilmouta avatar Nov 10 '21 12:11 gilmouta

Would it be possible to implement some sort of keep-alive messages to the WS during subscriptions, or alternatively make it so only the "watch" part is retried, not the "submit"?

This is a kind of all or nothing approach I'm afraid. The transaction is submitted and the lib is waiting for a status update, and probably the proxy in front of the node is cleaning up the connections after a certain timeout. A keep-alive is also not possible because the execution is blocked until a new message is received (this will need a whole different async implementation)

I could make the reconnect optional though, so you will have more control when a disconnect takes place.

Also if you omit the wait_for_inclusion=True the transaction is submitted without waiting for status updates, so you won't have this problem. On the other hand then you can't know the block hash the extrinsic is included in.

arjanz avatar Nov 15 '21 10:11 arjanz

As a workaround, I'm calling substrate.websocket.ping() every X seconds on a different thread, and it seems to work keeping the websocket alive

gilmouta avatar Nov 15 '21 14:11 gilmouta

That is interesting, I wouldn't expect that would work.. Thanks for sharing

arjanz avatar Nov 16 '21 12:11 arjanz