mirror of
https://github.com/jambonz/jambonz-feature-server.git
synced 2025-12-19 04:17:44 +00:00
* add retry for http requestor * fix failing testcase * wip * update ws-requestor * wip * wip * wip
152 lines
4.5 KiB
JavaScript
152 lines
4.5 KiB
JavaScript
// Test for HttpRequestor retry functionality
|
|
const test = require('tape');
|
|
const sinon = require('sinon');
|
|
const proxyquire = require('proxyquire').noCallThru();
|
|
const { createMocks, setupBaseRequestorMocks } = require('./utils/mock-helper');
|
|
|
|
// Create mocks
|
|
const mocks = createMocks();
|
|
|
|
// Mock timeSeries module
|
|
const timeSeriesMock = sinon.stub().returns(mocks.MockAlerter);
|
|
|
|
// Mock the config with required properties
|
|
const configMock = {
|
|
HTTP_POOL: '0',
|
|
HTTP_POOLSIZE: '10',
|
|
HTTP_PIPELINING: '1',
|
|
HTTP_TIMEOUT: 5000,
|
|
HTTP_PROXY_IP: null,
|
|
HTTP_PROXY_PORT: null,
|
|
HTTP_PROXY_PROTOCOL: null,
|
|
NODE_ENV: 'test',
|
|
HTTP_USER_AGENT_HEADER: 'test-agent'
|
|
};
|
|
|
|
// Mock db-helpers
|
|
const dbHelpersMock = mocks.MockDbHelpers;
|
|
|
|
// Require HttpRequestor with mocked dependencies
|
|
const BaseRequestor = proxyquire('../lib/utils/base-requestor', {
|
|
'@jambonz/time-series': timeSeriesMock,
|
|
'../config': configMock,
|
|
'../../': { srf: { locals: { stats: mocks.MockStats } } }
|
|
});
|
|
|
|
// Setup BaseRequestor mocks
|
|
setupBaseRequestorMocks(BaseRequestor);
|
|
|
|
// Require HttpRequestor with mocked dependencies
|
|
const HttpRequestor = proxyquire('../lib/utils/http-requestor', {
|
|
'./base-requestor': BaseRequestor,
|
|
'../config': configMock,
|
|
'@jambonz/db-helpers': dbHelpersMock
|
|
});
|
|
|
|
// Setup utility function
|
|
const setupRequestor = () => {
|
|
const hook = { url: 'http://localhost/test', method: 'POST' };
|
|
const requestor = new HttpRequestor(mocks.MockLogger, 'AC123', hook, 'testsecret');
|
|
requestor.stats = mocks.MockStats;
|
|
return requestor;
|
|
};
|
|
|
|
// Cleanup function for tests
|
|
const cleanup = (requestor) => {
|
|
sinon.restore();
|
|
if (requestor && requestor.close) requestor.close();
|
|
};
|
|
|
|
test('HttpRequestor: should retry on connection errors when specified in hash', async (t) => {
|
|
const requestor = setupRequestor();
|
|
|
|
// Setup a URL with retry params in the hash
|
|
const urlWithRetry = 'http://localhost/test#rc=3&rp=ct,5xx';
|
|
|
|
// First two calls fail with connection refused, third succeeds
|
|
const requestStub = sinon.stub(requestor.client, 'request');
|
|
const error = new Error('Connection refused');
|
|
error.code = 'ECONNREFUSED';
|
|
|
|
// Fail twice, succeed on third try
|
|
requestStub.onCall(0).rejects(error);
|
|
requestStub.onCall(1).rejects(error);
|
|
requestStub.onCall(2).resolves({
|
|
statusCode: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
body: { json: async () => ({ success: true }) }
|
|
});
|
|
|
|
try {
|
|
const hook = { url: urlWithRetry, method: 'GET' };
|
|
const result = await requestor.request('verb:hook', hook, null);
|
|
|
|
t.equal(requestStub.callCount, 3, 'Should have retried twice for a total of 3 calls');
|
|
t.deepEqual(result, { success: true }, 'Should return successful response');
|
|
} catch (err) {
|
|
t.fail(`Should not throw an error: ${err.message}`);
|
|
}
|
|
|
|
cleanup(requestor);
|
|
t.end();
|
|
});
|
|
|
|
test('HttpRequestor: should respect retry count (rc) from hash', async (t) => {
|
|
const requestor = setupRequestor();
|
|
|
|
// Setup a URL with retry params in the hash - only retry once
|
|
const urlWithRetry = 'http://localhost/test#rc=1&rp=ct';
|
|
|
|
// All calls fail with connection refused
|
|
const requestStub = sinon.stub(requestor.client, 'request');
|
|
const error = new Error('Connection refused');
|
|
error.code = 'ECONNREFUSED';
|
|
|
|
// Always fail
|
|
requestStub.rejects(error);
|
|
|
|
try {
|
|
const hook = { url: urlWithRetry, method: 'GET' };
|
|
await requestor.request('verb:hook', hook, null);
|
|
t.fail('Should have thrown an error');
|
|
} catch (err) {
|
|
t.equal(requestStub.callCount, 2, 'Should have retried once for a total of 2 calls');
|
|
t.equal(err.code, 'ECONNREFUSED', 'Should throw the original error');
|
|
}
|
|
|
|
cleanup(requestor);
|
|
t.end();
|
|
});
|
|
|
|
test('HttpRequestor: should respect retry policy (rp) from hash', async (t) => {
|
|
const requestor = setupRequestor();
|
|
|
|
// Setup a URL with retry params in hash - only retry on 5xx errors
|
|
const urlWithRetry = 'http://localhost/test#rc=2&rp=5xx';
|
|
|
|
// Fail with 404 (should not retry since rp=5xx)
|
|
const requestStub = sinon.stub(requestor.client, 'request');
|
|
requestStub.resolves({
|
|
statusCode: 404,
|
|
headers: {},
|
|
body: {}
|
|
});
|
|
|
|
try {
|
|
const hook = { url: urlWithRetry, method: 'GET' };
|
|
await requestor.request('verb:hook', hook, null);
|
|
t.fail('Should have thrown an error');
|
|
} catch (err) {
|
|
t.equal(requestStub.callCount, 1, 'Should not retry on 404 when rp=5xx');
|
|
t.equal(err.statusCode, 404, 'Should throw 404 error');
|
|
}
|
|
|
|
cleanup(requestor);
|
|
t.end();
|
|
});
|
|
|
|
module.exports = {
|
|
setupRequestor,
|
|
cleanup
|
|
};
|