mqrpc
Version:
💫 Easy RPC over RabbitMQ
70 lines (69 loc) • 3.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const ava_1 = require("ava");
const uuid = require("uuid/v4");
const amqp = require("amqplib");
const _config_1 = require("./_config");
const _utils_1 = require("./_utils");
const RpcServer_1 = require("../lib/RpcServer");
const RpcClient_1 = require("../lib/RpcClient");
const clientErrors = require("../lib/RpcClient/errors");
const Timer_1 = require("../lib/Timer");
let connection;
ava_1.default.before(async () => {
connection = await amqp.connect(_config_1.AMQP_URL);
});
ava_1.default.after.always(async () => {
await connection.close();
});
ava_1.default.beforeEach(async (t) => {
const rpcExchangeName = `mqrpc.${uuid()}`; // make sure each call goes to the right server
t.context.client = new RpcClient_1.default({ amqpClient: { connection }, rpcClient: { rpcExchangeName, idleTimeout: 50 } });
t.context.server = new RpcServer_1.default({ amqpClient: { connection }, rpcServer: { rpcExchangeName } });
await t.context.server.init();
await t.context.client.init();
t.context.server.registerDebugProcedures();
});
ava_1.default.afterEach(async (t) => {
await Promise.all([
t.context.client.term(),
t.context.server.term()
]);
});
ava_1.default('[integration] an RPC call resolves to the returned value from the procedure', async (t) => {
const res = await t.context.client.call('mqrpc.echo', 42);
t.is(res, 42);
});
ava_1.default('[integration] calling an unknown procedure raises', async (t) => {
await t.throws(t.context.client.call('doesnt.exist'), clientErrors.ServerError, 'Server Error - NoSuchOperation: No operation named "doesnt.exist" has been registered');
});
ava_1.default('[integration] works nicely with no arguments and no returns', async (t) => {
t.context.server.register('noop', () => { });
t.is(await t.context.client.call('noop'), undefined);
});
ava_1.default.serial('[integration] clears call timeouts on resolution and rejection', async (t) => {
const resolves = t.context.client.call('mqrpc.echo', 42);
const rejects = t.context.client.call('doesnt.exist');
const errorMsg = 'Server Error - NoSuchOperation: No operation named "doesnt.exist" has been registered';
const unhandledListener = err => t.fail(`Uncaught Error: ${err.message}`);
process.on('unhandledRejection', unhandledListener);
await t.notThrows(resolves);
await t.throws(rejects, clientErrors.ServerError, errorMsg);
await _utils_1.delay(50);
process.removeListener('unhandledRejection', unhandledListener);
t.pass();
});
ava_1.default('[integration] a slow call still works with well configured timeouts', async (t) => {
t.context.server.register('mqrpc.slow', () => _utils_1.delay(200).then(() => 42));
// works fine locally with smaller numbers, but not over the wire in CI
t.context.client.idleTimeout = 150;
t.context.client.ackTimeout = 250;
t.context.client.callTimeout = 500;
t.is(await t.context.client.call('mqrpc.slow'), 42);
});
ava_1.default('[integration] a slow call fails with a short callTimeout', async (t) => {
t.context.server.register('mqrpc.slow', () => _utils_1.delay(100).then(() => 42));
t.context.client.callTimeout = 50;
await t.throws(t.context.client.call('mqrpc.slow'), Timer_1.TimeoutExpired, 'callTimeout expired after 50ms');
await _utils_1.delay(150); // dont close channel yet (server will still reply)
});