Skip to content

Commit

Permalink
expose deep heart beat callbacks to clients
Browse files Browse the repository at this point in the history
  • Loading branch information
mrajatttt committed Mar 6, 2024
1 parent 09218f7 commit b933125
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 10 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).


## [2.2.3]
### Fixed
- .onConnectionEstablished() is fired twice after invoking .connect(); closes #124
- enable message receipts by default; closes #132
- expose deep heartbeat success/failure callback to clients


## [2.2.2]
### Fixed
- reject send callbacks instead of returning null
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "amazon-connect-chatjs",
"version": "2.2.2",
"version": "2.2.3",
"main": "dist/amazon-connect-chat.js",
"types": "dist/index.d.ts",
"engines": {
Expand Down
10 changes: 7 additions & 3 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ export const WEBSOCKET_EVENTS = {
ConnectionGained: "WebsocketConnectionGained",
Ended: "WebsocketEnded",
IncomingMessage: "WebsocketIncomingMessage",
InitWebsocket: "InitWebsocket"
InitWebsocket: "InitWebsocket",
DeepHeartbeatSuccess: "WebsocketDeepHeartbeatSuccess",
DeepHeartbeatFailure: "WebsocketDeepHeartbeatFailure"
};

export const CHAT_EVENTS = {
Expand All @@ -64,7 +66,9 @@ export const CHAT_EVENTS = {
MESSAGE_METADATA: "MESSAGEMETADATA",
PARTICIPANT_IDLE: "PARTICIPANT_IDLE",
PARTICIPANT_RETURNED: "PARTICIPANT_RETURNED",
AUTODISCONNECTION: "AUTODISCONNECTION"
AUTODISCONNECTION: "AUTODISCONNECTION",
DEEP_HEARTBEAT_SUCCESS: "DEEP_HEARTBEAT_SUCCESS",
DEEP_HEARTBEAT_FAILURE: "DEEP_HEARTBEAT_FAILURE"
};

export const CONTENT_TYPE = {
Expand Down Expand Up @@ -161,4 +165,4 @@ export const CREATE_PARTICIPANT_CONACK_FAILURE = "CREATE_PARTICIPANT_CONACK_FAIL
export const SEND_EVENT_CONACK_FAILURE = "SEND_EVENT_CONACK_FAILURE";
export const CREATE_PARTICIPANT_CONACK_API_CALL_COUNT = "CREATE_PARTICIPANT_CONACK_CALL_COUNT";

export const TYPING_VALIDITY_TIME = 10000;
export const TYPING_VALIDITY_TIME = 10000;
20 changes: 20 additions & 0 deletions src/core/chatController.js
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,8 @@ class ChatController {
this.connectionHelper.onConnectionLost(this._handleLostConnection.bind(this));
this.connectionHelper.onConnectionGain(this._handleGainedConnection.bind(this));
this.connectionHelper.onMessage(this._handleIncomingMessage.bind(this));
this.connectionHelper.onDeepHeartbeatSuccess(this._handleDeepHeartbeatSuccess.bind(this));
this.connectionHelper.onDeepHeartbeatFailure(this._handleDeepHeartbeatFailure.bind(this));
return this.connectionHelper.start();
}

Expand Down Expand Up @@ -281,6 +283,20 @@ class ChatController {
});
}

_handleDeepHeartbeatSuccess(eventData) {
this._forwardChatEvent(CHAT_EVENTS.DEEP_HEARTBEAT_SUCCESS, {
data: eventData,
chatDetails: this.getChatDetails()
});
}

_handleDeepHeartbeatFailure(eventData) {
this._forwardChatEvent(CHAT_EVENTS.DEEP_HEARTBEAT_FAILURE, {
data: eventData,
chatDetails: this.getChatDetails()
});
}

_handleIncomingMessage(incomingData) {
try {
let eventType = getEventTypeFromContentType(incomingData?.ContentType);
Expand Down Expand Up @@ -437,6 +453,10 @@ class ChatController {
return NetworkLinkStatus.Broken;
case ConnectionHelperStatus.Connected:
return NetworkLinkStatus.Established;
case ConnectionHelperStatus.DeepHeartbeatSuccess:
return NetworkLinkStatus.Established;
case ConnectionHelperStatus.DeepHeartbeatFailure:
return NetworkLinkStatus.Broken;
}
this._sendInternalLogToServer(this.logger.error(
"Reached invalid state. Unknown connectionHelperStatus: ",
Expand Down
30 changes: 30 additions & 0 deletions src/core/chatController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ describe("ChatController", () => {
onMessage: (handler) => {
messageHandlers.push(handler);
},
onDeepHeartbeatSuccess: () => {},
onDeepHeartbeatFailure: () => {},
start: () => startResponse,
end: () => endResponse,
getStatus: () => ConnectionHelperStatus.Connected,
Expand Down Expand Up @@ -936,4 +938,32 @@ describe("ChatController", () => {
expect(console.error).toBeCalledWith('Cannot call disconnectParticipant when participant is disconnected');
}
});

test('_handleDeepHeartbeatSuccess is triggered correctly', () => {
const chatController = getChatController();
chatController._forwardChatEvent = jest.fn(); // Mock _forwardChatEvent to spy on it

// Directly invoke the method
chatController._handleDeepHeartbeatSuccess({ message: 'Heartbeat succeeded' });

// Check if _forwardChatEvent was called correctly
expect(chatController._forwardChatEvent).toHaveBeenCalledWith(
CHAT_EVENTS.DEEP_HEARTBEAT_SUCCESS,
{ data: { message: 'Heartbeat succeeded' }, chatDetails: expect.anything() }
);
});

test('_handleDeepHeartbeatFailure is triggered correctly', () => {
const chatController = getChatController();
chatController._forwardChatEvent = jest.fn(); // Mock _forwardChatEvent to spy on it

// Directly invoke the method
chatController._handleDeepHeartbeatFailure({ error: 'Heartbeat failed' });

// Check if _forwardChatEvent was called correctly
expect(chatController._forwardChatEvent).toHaveBeenCalledWith(
CHAT_EVENTS.DEEP_HEARTBEAT_FAILURE,
{ data: { error: 'Heartbeat failed' }, chatDetails: expect.anything() }
);
});
});
8 changes: 8 additions & 0 deletions src/core/chatSession.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ export class ChatSession {
this.controller.subscribe(CHAT_EVENTS.CONNECTION_LOST, callback);
}

onDeepHeartbeatSuccess(callback){
this.controller.subscribe(CHAT_EVENTS.DEEP_HEARTBEAT_SUCCESS, callback);
}

onDeepHeartbeatFailure(callback){
this.controller.subscribe(CHAT_EVENTS.DEEP_HEARTBEAT_FAILURE, callback);
}

sendMessage(args) {
return this.controller.sendMessage(args);
}
Expand Down
10 changes: 9 additions & 1 deletion src/core/chatSession.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ describe("chatSession", () => {
const cb9 = jest.fn();
const cb10 = jest.fn();
const cb11 = jest.fn();
const cb12 = jest.fn();
const cb13 = jest.fn();

session.onParticipantIdle(cb1);
session.onParticipantReturned(cb2);
Expand All @@ -92,6 +94,8 @@ describe("chatSession", () => {
session.onConnectionEstablished(cb9);
session.onEnded(cb10);
session.onConnectionLost(cb11);
session.onDeepHeartbeatSuccess(cb12);
session.onDeepHeartbeatFailure(cb13);

controller._forwardChatEvent(CHAT_EVENTS.PARTICIPANT_IDLE, eventData);
controller._forwardChatEvent(CHAT_EVENTS.PARTICIPANT_RETURNED, eventData);
Expand All @@ -104,6 +108,8 @@ describe("chatSession", () => {
controller._forwardChatEvent(CHAT_EVENTS.CONNECTION_ESTABLISHED, eventData);
controller._forwardChatEvent(CHAT_EVENTS.CHAT_ENDED, eventData);
controller._forwardChatEvent(CHAT_EVENTS.CONNECTION_LOST, eventData);
controller._forwardChatEvent(CHAT_EVENTS.DEEP_HEARTBEAT_SUCCESS, eventData);
controller._forwardChatEvent(CHAT_EVENTS.DEEP_HEARTBEAT_FAILURE, eventData);

await new Promise((r) => setTimeout(r, 0));

Expand All @@ -118,6 +124,8 @@ describe("chatSession", () => {
expect(cb9).toHaveBeenCalled();
expect(cb10).toHaveBeenCalled();
expect(cb11).toHaveBeenCalled();
expect(cb12).toHaveBeenCalled();
expect(cb13).toHaveBeenCalled();
});

test('events', () => {
Expand Down Expand Up @@ -145,4 +153,4 @@ describe("chatSession", () => {
session.getChatDetails(args);
expect(controller.getChatDetails).toHaveBeenCalled();
});
});
});
46 changes: 44 additions & 2 deletions src/core/connectionHelpers/LpcConnectionHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ class LpcConnectionHelper extends BaseConnectionHelper {
this.baseInstance.onEnded(this.handleEnded.bind(this)),
this.baseInstance.onConnectionGain(this.handleConnectionGain.bind(this)),
this.baseInstance.onConnectionLost(this.handleConnectionLost.bind(this)),
this.baseInstance.onMessage(this.handleMessage.bind(this))
this.baseInstance.onMessage(this.handleMessage.bind(this)),
this.baseInstance.onDeepHeartbeatSuccess(this.handleDeepHeartbeatSuccess.bind(this)),
this.baseInstance.onDeepHeartbeatFailure(this.handleDeepHeartbeatFailure.bind(this))
];
}

Expand Down Expand Up @@ -100,6 +102,22 @@ class LpcConnectionHelper extends BaseConnectionHelper {
this.eventBus.trigger(ConnectionHelperEvents.ConnectionLost, {});
}

onDeepHeartbeatSuccess(handler) {
return this.eventBus.subscribe(ConnectionHelperEvents.DeepHeartbeatSuccess, handler);
}

handleDeepHeartbeatSuccess() {
this.eventBus.trigger(ConnectionHelperEvents.DeepHeartbeatSuccess, {});
}

onDeepHeartbeatFailure(handler) {
return this.eventBus.subscribe(ConnectionHelperEvents.DeepHeartbeatFailure, handler);
}

handleDeepHeartbeatFailure() {
this.eventBus.trigger(ConnectionHelperEvents.DeepHeartbeatFailure, {});
}

onMessage(handler) {
return this.eventBus.subscribe(ConnectionHelperEvents.IncomingMessage, handler);
}
Expand Down Expand Up @@ -133,7 +151,9 @@ class LpcConnectionHelperBase {
this.websocketManager.onMessage("aws/chat", this.handleMessage.bind(this)),
this.websocketManager.onConnectionGain(this.handleConnectionGain.bind(this)),
this.websocketManager.onConnectionLost(this.handleConnectionLost.bind(this)),
this.websocketManager.onInitFailure(this.handleEnded.bind(this))
this.websocketManager.onInitFailure(this.handleEnded.bind(this)),
this.websocketManager.onDeepHeartbeatSuccess(this.handleDeepHeartbeatSuccess.bind(this)),
this.websocketManager.onDeepHeartbeatFailure(this.handleDeepHeartbeatFailure.bind(this))
];
this.logger.info("Initializing websocket manager.");
if (!websocketManager) {
Expand Down Expand Up @@ -271,6 +291,28 @@ class LpcConnectionHelperBase {

return logEntry;
}

onDeepHeartbeatSuccess(handler) {
return this.eventBus.subscribe(ConnectionHelperEvents.DeepHeartbeatSuccess, handler);
}

handleDeepHeartbeatSuccess() {
this.status = ConnectionHelperStatus.DeepHeartbeatSuccess;
this.eventBus.trigger(ConnectionHelperEvents.DeepHeartbeatSuccess, {});
csmService.addCountMetric(WEBSOCKET_EVENTS.DeepHeartbeatSuccess, CSM_CATEGORY.API);
this.logger.info("Websocket deep heartbeat success.");
}

onDeepHeartbeatFailure(handler) {
return this.eventBus.subscribe(ConnectionHelperEvents.DeepHeartbeatFailure, handler);
}

handleDeepHeartbeatFailure() {
this.status = ConnectionHelperStatus.DeepHeartbeatFailure;
this.eventBus.trigger(ConnectionHelperEvents.DeepHeartbeatFailure, {});
csmService.addCountMetric(WEBSOCKET_EVENTS.DeepHeartbeatFailure, CSM_CATEGORY.API);
this.logger.info("Websocket deep heartbeat failure.");
}
}

export default LpcConnectionHelper;
Loading

0 comments on commit b933125

Please sign in to comment.