Fix close event not firing on wire
This commit is contained in:
parent
29b2796627
commit
29b79f25c0
21
wire.ts
21
wire.ts
@ -585,6 +585,7 @@ function wire_impl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wire supports re-connection; socket and read/write channels are null when closed
|
// wire supports re-connection; socket and read/write channels are null when closed
|
||||||
|
let connected = false;
|
||||||
let socket: Deno.Conn | null = null;
|
let socket: Deno.Conn | null = null;
|
||||||
let read_pop: Receiver<Uint8Array> | null = null;
|
let read_pop: Receiver<Uint8Array> | null = null;
|
||||||
let write_push: Sender<Uint8Array> | null = null;
|
let write_push: Sender<Uint8Array> | null = null;
|
||||||
@ -601,8 +602,9 @@ function wire_impl(
|
|||||||
else throw new WireError(`connection closed`);
|
else throw new WireError(`connection closed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// socket reader channel worker
|
|
||||||
async function read_socket(socket: Deno.Conn, push: Sender<Uint8Array>) {
|
async function read_socket(socket: Deno.Conn, push: Sender<Uint8Array>) {
|
||||||
|
let err;
|
||||||
|
try {
|
||||||
const header_size = 5;
|
const header_size = 5;
|
||||||
const read_buf = new Uint8Array(64 * 1024); // shared buffer for all socket reads
|
const read_buf = new Uint8Array(64 * 1024); // shared buffer for all socket reads
|
||||||
let buf = new Uint8Array(); // concatenated messages read so far
|
let buf = new Uint8Array(); // concatenated messages read so far
|
||||||
@ -620,6 +622,11 @@ function wire_impl(
|
|||||||
|
|
||||||
// there should be nothing left in buf if we gracefully exited
|
// there should be nothing left in buf if we gracefully exited
|
||||||
if (buf.length !== 0) throw new WireError(`unexpected end of stream`);
|
if (buf.length !== 0) throw new WireError(`unexpected end of stream`);
|
||||||
|
} catch (e) {
|
||||||
|
throw (err = e);
|
||||||
|
} finally {
|
||||||
|
if (connected) close(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_msg(msg: Uint8Array) {
|
function handle_msg(msg: Uint8Array) {
|
||||||
@ -668,8 +675,9 @@ function wire_impl(
|
|||||||
else throw new WireError(`connection closed`);
|
else throw new WireError(`connection closed`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// socket writer channel worker
|
|
||||||
async function write_socket(socket: Deno.Conn, pop: Receiver<Uint8Array>) {
|
async function write_socket(socket: Deno.Conn, pop: Receiver<Uint8Array>) {
|
||||||
|
let err;
|
||||||
|
try {
|
||||||
for (let buf; (buf = await pop()) !== null; ) {
|
for (let buf; (buf = await pop()) !== null; ) {
|
||||||
const bufs = [buf]; // proactively dequeue more queued msgs synchronously, if any
|
const bufs = [buf]; // proactively dequeue more queued msgs synchronously, if any
|
||||||
for (let i = 1, buf; (buf = pop.try()) !== null; ) bufs[i++] = buf;
|
for (let i = 1, buf; (buf = pop.try()) !== null; ) bufs[i++] = buf;
|
||||||
@ -677,17 +685,23 @@ function wire_impl(
|
|||||||
for (let i = 0, n = buf.length; i < n; )
|
for (let i = 0, n = buf.length; i < n; )
|
||||||
i += await socket.write(buf.subarray(i));
|
i += await socket.write(buf.subarray(i));
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw (err = e);
|
||||||
|
} finally {
|
||||||
|
if (connected) close(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function connect() {
|
async function connect() {
|
||||||
using _rlock = await rlock();
|
using _rlock = await rlock();
|
||||||
using _wlock = await wlock();
|
using _wlock = await wlock();
|
||||||
close(new WireError(`reconnecting`));
|
if (connected) return;
|
||||||
try {
|
try {
|
||||||
const s = (socket = await socket_connect(host, port));
|
const s = (socket = await socket_connect(host, port));
|
||||||
read_pop = channel.receiver((push) => read_socket(s, push));
|
read_pop = channel.receiver((push) => read_socket(s, push));
|
||||||
write_push = channel.sender((pop) => write_socket(s, pop));
|
write_push = channel.sender((pop) => write_socket(s, pop));
|
||||||
await handle_auth(); // run auth with rw lock
|
await handle_auth(); // run auth with rw lock
|
||||||
|
connected = true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw (close(e), e);
|
throw (close(e), e);
|
||||||
}
|
}
|
||||||
@ -701,6 +715,7 @@ function wire_impl(
|
|||||||
delete (params as Record<string, string>)[name];
|
delete (params as Record<string, string>)[name];
|
||||||
st_cache.clear(), (st_ids = 0);
|
st_cache.clear(), (st_ids = 0);
|
||||||
(tx_status = "I"), (tx_stack.length = 0);
|
(tx_status = "I"), (tx_stack.length = 0);
|
||||||
|
connected &&= (wire.emit("close", reason), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING
|
// https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-PIPELINING
|
||||||
|
Loading…
Reference in New Issue
Block a user