Skip to content

Conversation

@CapoMK25
Copy link
Collaborator

Brief description

This PR implements MongoDB Transaction support for both the Global and Clan chat modules. The goal is to ensure all or nothing behavior, message persistence and any secondary operations (e.g., player stats updates or daily task progress), preventing "ghost" messages if a downstream operation fails.

Key changes

Commit 1: Updated the tests to handle the new transaction support instead of the other way around

Commit 2: Implemented the actual transaction support

Updated GlobalChatGateway and ClanChatGateway to initiate a ClientSession via @InjectConnection()

Modified handleNewGlobalMessage and handleNewClanMessage to accept and pass the session down to the service and repository layers.

Implemented try/catch/finally blocks to ensure abortTransaction() is called on failure and the session is always closed.

Verification results

Since standard MQTT testing is almost impossible in Postman, the following verification was performed:

  • Created a temporary endpoint to simulate a database crash immediately after a message save.
  • Verified via MongoDB Shell that the abortTransaction() successfully prevented the message from being committed to the altzone_dev database.
  • All 1153 existing unit and integration tests passed.

Change list

  • src/__tests__/chat/... Updated 4 test suites to support new method signatures and verify DB call counts.
  • src/chat/chat.gateway.ts Implemented transaction lifecycle (session management) for all chat-related WebSocket events.
  • src/chat/service/baseChat.service.ts Refactored base logic to propagate transaction options to the core ChatService.
  • src/chat/service/chat.service.ts Enabled createOne, readOneById, and updateOneById to utilize provided database sessions.
  • src/chat/service/clanChat.service.ts Updated Clan message/reaction handlers to support transactional all-or-nothing behavior.
  • src/chat/service/globalChat.service.ts Updated Global message/reaction handlers to support transactional all-or-nothing behavior.

Copy link
Member

@hoan301298 hoan301298 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just reviewed your PR quickly but unfortunately, I did not see you implement the transaction methods. Please use the transaction methods in Common/functions as we worked on it before.

@CapoMK25 CapoMK25 requested a review from hoan301298 January 29, 2026 18:50
Copy link
Member

@hoan301298 hoan301298 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since those changes still lacked of many requirements and need to be checked carefully with options type, documentation comments. Please check again every methods, workflow and documentation comments to match the requirements.

@WebSocketGateway(apiPort)
@UseFilters(GlobalWsExceptionFilter)
export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect {
private readonly logger = new Logger(ChatGateway.name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is your purpose to import Logger in here? The logger is declared but never in use.

}

@SubscribeMessage('clanMessage')
@WsLog()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please do not remove @WsLog() if you don't understand what is it used for. Also check for functions below.

@ConnectedSocket() client: WebSocketUser,
) {
await this.clanChatService.handleNewClanMessage(client, message);
async handleNewClanMessage(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name of this function is the same with clanChatService.handleNewClanMessage. Please be aware of changing those things.

const [session, sessionError] = await initializeSession(this.connection);
if (sessionError) return [null, sessionError];

try {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, remove the try-catch block that we handle to catch the errors manually!

@SubscribeMessage('clanMessageReaction')
@WsLog()
async handleClanMessageReaction(
async handleNewClanReaction(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

like above, please rename it as before

async handleNewGlobalReaction(
client: WebSocketUser,
reaction: AddReactionDto,
options?: any,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please follow the type of option by each service they are using, any is very bad option in here.

*/
async handleNewClanMessage(client: WebSocketUser, message: WsMessageBodyDto) {
const chatMessage = new CreateChatMessageDto({
async handleNewClanMessage(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add Documentation comments for options param

async handleNewClanReaction(
client: WebSocketUser,
reaction: AddReactionDto,
options?: TIServiceUpdateManyOptions,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

options: TIServiceUpdateByIdOptions following the ChatService.addReaction

* @param chatMessage - The DTO containing the new chat message data.
* @param client - The WebSocket user who sent the message.
* @param chatType - The type of chat (e.g., group, private).
* @param recipients - The set of WebSocket users to broadcast the message to.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add param for options

client: WebSocketUser,
reaction: AddReactionDto,
recipients: Set<WebSocketUser>,
options?: any,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add the correct type for options

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

3 participants