Created
April 9, 2023 02:32
-
-
Save mtorre4580/17ef9120aafe5e1f5dbdf4a186c84229 to your computer and use it in GitHub Desktop.
Example http-client with circuit breaker support and keep alive connection with axios in Node.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const axios = require("axios"); | |
const Agent = require("agentkeepalive"); | |
const CircuitBreaker = require("opossum"); | |
// Replace with your configs | |
const TIMEOUT_DEFAULT = 2500; | |
const MAX_SOCKETS = 100; | |
const MAX_FREE_SOCKET = 10; | |
const TIME_OUT_KEEP_ALIVE = 60000; | |
const FREE_SOCKET_TIMEOUT = 30000; | |
const RESET_TIMEOUT_CIRCUIT_BREAKER = 15000; | |
const ERROR_THRESHOLD_PERCENT_CIRCUIT_BREAKER = 25; | |
// Replace with your logger | |
const logger = console; | |
/** | |
* Create the configuration for agent http | |
* @returns {object} | |
*/ | |
function createHttpAgent() { | |
return new Agent({ | |
maxSockets: MAX_SOCKETS, | |
maxFreeSockets: MAX_FREE_SOCKET, | |
timeout: TIME_OUT_KEEP_ALIVE, | |
freeSocketTimeout: FREE_SOCKET_TIMEOUT, | |
}); | |
} | |
/** | |
* Create the configuration for agent https | |
* @returns {object} | |
*/ | |
function createHttpsAgent() { | |
return new Agent.HttpsAgent({ | |
maxSockets: MAX_SOCKETS, | |
maxFreeSockets: MAX_FREE_SOCKET, | |
timeout: TIME_OUT_KEEP_ALIVE, | |
freeSocketTimeout: FREE_SOCKET_TIMEOUT, | |
}); | |
} | |
/** | |
* Create an instance with axios with keep alive feature | |
* @param {object} config | |
* @returns {object} | |
*/ | |
function createInstance(config) { | |
const httpClient = axios.create(config || { timeout: TIMEOUT_DEFAULT }); | |
httpClient.defaults.httpAgent = createHttpAgent(); | |
httpClient.defaults.httpsAgent = createHttpsAgent(); | |
return httpClient; | |
} | |
/** | |
* Create an instance for the circuit breaker for any method | |
* @param {Function} handler | |
* @param {object} options | |
* @returns CircuitBreaker | |
*/ | |
function createCircuitBreaker(handler, options) { | |
const circuitBreaker = new CircuitBreaker(handler, { | |
resetTimeout: RESET_TIMEOUT_CIRCUIT_BREAKER, | |
errorThresholdPercentage: ERROR_THRESHOLD_PERCENT_CIRCUIT_BREAKER, | |
timeout: TIMEOUT_DEFAULT, | |
errorFilter: (err) => err.statusCode !== 401 || err.statusCode !== 403, | |
...options, | |
}); | |
circuitBreaker.on("halfOpen", () => { | |
logger.warn( | |
`The Circuit Breaker is "HALF_OPEN" for "${circuitBreaker.name}"` | |
); | |
}); | |
circuitBreaker.on("open", () => { | |
logger.error(`The Circuit Breaker is "OPEN" for "${circuitBreaker.name}"`); | |
}); | |
circuitBreaker.on("success", (response) => { | |
logger.debug(`API response: ${JSON.stringify(response, null, 2)}`); | |
}); | |
return circuitBreaker; | |
} | |
// Example using the instance axios with the circuit breaker support | |
// Only for check, remove | |
(async () => { | |
async function getCountryArgentina() { | |
const { data } = await axiosInstance.get( | |
`https://restcountries.com/v3.1/name/argentina`, | |
{ | |
params: { fields: "name, capital, flag" }, | |
} | |
); | |
return data; | |
} | |
const axiosInstance = createInstance(); | |
const circuitBreaker = createCircuitBreaker(getCountryArgentina); | |
await circuitBreaker.fire(); | |
})(); | |
module.exports = { createInstance, createCircuitBreaker }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment