[x] Added tests for code changes or test/build only changes
[x] Updated the change log file (CHANGES.md|CHANGELOG.md) or test/build only changes
[x] Completed the PR template below:
Description
There is a memory leak when the client is instantiated inside a http request.
var Cloudant = require('./cloudant');
const http = require('http');
const server = http.createServer((req, res) => {
var cloudantBasic = Cloudant({
//account setting
plugins: 'cookieauth'
});
async function getDbList() {
return cloudantBasic.db.list();
}
getDbList().then(result => {
res.statusCode = 200;
res.end(JSON.stringify(result) + '\n');
console.log('####test success');
}).catch(err => {
res.statusCode = 401;
res.end(err.error + '\n');
console.log('####test failed', err);
});
});
server.listen(3000);
console.log('Server listening to port 3000. Press Ctrl+C to stop it.');
In this case when the server receives a request it will instantiate a client and after the response arrived all the request that went out toward Cloudant remained in the memory.
Approach
The default CloudantClient has the keepAlive option turned on and thank to this the opened sockets remain open and the last sent requests remain in the memory.
So the memory could have been cleared when every socket had been closed.
The current library supports only singleton usage. If it is not followed by the user there will be memory leak in the application.
However, to mitigate the problem I used bind functions to remove several references from the memory and created a specific Agent for token refreshment, where the keepAlive is set to false. This way the token refreshment requests will be closed when the request is completed.
The above code sample was executed with the previous library and the current version. I sent 8 request to see the memory consumption:
---
prev
now
diff
Request speed
7087 ms
7232 ms
+200ms
after 8 request
8.8 MB
8.9 MB
+0.1MB
5 minutes later
8.1 MB
7.8 MB
-0.3MB
After 5 minutes more memory could be freed up by the Garbage Collector.
Schema & API Changes
Not changed.
Security and Privacy
Not changed.
Testing
Updated 1 test case:
makes another renewal only after setting force renew: added done closure to catch method of the Promise. This way the test case will not remain in hanging if it fails.
Modified Finished token renewal. to Answer received to token renewal request.
Added 2 new debug log:
Checklist
CHANGES.md
|CHANGELOG.md
) or test/build only changesDescription
There is a memory leak when the client is instantiated inside a http request.
In this case when the server receives a request it will instantiate a client and after the response arrived all the request that went out toward Cloudant remained in the memory.
Approach
The default
CloudantClient
has thekeepAlive
option turned on and thank to this the opened sockets remain open and the last sent requests remain in the memory. So the memory could have been cleared when every socket had been closed. The current library supports only singleton usage. If it is not followed by the user there will be memory leak in the application. However, to mitigate the problem I usedbind
functions to remove several references from the memory and created a specific Agent for token refreshment, where thekeepAlive
is set tofalse
. This way the token refreshment requests will be closed when the request is completed.Mainly modified components: TokenManager, CoockieTokenManager, IAMTokenManager.
After 5 minutes more memory could be freed up by the Garbage Collector.
Schema & API Changes
Not changed.
Security and Privacy
Not changed.
Testing
Updated 1 test case:
makes another renewal only after setting force renew
: addeddone
closure tocatch
method of the Promise. This way the test case will not remain in hanging if it fails.Modified
Finished token renewal.
toAnswer received to token renewal request.
Added 2 new debug log:Succeeded to renew token
Failed to renew token