Skip to content

Conversation

kim-sung-jee
Copy link
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Currently, NestJS's WebSocket implementation provides a convenient way to handle Socket.IO acknowledgements by returning a value from a @SubscribeMessage() handler. This implicit ack handling is great for simple, synchronous responses.

However, there is no way for developers to get a direct reference to the ack callback function within the handler. This makes it very difficult or impossible to implement advanced use cases, such as:

  • Sending an acknowledgement after a complex asynchronous operation (e.g., a database call within a try...catch block).
  • Conditionally sending an acknowledgement based on business logic.
  • Having fine-grained control over the response payload for success and error cases.

This limitation is related to the issue described in #15286, where the ack callback is not correctly passed to the handler if declared as a parameter.

Issue Number: #15286

What is the new behavior?

This PR introduces a new @Ack() parameter decorator and enhances the underlying WebSocket infrastructure to allow for explicit, manual handling of acknowledgement callbacks, bringing it in line with the capabilities of socket.io.

  1. New @Ack() Decorator: Developers can now inject the ack callback function directly into their @SubscribeMessage() handlers, similar to how @MessageBody() or @ConnectedSocket() work.

    @SubscribeMessage('update-item')
    handleUpdate(
      @MessageBody() data: any,
      @Ack() ack: (response: any) => void,
    ) {
      // Developer now has full control over the ack callback
      ack({ status: 'ok' });
    }
  2. Automatic Ack Deactivation: When the @Ack() decorator is used in a handler, the framework's default behavior of automatically sending an ack based on the return value is disabled. This prevents accidental double-sends and provides clear, predictable behavior.

  3. Preserved Implicit Behavior: Handlers that do not use the @Ack() decorator will continue to function as before. Returning a value will still trigger an implicit acknowledgement, ensuring full backward compatibility.

To achieve this, the following changes were made:

  • A new WsParamtype.ACK was introduced.
  • GatewayMetadataExplorer now detects the usage of @Ack() and adds an isAckHandledManually flag to the handler's metadata.
  • WebSocketsController correctly propagates this flag to the platform adapter.
  • IoAdapter now consumes this flag to conditionally skip the automatic ack call.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@kim-sung-jee kim-sung-jee changed the title Feature/websockets manual ack feat(websockets): allow manual acknowledgement handling with @Ack() decorator Aug 18, 2025
@coveralls
Copy link

coveralls commented Aug 18, 2025

Pull Request Test Coverage Report for Build fa491690-4869-4361-8a59-e7d591cea9db

Details

  • 23 of 23 (100.0%) changed or added relevant lines in 7 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.03%) to 88.763%

Totals Coverage Status
Change from base Build 5fabdacf-4d8f-4ad7-8aa2-61d6c0524836: 0.03%
Covered Lines: 7291
Relevant Lines: 8214

💛 - Coveralls

@kim-sung-jee kim-sung-jee force-pushed the feature/websockets-manual-ack branch from c2534b8 to 0c7b94d Compare August 18, 2025 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants