postchain-client
Version:
Client library for accessing a Postchain node through REST.
114 lines • 6.36 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { FailoverStrategy, Method } from "../../src/blockchainClient/enums";
import { retryRequest } from "../../src/blockchainClient/failoverStrategies";
import { handleRequest } from "../../src/blockchainClient/httpUtil";
import { createNodeManager } from "../../src/blockchainClient/nodeManager";
import { mockNodeUrls } from "../common/mocks";
jest.mock("../../src/blockchainClient/httpUtil", () => ({
handleRequest: jest.fn(),
}));
const mockHandleRequest = handleRequest;
describe("Sticky node feature", () => {
afterEach(() => {
jest.clearAllMocks();
jest.restoreAllMocks();
});
describe("sticky node logic", () => {
const endpointUrlPool = mockNodeUrls;
const retryRequestConfig = {
endpointPool: endpointUrlPool.map(url => ({ url, whenAvailable: 0 })),
failoverStrategy: FailoverStrategy.TryNextOnError,
statusPollCount: 1,
statusPollInterval: 1,
attemptsPerEndpoint: 2,
attemptInterval: 100,
unreachableDuration: 5000,
};
const successfullResponse = { error: null, statusCode: 200, rspBody: "" };
const failedResponse = { error: null, statusCode: 500, rspBody: "" };
it("should NOT retain a node when sticky node is disabled.", () => __awaiter(void 0, void 0, void 0, function* () {
mockHandleRequest
.mockResolvedValueOnce(successfullResponse)
.mockResolvedValueOnce(successfullResponse)
.mockResolvedValueOnce(successfullResponse);
const nodeManager = createNodeManager({
nodeUrls: endpointUrlPool,
useStickyNode: false,
unavailableDuration: 5000,
});
for (let i = 0; i < 3; i++) {
yield retryRequest({
method: Method.GET,
path: "/path",
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
validateStatusCode: statusCode => ![500, 503].includes(statusCode),
});
}
const requestNodes = mockHandleRequest.mock.calls.map(call => call[2]);
expect(requestNodes.every(node => node === requestNodes[0])).toBe(false);
}));
it("should be possible to retain the same node in between requests.", () => __awaiter(void 0, void 0, void 0, function* () {
mockHandleRequest
.mockResolvedValueOnce(successfullResponse)
.mockResolvedValueOnce(successfullResponse)
.mockResolvedValueOnce(successfullResponse);
const nodeManager = createNodeManager({
nodeUrls: endpointUrlPool,
useStickyNode: true,
unavailableDuration: 5000,
});
for (let i = 0; i < 3; i++) {
yield retryRequest({
method: Method.GET,
path: "/path",
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
validateStatusCode: statusCode => ![500, 503].includes(statusCode),
});
}
const selectedStickyNode = mockHandleRequest.mock.calls[0][2];
expect(mockHandleRequest.mock.calls[1][2]).toBe(selectedStickyNode);
expect(mockHandleRequest.mock.calls[2][2]).toBe(selectedStickyNode);
expect(mockHandleRequest).toHaveBeenCalledTimes(3);
}));
it("should set new sticky node, when the original one fails.", () => __awaiter(void 0, void 0, void 0, function* () {
mockHandleRequest
.mockResolvedValueOnce(failedResponse)
.mockResolvedValueOnce(failedResponse)
.mockResolvedValueOnce(failedResponse)
.mockResolvedValueOnce(successfullResponse)
.mockResolvedValueOnce(failedResponse)
.mockResolvedValueOnce(failedResponse)
.mockResolvedValueOnce(successfullResponse);
const nodeManager = createNodeManager({
nodeUrls: endpointUrlPool,
useStickyNode: true,
unavailableDuration: 5000,
});
for (let i = 0; i < 2; i++) {
yield retryRequest({
method: Method.GET,
path: "/path",
config: Object.assign(Object.assign({}, retryRequestConfig), { nodeManager }),
validateStatusCode: statusCode => ![500, 503].includes(statusCode),
});
}
const nodeOfRequest = mockHandleRequest.mock.calls.map(call => call[2]);
expect(nodeOfRequest[0]).toBe(nodeOfRequest[1]); // Both requests should have used the same node, and both should have failed.
expect(nodeOfRequest[2]).not.toBe(nodeOfRequest[0]); // Should have picked a new node, and the request should have failed.
expect(nodeOfRequest[3]).toBe(nodeOfRequest[2]); // Should have retried on a new node, succeeded, and set it as the new sticky node.
expect(nodeOfRequest[4]).toBe(nodeOfRequest[3]); // Should have used the sticky node, but request should have failed.
expect(nodeOfRequest[5]).toBe(nodeOfRequest[4]); // Should have used the sticky node again, but request should have failed.
expect(nodeOfRequest[6]).not.toBe(nodeOfRequest[5]); // Should have picked a new node and succeeded.
expect(mockHandleRequest).toHaveBeenCalledTimes(7);
}));
});
});
//# sourceMappingURL=stickyNode.test.js.map