fix: remove error cb handling for socket.send() calls

Fixes promise not ever being resolved
This commit is contained in:
PalmDevs
2024-03-29 19:51:19 +07:00
parent 6abb740994
commit 29544d4e01
3 changed files with 78 additions and 90 deletions

View File

@@ -34,14 +34,10 @@ export default class Client {
op: ServerOperation.Hello, op: ServerOperation.Hello,
d: null, d: null,
}) })
.then(() => {
this._listen() this._listen()
this.ready = true this.ready = true
this.#emitter.emit('ready') this.#emitter.emit('ready')
})
.catch(() => {
this.disconnect(DisconnectReason.ServerError)
})
} }
on<TOpName extends keyof ClientEventHandlers>(name: TOpName, handler: ClientEventHandlers[typeof name]) { on<TOpName extends keyof ClientEventHandlers>(name: TOpName, handler: ClientEventHandlers[typeof name]) {
@@ -57,12 +53,9 @@ export default class Client {
} }
send<TOp extends ServerOperation>(packet: Omit<Packet<TOp>, 's'>, sequence?: number) { send<TOp extends ServerOperation>(packet: Omit<Packet<TOp>, 's'>, sequence?: number) {
return new Promise<void>((resolve, reject) => { this.#throwIfDisconnected('Cannot send packet to client that has already disconnected')
this.#throwIfDisconnected('Cannot send packet to client that has already disconnected') this.#socket.send(serializePacket({ ...packet, s: sequence ?? this.currentSequence++ } as Packet<TOp>), err => {
this.#socket.send( throw err
serializePacket({ ...packet, s: sequence ?? this.currentSequence++ } as Packet<TOp>),
err => (err ? reject(err) : resolve()),
)
}) })
} }

View File

@@ -39,33 +39,31 @@ export default class Client {
async parseText(text: string) { async parseText(text: string) {
this.#throwIfNotReady() this.#throwIfNotReady()
return await this.ws this.ws.send({
.send({ op: ClientOperation.ParseText,
op: ClientOperation.ParseText, d: {
d: { text,
text, },
}, })
})
.then(() => {
// Since we don't have heartbeats anymore, this is fine.
// But if we add anything similar, this will cause another race condition
// To fix this, we can try adding a instanced function that would return the currentSequence
// and it would be updated every time a "heartbeat ack" packet is received
const expectedNextSeq = this.ws.currentSequence + 1
const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
awaitPacket(this.ws, op, expectedNextSeq, timeout)
return Promise.race([ // Since we don't have heartbeats anymore, this is fine.
awaitPkt(ServerOperation.ParsedText), // But if we add anything similar, this will cause another race condition
awaitPkt(ServerOperation.ParseTextFailed, this.ws.timeout + 5000), // To fix this, we can try adding a instanced function that would return the currentSequence
]) // and it would be updated every time a "heartbeat ack" packet is received
.then(pkt => { const expectedNextSeq = this.ws.currentSequence + 1
if (pkt.op === ServerOperation.ParsedText) return pkt.d const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
throw new Error('Failed to parse text, the API encountered an error') awaitPacket(this.ws, op, expectedNextSeq, timeout)
})
.catch(() => { return Promise.race([
throw new Error('Failed to parse text, the API did not respond in time') awaitPkt(ServerOperation.ParsedText),
}) awaitPkt(ServerOperation.ParseTextFailed, this.ws.timeout + 5000),
])
.then(pkt => {
if (pkt.op === ServerOperation.ParsedText) return pkt.d
throw new Error('Failed to parse text, the API encountered an error')
})
.catch(() => {
throw new Error('Failed to parse text, the API did not respond in time')
}) })
} }
@@ -77,61 +75,57 @@ export default class Client {
async parseImage(url: string) { async parseImage(url: string) {
this.#throwIfNotReady() this.#throwIfNotReady()
return await this.ws this.ws.send({
.send({ op: ClientOperation.ParseImage,
op: ClientOperation.ParseImage, d: {
d: { image_url: url,
image_url: url, },
}, })
})
.then(() => {
// See line 48
const expectedNextSeq = this.ws.currentSequence + 1
const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
awaitPacket(this.ws, op, expectedNextSeq, timeout)
return Promise.race([ // See line 48
awaitPkt(ServerOperation.ParsedImage), const expectedNextSeq = this.ws.currentSequence + 1
awaitPkt(ServerOperation.ParseImageFailed, this.ws.timeout + 5000), const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
]) awaitPacket(this.ws, op, expectedNextSeq, timeout)
.then(pkt => {
if (pkt.op === ServerOperation.ParsedImage) return pkt.d return Promise.race([
throw new Error('Failed to parse image, the API encountered an error') awaitPkt(ServerOperation.ParsedImage),
}) awaitPkt(ServerOperation.ParseImageFailed, this.ws.timeout + 5000),
.catch(() => { ])
throw new Error('Failed to parse image, the API did not respond in time') .then(pkt => {
}) if (pkt.op === ServerOperation.ParsedImage) return pkt.d
throw new Error('Failed to parse image, the API encountered an error')
})
.catch(() => {
throw new Error('Failed to parse image, the API did not respond in time')
}) })
} }
async trainMessage(text: string, label: string) { async trainMessage(text: string, label: string) {
this.#throwIfNotReady() this.#throwIfNotReady()
return await this.ws this.ws.send({
.send({ op: ClientOperation.TrainMessage,
op: ClientOperation.TrainMessage, d: {
d: { label,
label, text,
text, },
}, })
})
.then(() => {
// See line 48
const expectedNextSeq = this.ws.currentSequence + 1
const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
awaitPacket(this.ws, op, expectedNextSeq, timeout)
return Promise.race([ // See line 48
awaitPkt(ServerOperation.TrainedMessage), const expectedNextSeq = this.ws.currentSequence + 1
awaitPkt(ServerOperation.TrainMessageFailed, this.ws.timeout + 5000), const awaitPkt = (op: ServerOperation, timeout = this.ws.timeout) =>
]) awaitPacket(this.ws, op, expectedNextSeq, timeout)
.then(pkt => {
if (pkt.op === ServerOperation.TrainedMessage) return return Promise.race([
throw new Error('Failed to train message, the API encountered an error') awaitPkt(ServerOperation.TrainedMessage),
}) awaitPkt(ServerOperation.TrainMessageFailed, this.ws.timeout + 5000),
.catch(() => { ])
throw new Error('Failed to train message, the API did not respond in time') .then(pkt => {
}) if (pkt.op === ServerOperation.TrainedMessage) return
throw new Error('Failed to train message, the API encountered an error')
})
.catch(() => {
throw new Error('Failed to train message, the API did not respond in time')
}) })
} }

View File

@@ -49,6 +49,7 @@ export class ClientWebSocketManager {
}, this.timeout) }, this.timeout)
this.#socket.on('open', () => { this.#socket.on('open', () => {
this.disconnected = false
clearTimeout(timeout) clearTimeout(timeout)
this.#listen() this.#listen()
rs() rs()
@@ -107,9 +108,9 @@ export class ClientWebSocketManager {
send<TOp extends ClientOperation>(packet: Packet<TOp>) { send<TOp extends ClientOperation>(packet: Packet<TOp>) {
this.#throwIfDisconnected('Cannot send a packet when already disconnected from the server') this.#throwIfDisconnected('Cannot send a packet when already disconnected from the server')
return new Promise<void>((resolve, reject) => this.#socket.send(serializePacket(packet), err => {
this.#socket.send(serializePacket(packet), err => (err ? reject(err) : resolve())), throw err
) })
} }
/** /**