-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
My app uses connect.onAccountChange() and connect.removeAccountChangeListener() and is keeps open 100-200 subscritions.
Main libraries:
- @solana/web3.js ^1.91.7
- rpc-websockets ^7.5.1
The app crashes when it tries to use subscribe/unsubscribe using onAccountChange()/removeAccountChangeListener() and the Websocket is not with readyState===1.
Fail when trying to subscribe (it goes in an infinite loop with all the accounts handled at that moment):
accountSubscribe error for argument [
'F3TuARNBKV6U7uA4DvLZUUgmcAAEtpDeMyC36Zb1CPnR',
{ encoding: 'base64', commitment: 'confirmed' }
] Tried to call a JSON-RPC method `accountSubscribe` but the socket was not `CONNECTING` or `OPEN` (`readyState` was 3)
Fail when trying to unsubscribe (it goes in an infinite loop with all the accounts handled at that moment):
accountUnsubscribe error: Tried to call a JSON-RPC method `accountUnsubscribe` but the socket was not `CONNECTING` or `OPEN` (`readyState` was 2)
And finally crashes:
<--- Last few GCs --->
[1996:0000021E09A48EE0] 19434569 ms: Mark-Compact 4047.4 (4134.3) -> 4032.6 (4135.3) MB, 1414.30 / 0.00 ms (average mu = 0.253, current mu = 0.245) allocation failure; scavenge might not succeed
[1996:0000021E09A48EE0] 19436455 ms: Mark-Compact 4048.4 (4135.3) -> 4033.8 (4136.6) MB, 1735.41 / 0.00 ms (average mu = 0.169, current mu = 0.080) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 00007FF6430BC81B node::SetCppgcReference+17979
2: 00007FF643026674 DSA_meth_get_flags+89316
3: 00007FF643AA4871 v8::Isolate::ReportExternalAllocationLimitReached+65
4: 00007FF643A8DFC8 v8::Function::Experimental_IsNopFunction+1336
5: 00007FF6438EFA70 v8::Platform::SystemClockTimeMillis+659328
6: 00007FF6438FBCF3 v8::Platform::SystemClockTimeMillis+709123
7: 00007FF6438F9654 v8::Platform::SystemClockTimeMillis+699236
8: 00007FF6438EC790 v8::Platform::SystemClockTimeMillis+646304
9: 00007FF643901E0A v8::Platform::SystemClockTimeMillis+733978
10: 00007FF643902687 v8::Platform::SystemClockTimeMillis+736151
11: 00007FF643910F7F v8::Platform::SystemClockTimeMillis+795791
12: 00007FF6435D1CA5 v8::CodeEvent::GetFunctionName+116773
As far as WebSocket.readyState is not visible, I have tried to catch the error in different ways but I can't catch it.
Option 1: try-catch
const removeListener = async (id:number) =>{
let ok:boolean = false;
let n_times:number = 1;
do{
try{
await connection.removeAccountChangeListener(id);
ok = true;
}catch(error){
ok = false;
}
if (!ok){
await delay(1000); // custom function to delay 1s
console.log(`Try: ${n_times}, Nop: ${id}`);
n_times++;
}else{
console.log(`Try: ${n_times}, Disconnected: ${id}`);
}
}while(!ok);
}
Option 2: catch chained
const removeListener = async (id:number) =>{
let ok:boolean = false;
let n_times:number = 1;
do{
ok = true;
await connection.removeAccountChangeListener(id).catch(error){
ok = false;
}
if (!ok){
await delay(1000); // custom function to delay 1s
console.log(`Try: ${n_times}, Nop: ${id}`);
n_times++;
}else{
console.log(`Try: ${n_times}, Disconnected: ${id}`);
}
}while(!ok);
}
These errors are in file "rpc-websocket.ts" call and notify reject funcions:
new Error(
'Tried to call a JSON-RPC method `' +
args[0] +
'` but the socket was not `CONNECTING` or `OPEN` (`readyState` was ' +
readyState +
')',
),
But I think the problem could came from 'connection.ts' which has this piece of code with a no controlled catch, because I can't catch the error:
/**
* @internal
*/
private _handleServerNotification<
TCallback extends SubscriptionConfig['callback'],
>(
serverSubscriptionId: ServerSubscriptionId,
callbackArgs: Parameters<TCallback>,
): void {
const callbacks =
this._subscriptionCallbacksByServerSubscriptionId[serverSubscriptionId];
if (callbacks === undefined) {
return;
}
callbacks.forEach(cb => {
try {
cb(
// I failed to find a way to convince TypeScript that `cb` is of type
// `TCallback` which is certainly compatible with `Parameters<TCallback>`.
// See https://github.com/microsoft/TypeScript/issues/47615
// @ts-ignore
...callbackArgs,
);
} catch (e) {
console.error(e);
}
});
}
Few questions open en Solana Stack Exchange:
https://solana.stackexchange.com/questions/15643/accountunsubscribe-and-accountsubscribe-error-tried-to-call-a-json-rpc-method-w
https://solana.stackexchange.com/questions/15698/solana-web3-js-it-is-not-possible-to-detect-websocket-error
Could it be a bug?
How can I handle or catch this error?
How can I check websocket.readyStatus to avoid subscribe/unsubscribe when it is not in OPEN or CONNECTING?