Wyle.Gong-巩文昕 7a1aae1e2f ui
2025-04-23 11:21:08 +08:00

254 lines
6.0 KiB
JavaScript

/*
* Copyright 2018-2023 The NATS Authors
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const test = require("ava");
const { NatsServer, wsConfig } = require("./helpers/launcher");
const {
createInbox,
Events,
ErrorCode,
deferred,
DebugEvents,
} = require("../lib/nats-base-client/internal_mod");
const { Lock } = require("./helpers/lock");
const {
connect,
} = require("./index");
test("reconnect - should receive when some servers are invalid", async (t) => {
const ns = await NatsServer.start(wsConfig());
const servers = ["ws://127.0.0.1:7", `ws://127.0.0.1:${ns.websocket}`];
const nc = await connect({ servers: servers, noRandomize: true });
const lock = Lock(1);
const subj = createInbox();
await nc.subscribe(subj, {
callback: () => {
lock.unlock();
},
});
nc.publish(subj);
await lock;
await nc.close();
await ns.stop();
// @ts-ignore
const a = nc.protocol.servers.getServers();
t.is(a.length, 1);
t.true(a[0].didConnect);
});
test("reconnect - events", async (t) => {
const ns = await NatsServer.start(wsConfig());
let nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
waitOnFirstConnect: true,
reconnectTimeWait: 100,
maxReconnectAttempts: 10,
});
let disconnects = 0;
let reconnecting = 0;
const status = nc.status();
(async () => {
for await (const e of status) {
switch (e.type) {
case "disconnect":
disconnects++;
break;
case "reconnecting":
reconnecting++;
break;
default:
t.log(e);
}
}
})().then();
await ns.stop();
try {
await nc.closed();
} catch (err) {
t.is(err.code, ErrorCode.ConnectionRefused);
}
t.is(disconnects, 1, "disconnects");
t.is(reconnecting, 10, "reconnecting");
});
test("reconnect - reconnect not emitted if suppressed", async (t) => {
const ns = await NatsServer.start(wsConfig());
let nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
reconnect: false,
});
let disconnects = 0;
(async () => {
for await (const e of nc.status()) {
switch (e.type) {
case Events.Disconnect:
disconnects++;
break;
case DebugEvents.Reconnecting:
t.fail("shouldn't have emitted reconnecting");
break;
}
}
})().then();
await ns.stop();
await nc.closed();
t.pass();
});
test("reconnect - reconnecting after proper delay", async (t) => {
const ns = await NatsServer.start(wsConfig());
let nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
reconnectTimeWait: 500,
maxReconnectAttempts: 1,
});
// @ts-ignore
const serverLastConnect = nc.protocol.servers.getCurrentServer().lastConnect;
const dt = deferred();
const _ = (async () => {
for await (const e of nc.status()) {
switch (e.type) {
case DebugEvents.Reconnecting:
const elapsed = Date.now() - serverLastConnect;
dt.resolve(elapsed);
break;
}
}
})();
await ns.stop();
const elapsed = await dt;
t.true(elapsed >= 500 && elapsed <= 700, `elapsed was ${elapsed}`);
await nc.closed();
});
test("reconnect - indefinite reconnects", async (t) => {
let ns = await NatsServer.start(wsConfig());
let nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
reconnectTimeWait: 100,
maxReconnectAttempts: -1,
});
let disconnects = 0;
let reconnects = 0;
let reconnect = false;
(async () => {
for await (const e of nc.status()) {
switch (e.type) {
case Events.Disconnect:
disconnects++;
break;
case Events.Reconnect:
reconnect = true;
nc.close();
break;
case DebugEvents.Reconnecting:
reconnects++;
break;
}
}
})().then();
await ns.stop();
const lock = Lock(1);
setTimeout(async (t) => {
ns = await ns.restart();
lock.unlock();
}, 1000);
await nc.closed();
await ns.stop();
await lock;
await ns.stop();
t.true(reconnects > 5);
t.true(reconnect);
t.is(disconnects, 1);
});
test("reconnect - jitter", async (t) => {
let ns = await NatsServer.start(wsConfig());
let called = false;
const h = () => {
called = true;
return 15;
};
let hasDefaultFn;
let dc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
reconnect: false,
});
hasDefaultFn = typeof dc.options.reconnectDelayHandler === "function";
let nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
maxReconnectAttempts: 1,
reconnectDelayHandler: h,
});
await ns.stop();
await nc.closed();
await dc.closed();
t.true(called);
t.true(hasDefaultFn);
});
test("reconnect - internal disconnect forces reconnect", async (t) => {
const ns = await NatsServer.start(wsConfig());
const nc = await connect({
servers: `ws://127.0.0.1:${ns.websocket}`,
reconnect: true,
reconnectTimeWait: 200,
});
let stale = false;
let disconnect = false;
const lock = Lock();
(async () => {
for await (const e of nc.status()) {
switch (e.type) {
case DebugEvents.StaleConnection:
stale = true;
break;
case Events.Disconnect:
disconnect = true;
break;
case Events.Reconnect:
lock.unlock();
break;
}
}
})().then();
nc.protocol.disconnect();
await lock;
t.true(disconnect, "disconnect");
t.true(stale, "stale");
await nc.close();
await ns.stop();
});