feat(streamer): pcm tcp tap with reconnect backoff
This commit is contained in:
parent
8bca1767bd
commit
40ac86717a
1 changed files with 51 additions and 0 deletions
51
streamer/src/pcm-tap.ts
Normal file
51
streamer/src/pcm-tap.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
import { EventEmitter } from "node:events";
|
||||
import { Socket, connect } from "node:net";
|
||||
|
||||
export interface PcmTapOpts {
|
||||
host: string;
|
||||
port: number;
|
||||
reconnectInitialMs?: number;
|
||||
reconnectMaxMs?: number;
|
||||
}
|
||||
|
||||
export class PcmTap extends EventEmitter {
|
||||
private socket: Socket | null = null;
|
||||
private stopped = false;
|
||||
private backoff: number;
|
||||
|
||||
constructor(private opts: PcmTapOpts) {
|
||||
super();
|
||||
this.backoff = opts.reconnectInitialMs ?? 1000;
|
||||
}
|
||||
|
||||
start(): void {
|
||||
if (this.stopped) return;
|
||||
this.connect();
|
||||
}
|
||||
|
||||
stop(): void {
|
||||
this.stopped = true;
|
||||
this.socket?.destroy();
|
||||
}
|
||||
|
||||
private connect(): void {
|
||||
this.emit("connecting");
|
||||
const sock = connect({ host: this.opts.host, port: this.opts.port });
|
||||
this.socket = sock;
|
||||
|
||||
sock.on("connect", () => {
|
||||
this.emit("connected");
|
||||
this.backoff = this.opts.reconnectInitialMs ?? 1000;
|
||||
});
|
||||
sock.on("data", (chunk) => this.emit("data", chunk));
|
||||
sock.on("error", (err) => this.emit("warn", err));
|
||||
sock.on("close", () => {
|
||||
if (this.stopped) return;
|
||||
this.emit("disconnected");
|
||||
const max = this.opts.reconnectMaxMs ?? 30000;
|
||||
const wait = Math.min(this.backoff, max);
|
||||
this.backoff = Math.min(this.backoff * 2, max);
|
||||
setTimeout(() => this.connect(), wait);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue