This repository was archived by the owner on Sep 18, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 42
This repository was archived by the owner on Sep 18, 2025. It is now read-only.
[Memory-Leak]: Unsubscribe and return from iterator is missed, when using subscription´s onDisconnect #16
Copy link
Copy link
Open
Labels
help wantedExtra attention is neededExtra attention is needed
Description
Notes
- Memory-Leak is appearing
- We like to make this project more resilient to memory leaks
- Maybe a code Smell at pullValue could be assumed
- In some eslint rules, for example, it is strongly recommended to avoid creating promises via "new"
- The code was taken into Steffi-Graph for debugging analysis
- Implemented subscriptions onDisconnect to close the connection, which is triggered from the client (closing his browsertab for example)
Analysis of Log Data (We found a moment, where unsubscribe would be missed):
steffi-graph: subscribe { topicName: 'article',
steffi-graph: onMessage: [AsyncFunction: bound pushValue],
steffi-graph: options: undefined }
steffi-graph: getSubscriptions
steffi-graph: exists? true article
steffi-graph: subscribe all [ 6 ]
steffi-graph: next Promise { [ 6 ] } listening?: true
steffi-graph: (not resolved yet) pullQueue: pushed resolve reference to queue with length: 1
//
// Unsubscribe and return seems to be missing here!
//
steffi-graph: onDissconnect initial context { auth:
steffi-graph: { user:
steffi-graph: { accountname: 'admin',
steffi-graph:
steffi-graph: isAuthenticated: true,
steffi-graph: scope:
steffi-graph: ...
steffi-graph: token: ...
//
// Websocket connection to specific client should be closed here after onDisconnect
//
Question
Would an alternative approach make sense here?
New Approach to discuss
...
Feedback from Nacho (Google) to this Implementation
It seems that you have 800k instances of Promises, which is taking 80% of your memory. This most frequently happens when a Promise is neither resolved or rejected, which looking at your code could be happening at pullValue:
pullValue() {
return new Promise(resolve => {
if (this.pushQueue.length !== 0) {
const res = this.pushQueue.shift()
resolve({ value: res, done: false })
} else {
this.pullQueue.push(resolve)
}
})
}
You are delaying the resolution of the Promise by adding it to pullQueue, could it be that nobody is pulling that data later? My guess is that there is no cleanup of these delayed Promises by either resolving or rejecting.
A test case for this would be useful. I am forwarding this to a colleague in case they can offer an additional insight.
Reactions are currently unavailable
Metadata
Metadata
Labels
help wantedExtra attention is neededExtra attention is needed