Skip to content

Commit

Permalink
Added agentIdleTimeout field to discard agents after timeouts
Browse files Browse the repository at this point in the history
  • Loading branch information
parthverma1 committed Aug 15, 2024
1 parent e7119b5 commit d8d52e6
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -976,6 +976,7 @@ request.defaults({
[linux-timeout]: http://www.sekuda.com/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout

- `maxResponseSize` - Abort request if the response size exceeds this threshold (bytes).
- `agentIdleTimeout` - set to number of milliseconds after which the agent should be discarded for reuse
---

- `localAddress` - local interface to bind for network connections.
Expand Down
15 changes: 9 additions & 6 deletions request.js
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ Request.prototype.init = function (options) {
self.agent = false
} else {
try {
self.agent = self.agent || self.getNewAgent()
self.agent = self.agent || self.getNewAgent({agentIdleTimeout: options.agentIdleTimeout})
} catch (error) {
// tls.createSecureContext() throws on bad options
return self.emit('error', error)
Expand Down Expand Up @@ -774,7 +774,7 @@ Request.prototype.init = function (options) {
})
}

Request.prototype.getNewAgent = function () {
Request.prototype.getNewAgent = function ({agentIdleTimeout}) {
var self = this
var Agent = self.agentClass
var options = {}
Expand Down Expand Up @@ -900,24 +900,27 @@ Request.prototype.getNewAgent = function () {
}
}

if (self.pool === globalPool && !poolKey && Object.keys(options).length === 0 && self.httpModule.globalAgent) {
if (self.pool === globalPool && !poolKey && Object.keys(options).length === 0 && self.httpModule.globalAgent && typeof agentIdleTimeout !== 'number') {
// not doing anything special. Use the globalAgent
return self.httpModule.globalAgent
}

// we're using a stored agent. Make sure it's protocol-specific
poolKey = self.protocolVersion + ':' + self.uri.protocol + poolKey

let agent = self.pool[poolKey]

// generate a new agent for this setting if none yet exists
if (!self.pool[poolKey]) {
self.pool[poolKey] = new Agent(options)
if (!agent || (typeof agentIdleTimeout === 'number' && (agent.lastUsedAt ?? 0) + agentIdleTimeout < Date.now())) {
agent = self.pool[poolKey] = new Agent(options)
// properly set maxSockets on new agents
if (self.pool.maxSockets) {
self.pool[poolKey].maxSockets = self.pool.maxSockets
}
}

return self.pool[poolKey]
agent.lastUsedAt = Date.now()
return agent
}

Request.prototype.start = function () {
Expand Down
70 changes: 70 additions & 0 deletions tests/test-agentIdleTimeout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'use strict'

var server = require('./server')
var request = require('../index')
var tape = require('tape')
const { response } = require('har-validator')

var s

function createServer () {
const s = server.createServer()

s.on('/', function (req, res) {
res.writeHead(200, { 'content-type': 'text/plain' })
res.end()
})

return s
}

tape('setup', function (t) {
s = createServer()
s.listen(0, function () {
t.end()
})
})

tape('should reuse the same agent', function (t) {
const data = {
url: s.url + '/',
agentIdleTimeout: 1000
}

const r1 = request(data, function (err, res) {
t.equal(err, null)
t.equal(res.statusCode, 200)
const r2 = request(data, function (err) {
t.equal(err, null)
t.end()
t.equal(r1.agent.identifier, r2.agent.identifier)
})
})
r1.agent.identifier = '1234'
})

tape('should use new agent after timeout', function (t) {
const data = {
url: s.url + '/',
agentIdleTimeout: 100
}

const r1 = request(data, function (err, res) {
t.equal(err, null)
t.equal(res.statusCode, 200)
setTimeout(() => {
const r2 = request(data, function (err) {
t.equal(err, null)
t.end()
t.notEqual(r1.agent.identifier, r2.agent.identifier)
})
}, 200)
})
r1.agent.identifier = '12345'
})

tape('cleanup', function (t) {
s.close(function () {
t.end()
})
})

0 comments on commit d8d52e6

Please sign in to comment.