In the Daml Finance Reference App we make use of
useStreamQueries a lot. I realized that the websocket connections don’t get released / closed when I eg. navigate away from a page that calls
useStreamQueries. This leads to a lot of ununsed connections staying open, and when it reaches ~500 of them (as evidenced in the sandbox logs) the whole app crashes and burns.
Is there a way to explicitly release those connections, or if not, what is the “policy” of when these get closed?
On the json-api side, it’s determined by the websocket-config.max-duration setting. The default is a very long 2 hours. You can turn this way down, because the
@daml/ledger library should handle reconnecting for you if the page is still active.
However, you must also consider the reconnectThreshold setting in your
new Ledger invocations. The default is
30000 (30 seconds); ensure that your json-api isn’t set up to disconnect faster than
@daml/ledger can detect a healthy connection. (Some further discussion of proposed reconnect semantics here.)
Assuming you mean “when the React components get unmounted”, I’m not sure what to suggest here. The underlying
@daml/ledger functions seem to return explicit streams on which you can call
.close, but it looks like those streams are not exposed by the
@daml/react library. Looking through what I believe to be the relevant code, it looks like we plug the stream directly into a React “state” behind the scenes, in a sort-of separate JS “thread”, and that’s the only place where the stream object itself is accessible.
I suppose this works well enough to get started quickly on a prototype (which is the main goal of the
@daml/react library), or if you’re in a situation where you know all of the streams you need to open from the very first render of the page (i.e. you don’t expect to dynamically change the set of open streams based on user behaviour), but, as you’ve found out, it’s an approach that definitely has its limits.
My best recommendation at this point would be to use the
@daml/ledger library more directly. The
useLedger function from the
@daml/react library returns a
Ledger object from the
@daml/ledger library, so you may operate on that more explicitly. You’ll need to add the “close stream” operation yourself, probably on
componentWillUnmount or similar - my React is very rusty at this point, I think it’s been about five to six years since I last looked into React in depth.
Thanks both for the answers. Setting the max-duration down to 1 minute seems to have remediated the situation sufficiently, it’s now recycling the connections regularily. Maybe consider changing the default for this setting.
For reference, here’s the full JSON API config I’m using now:
address = "0.0.0.0"
port = 7575
address = "localhost"
port = 6865
max-duration = 1m
And I use this setting in
daml.yaml to load the config when running