Skip to content

Commit

Permalink
fix: handle attempt to send response when port is disconnected
Browse files Browse the repository at this point in the history
  • Loading branch information
fellowseb committed Feb 26, 2024
1 parent 4345cff commit 956ab05
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 22 deletions.
40 changes: 25 additions & 15 deletions src/Transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,23 +177,33 @@ export class Transport {
// Call local handlers with the request data
callHandlers(data, handlers)
// If the resulting promise is fulfilled, send a response to the far end
.then(response => this._channel.send({
type: 'response',
slotName,
id,
data: response,
param
}))
.then(async (response) => {
await this.autoReconnect()
if (!this.isDisconnected()) {
this._channel.send({
type: 'response',
slotName,
id,
data: response,
param
})
}
})

// If the resulting promise is rejected, send an error to the far end
.catch((error: Error) => this._channel.send({
id,
message: `${error}`,
param,
slotName,
stack: error.stack || '',
type: 'error'
}))
.catch(async (error: Error) => {
await this.autoReconnect()
if (!this.isDisconnected()) {
this._channel.send({
id,
message: `${error}`,
param,
slotName,
stack: error.stack || '',
type: 'error'
})
}
})
}

/**
Expand Down
18 changes: 12 additions & 6 deletions test/TestChannel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,18 @@ export class TestChannel extends GenericChannel {

public autoReconnectSpy = jest.fn()

constructor() {
constructor(
options: { withAutoReconnect: boolean } = { withAutoReconnect: true }
) {
super()

if (options.withAutoReconnect) {
this.autoReconnect = () => {
this.callConnected()

this.autoReconnectSpy()
}
}
}

/**
Expand Down Expand Up @@ -39,11 +49,7 @@ export class TestChannel extends GenericChannel {
this._error(new Error('LOLOL'))
}

public autoReconnect() {
this.callConnected()

this.autoReconnectSpy()
}
public autoReconnect?: () => void | undefined

public send(message: TransportMessage) {
this.sendSpy(message)
Expand Down
81 changes: 80 additions & 1 deletion test/Transport.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ describe('Transport', () => {
expect(channel.sendSpy).not.toHaveBeenCalledWith({ type: 'handler_unregistered', slotName, param })
})


it('should call the appropriate handler when a request is received', async () => {

const slotName = 'buildCelery'
Expand Down Expand Up @@ -103,6 +102,86 @@ describe('Transport', () => {
})
})

describe('when the channel has autoReconnect capability', () => {
it('should call the handler when a request is received if the channel went disconnected', async () => {

const slotName = 'buildCelery'
const handler = slots[slotName][0]

// Register handler on slot
transport.registerHandler(slotName, param, handler)

const request: TransportMessage = {
type: 'request',
slotName,
id: '5',
param,
data: {
height: 5,
constitution: 'strong'
}
}

channel.callDisconnected()
channel.fakeReceive(request)

await flushPromises()
expect(handler).toHaveBeenCalledWith(request.data)
expect(channel.sendSpy).toHaveBeenCalledWith({
slotName,
type: 'response',
id: '5',
param,
data: {
color: 'blue'
}
})
})
})

describe('when the channel does not have autoReconnect capability', () => {
beforeEach(() => {
channel = new TestChannel({ withAutoReconnect: false })
transport = new Transport(channel)
channel.callConnected()
})

it('should not call the handler when a request is received if the channel went disconnected', async () => {

const slotName = 'buildCelery'
const handler = slots[slotName][0]

// Register handler on slot
transport.registerHandler(slotName, param, handler)

const request: TransportMessage = {
type: 'request',
slotName,
id: '5',
param,
data: {
height: 5,
constitution: 'strong'
}
}

channel.fakeReceive(request)
channel.callDisconnected()

await flushPromises()
expect(handler).toHaveBeenCalledWith(request.data)
expect(channel.sendSpy).not.toHaveBeenCalledWith({
slotName,
type: 'response',
id: '5',
param,
data: {
color: 'blue'
}
})
})
})

it('should send a handler_unregistered message when the last local handler is unregistered', () => {

const slotName = 'buildCelery'
Expand Down

0 comments on commit 956ab05

Please sign in to comment.