Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question service #28

Merged
merged 11 commits into from
Sep 17, 2024
Merged

Question service #28

merged 11 commits into from
Sep 17, 2024

Conversation

cyri113
Copy link
Contributor

@cyri113 cyri113 commented Sep 17, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced QuestionService for handling Telegram bot interactions.
    • Added BotController to manage messaging events.
    • New classes for handling question results and text.
    • Enhanced bot functionality to process user messages and integrate with a question service.
    • Added telegram-question service for improved bot capabilities.
    • New configuration for question service URI to enhance flexibility.
    • Added TGQuestionService for dedicated handling of TG questions.
  • Bug Fixes

    • Updated interceptor strategies for message handling across various controllers.
  • Chores

    • Updated Docker and configuration files for improved development setup.
    • Added Jest configuration for end-to-end testing.
  • Documentation

    • Improved module and service organization for better clarity and maintainability.

Copy link

coderabbitai bot commented Sep 17, 2024

Warning

Rate limit exceeded

@cyri113 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 17 minutes and 6 seconds before requesting another review.

How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Commits

Files that changed from the base of the PR and between 9b00549 and 7f168d0.

Walkthrough

The pull request introduces substantial updates across various services in a NestJS application. Key modifications include the addition of a question-service for processing messages from a Telegram bot, enhancements to the bot service for improved message handling, and updates to controllers and services to integrate new functionalities. The Docker configuration has been adjusted for development environments, and new dependencies have been added to facilitate HTTP requests and service interactions.

Changes

File Path Change Summary
Dockerfile Added RUN npm run build question-service to include the question-service in the Docker build process.
apps/bot/src/bot.controller.ts Introduced BotController class with a sendMessage method to handle Telegram message events.
apps/bot/src/bot.module.ts Added BotController and registered Services.TGQuestionService in the module.
apps/bot/src/bot.service.ts Updated BotService to inject tgQuestionClient and added a new sendMessage method for sending messages.
apps/event-store/src/event-store.controller.ts Modified import path for EventsInterceptor.
apps/graph-store/src/chat_member/chat_member.controller.ts Replaced RmqInterceptor with EventsInterceptor.
apps/graph-store/src/edited_message/edited_message.controller.ts Replaced RmqInterceptor with EventsInterceptor.
apps/graph-store/src/message/message.controller.ts Replaced RmqInterceptor with EventsInterceptor.
apps/graph-store/src/message_reaction/message_reaction.controller.ts Replaced RmqInterceptor with EventsInterceptor.
apps/question-service/src/dto/QuestionResult.ts Added QuestionResult class for representing question results.
apps/question-service/src/dto/QuestionText.ts Added QuestionText class for encapsulating question text.
apps/question-service/src/main.ts Established the entry point for the QuestionService application with microservice setup.
apps/question-service/src/question-service.controller.ts Introduced QuestionServiceController to handle messages from Telegram and respond with processed data.
apps/question-service/src/question-service.module.ts Created QuestionServiceModule to encapsulate the question service functionality.
apps/question-service/src/question-service.service.ts Added QuestionServiceService for handling HTTP interactions with a remote service.
docker-compose.yml Updated service configurations for development, added telegram-question and question-service-ext services.
libs/common/src/config/index.ts Added export for question.config.
libs/common/src/config/question.config.ts Introduced questionConfig function for dynamic service URI configuration.
libs/common/src/constants/events.ts Added TelegramAction constant for handling Telegram actions.
libs/common/src/constants/services.ts Added TGQuestionService configuration for message handling.
nest-cli.json Added configuration for question-service.
apps/question-service/test/app.e2e-spec.ts Introduced end-to-end test for the QuestionServiceController.
apps/question-service/test/jest-e2e.json Added Jest configuration for end-to-end testing.
apps/question-service/tsconfig.app.json Created TypeScript configuration for the question-service.
apps/graph-store/src/graph-store.module.ts Minor formatting change in class declaration.
apps/graph-store/src/interceptors/rmq.interceptor.spec.ts Removed unit tests for RmqInterceptor.
apps/graph-store/src/interceptors/rmq.interceptor.ts Removed implementation of RmqInterceptor.

Possibly related PRs

  • changed EDITED edge #27: The changes in the message.service.ts file involve modifications to message handling logic, which may relate to the overall messaging functionality being enhanced in the main PR, particularly in the context of how messages are processed and updated within the application.

Poem

In the garden where code does bloom,
A question service finds its room.
With bots that send and messages clear,
Our updates bring us all good cheer.
So hop along, let’s code and play,
For every change, a brighter day! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    -- I pushed a fix in commit <commit_id>, please review it.
    -- Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    -- @coderabbitai generate unit testing code for this file.
    -- @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    -- @coderabbitai generate interesting stats about this repository and render them as a table.
    -- @coderabbitai read src/utils.ts and generate unit testing code.
    -- @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    -- @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Outside diff range and nitpick comments (3)
apps/question-service/src/dto/QuestionText.ts (1)

1-3: LGTM!

The QuestionText class is a simple and clear DTO for encapsulating question text data. The class name and property name are descriptive, and the class is exported appropriately.

Consider explicitly marking the text property as public for clarity and consistency with TypeScript best practices:

export class QuestionText {
-  text: string;
+  public text: string;
}
apps/question-service/test/app.e2e-spec.ts (1)

18-23: Update the expected response message to match the actual functionality.

The test case is structured correctly and ensures that the root endpoint is accessible and responds with a 200 status code. However, the asserted response message "Hello World!" seems to be a placeholder.

Please update the expected response message to align with the actual functionality of the endpoint. This will provide more meaningful validation of the endpoint's behavior.

apps/question-service/src/question-service.controller.spec.ts (1)

5-24: LGTM! Consider enabling the commented-out test case.

The testing module setup for the QuestionServiceController looks good and follows NestJS best practices.

However, there is a commented-out test case for the getHello method. Consider enabling this test case to ensure the method is properly tested and to prevent potential bugs or regressions.

Tools
GitHub Check: lint

[failure] 6-6:
'questionServiceController' is assigned a value but never used

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 6da2cfa and 6b15911.

Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
Files selected for processing (29)
  • Dockerfile (1 hunks)
  • apps/bot/src/bot.controller.ts (1 hunks)
  • apps/bot/src/bot.module.ts (2 hunks)
  • apps/bot/src/bot.service.ts (4 hunks)
  • apps/event-store/src/event-store.controller.ts (1 hunks)
  • apps/graph-store/src/chat_member/chat_member.controller.ts (2 hunks)
  • apps/graph-store/src/edited_message/edited_message.controller.ts (2 hunks)
  • apps/graph-store/src/graph-store.module.ts (1 hunks)
  • apps/graph-store/src/interceptors/rmq.interceptor.spec.ts (0 hunks)
  • apps/graph-store/src/interceptors/rmq.interceptor.ts (0 hunks)
  • apps/graph-store/src/message/message.controller.ts (2 hunks)
  • apps/graph-store/src/message_reaction/message_reaction.controller.ts (2 hunks)
  • apps/question-service/src/dto/QuestionResult.ts (1 hunks)
  • apps/question-service/src/dto/QuestionText.ts (1 hunks)
  • apps/question-service/src/main.ts (1 hunks)
  • apps/question-service/src/question-service.controller.spec.ts (1 hunks)
  • apps/question-service/src/question-service.controller.ts (1 hunks)
  • apps/question-service/src/question-service.module.ts (1 hunks)
  • apps/question-service/src/question-service.service.ts (1 hunks)
  • apps/question-service/test/app.e2e-spec.ts (1 hunks)
  • apps/question-service/test/jest-e2e.json (1 hunks)
  • apps/question-service/tsconfig.app.json (1 hunks)
  • docker-compose.yml (3 hunks)
  • libs/common/src/config/index.ts (1 hunks)
  • libs/common/src/config/question.config.ts (1 hunks)
  • libs/common/src/constants/events.ts (1 hunks)
  • libs/common/src/constants/services.ts (1 hunks)
  • nest-cli.json (1 hunks)
  • package.json (3 hunks)
Files not reviewed due to no reviewable changes (2)
  • apps/graph-store/src/interceptors/rmq.interceptor.spec.ts
  • apps/graph-store/src/interceptors/rmq.interceptor.ts
Files skipped from review due to trivial changes (4)
  • apps/event-store/src/event-store.controller.ts
  • apps/graph-store/src/graph-store.module.ts
  • apps/question-service/test/jest-e2e.json
  • apps/question-service/tsconfig.app.json
Additional context used
GitHub Check: lint
apps/question-service/src/question-service.controller.spec.ts

[failure] 6-6:
'questionServiceController' is assigned a value but never used

Biome
apps/question-service/src/question-service.controller.ts

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Additional comments not posted (46)
apps/question-service/src/dto/QuestionResult.ts (1)

1-4: LGTM!

The QuestionResult class is well-structured and follows TypeScript best practices:

  • The class properties are appropriately typed using string literal types and number types.
  • The use of string literal types for the label property ensures type safety and reduces the chances of runtime errors.
  • The class is exported, allowing it to be imported and used in other parts of the codebase.

Overall, the class provides a clear and structured way to represent the outcome of a question evaluation, facilitating better data handling and type safety within the application.

libs/common/src/config/question.config.ts (1)

1-5: LGTM!

The questionConfig function provides a clean and flexible way to configure the question service URI. Using environment variables for configuration is a good practice as it allows for flexibility and security. The function signature uses Record<string, unknown> as the return type, which is a good way to represent a generic object type.

The code changes look good to me.

libs/common/src/config/index.ts (1)

6-6: LGTM! Verify the question.config module.

The new export statement looks good and enhances the module's functionality by integrating the configurations from question.config.

Please ensure that:

  1. The question.config module exists at the correct path.
  2. It exports the expected configurations without any issues.

You can use the following script to verify:

Verification successful

Verification successful: question.config.ts exists and exports the expected configuration.

The libs/common/src/config/question.config.ts file has been verified:

  1. The file exists in the correct location.
  2. It contains one export statement as expected.
  3. The exported questionConfig function returns an object with the question.uri configuration, which uses an environment variable for flexibility.

These changes enhance the module's functionality by integrating the question configuration, allowing for dynamic configuration of the question service URI.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and correctness of the `question.config` module.

# Test 1: Check if the `question.config` file exists. Expect: File found.
if [ -f "libs/common/src/config/question.config.ts" ] || [ -f "libs/common/src/config/question.config.js" ]; then
    echo "File libs/common/src/config/question.config exists."
else 
    echo "File libs/common/src/config/question.config does not exist."
fi

# Test 2: Check if the `question.config` module has any export statements. Expect: At least one export statement.
exports_count=$(rg --type typescript --type javascript -c $'export' libs/common/src/config/question.config)
if [ "$exports_count" -gt 0 ]; then
    echo "File libs/common/src/config/question.config contains $exports_count export statements."
else
    echo "File libs/common/src/config/question.config does not contain any export statements."
fi

Length of output: 588


Script:

#!/bin/bash
# Description: Verify the existence and correctness of the `question.config` module using alternative methods.

# Test 1: Confirm the existence of the question.config.ts file
echo "Test 1: Checking file existence"
if [ -f "libs/common/src/config/question.config.ts" ]; then
    echo "File libs/common/src/config/question.config.ts exists."
else 
    echo "File libs/common/src/config/question.config.ts does not exist."
fi

# Test 2: Check for export statements using grep instead of rg
echo "Test 2: Checking for export statements"
export_count=$(grep -c "export" libs/common/src/config/question.config.ts)
if [ "$export_count" -gt 0 ]; then
    echo "File libs/common/src/config/question.config.ts contains $export_count export statement(s)."
else
    echo "File libs/common/src/config/question.config.ts does not contain any export statements."
fi

# Test 3: Display the content of the file for manual verification
echo "Test 3: Displaying file content for manual verification"
echo "Content of libs/common/src/config/question.config.ts:"
cat libs/common/src/config/question.config.ts

Length of output: 1011

libs/common/src/constants/services.ts (1)

14-17: LGTM!

The addition of the TGQuestionService configuration to the Services constant is consistent with the existing service definitions and follows the established naming convention.

This change sets the stage for integrating the TGQuestionService into the application. The actual implementation and usage of the service should be reviewed separately to ensure it aligns with the application architecture and requirements.

apps/question-service/src/main.ts (1)

5-12: LGTM!

The bootstrap function correctly sets up a NestJS microservice for the Question Service. It follows the standard pattern, uses the RmqService to connect to RabbitMQ, targets the correct queue, and starts all microservices. This setup is crucial for the functionality of the Question Service within the broader system architecture.

Dockerfile (1)

17-17: LGTM!

The addition of the build command for the question-service is consistent with the existing build commands and follows the same pattern. This change ensures that the question-service is built and included in the production image, which is necessary for the application to function correctly in its deployed environment.

libs/common/src/constants/events.ts (1)

19-21: LGTM!

The new constant TelegramAction with the property SEND_MESSAGE is a good addition. It provides a clear and centralized way to reference the action of sending messages, which can improve code readability and maintainability.

Exporting the constant is also a good practice for reusability.

apps/question-service/src/question-service.service.ts (3)

1-5: LGTM!

The imports are correctly used to bring in the required dependencies.


7-8: LGTM!

The class declaration and the @Injectable() decorator are correctly used to define a service that can be managed by the NestJS dependency injection system.


9-16: LGTM!

The constructor correctly uses dependency injection to get instances of HttpService and ConfigService, and sets the uri property using the question.uri configuration value.

apps/question-service/test/app.e2e-spec.ts (2)

1-4: LGTM!

The imports are correct and necessary for setting up the testing module using NestJS and Supertest.


6-16: LGTM!

The testing module is set up correctly by importing the QuestionServiceModule, and the Nest application instance is created and initialized properly for testing purposes.

apps/bot/src/bot.module.ts (4)

12-12: LGTM!

The import statement for BotController is correctly written and follows the naming convention.


23-23: Registering the question service aligns with the PR objective.

The registration of TGQuestionService with the RmqModule aligns with the PR objective of adding a question service. This will make the service available for injection in the controllers and providers of this module.


25-25: Adding the controller to the module is correct.

Including BotController in the controllers array of the @Module decorator is the correct way to make the controller part of the module. This allows the controller to handle incoming requests related to the bot functionality.


28-28: Adding an empty line after the class definition is a good practice.

Although not functionally necessary, adding an empty line after the class definition of BotModule improves the readability of the code and aligns with many style guide recommendations.

apps/question-service/src/question-service.module.ts (4)

1-12: LGTM!

The module imports are well-organized and provide the necessary functionality for the QuestionServiceModule. The use of a shared library @app/common for custom modules and configurations promotes code reuse and maintainability.


16-20: LGTM!

The ConfigModule is correctly configured to load and validate the necessary configurations. Setting the configurations as global ensures they are accessible throughout the application. The use of schemaConfig for validation and loading rmqConfig and questionConfig separately allows for a modular and maintainable configuration setup.


23-23: LGTM!

Registering RmqModule with Services.TelegramBot service enables the QuestionServiceModule to communicate with the Telegram bot service using RabbitMQ. This setup allows for loose coupling between services and enables asynchronous communication, which is a good architectural practice.


14-28: LGTM!

The QuestionServiceModule is declared correctly as a NestJS module. It imports the necessary modules and declares the related controller and service, encapsulating the question service functionality within a logical boundary. The module structure follows the NestJS best practices and promotes a modular and maintainable architecture.

apps/bot/src/bot.controller.ts (2)

7-11: LGTM!

The MessagePayload interface accurately represents the structure of the payload for the sendMessage method. The property types are appropriate for their intended use.


13-25: LGTM!

The BotController class is well-structured and follows best practices for a NestJS controller. It correctly uses decorators, dependency injection, and message patterns to handle incoming messages and delegate the sending logic to the service layer. The sendMessage method is implemented correctly, accepting a payload of type MessagePayload and destructuring it to extract the required properties before calling the sendMessage method of the BotService.

nest-cli.json (1)

49-56: LGTM!

The addition of the "question-service" configuration follows the established conventions and mirrors the structure of existing service configurations. This change enables the proper integration of the "question-service" into the application architecture, facilitating its development and deployment within the NestJS framework.

apps/question-service/src/question-service.controller.ts (1)

12-47: LGTM! The class is well-structured and follows the NestJS controller pattern.

The QuestionServiceController class is designed to handle incoming messages from a Telegram bot using the @MessagePattern decorator. It processes the message text using the QuestionServiceService and sends a formatted response back to the Telegram chat. The use of decorators and the overall structure of the class adhere to the NestJS best practices for building microservices.

Tools
Biome

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

apps/bot/src/bot.service.ts (4)

5-7: LGTM!

The new imports from the grammy library are correctly specified and follow the proper syntax. The imported entities are used in the code changes below.


17-18: LGTM!

The new dependency tgQuestionClient is correctly injected into the BotService constructor using the @Inject decorator and the Services.TGQuestionService.name token. The dependency is declared as a private readonly property of type ClientProxy and is used in the code changes below to emit events to the TGQuestionService.


34-37: LGTM!

The new condition correctly checks if the message sender is not a bot using the is_bot property of the from object. The tgQuestionClient is used to emit the event to the TGQuestionService only if the condition is true. The return statement is added to exit the event handler after emitting the event.


47-56: LGTM!

The new method sendMessage is correctly defined with the appropriate parameters and return type. The method uses the bot.api.sendMessage method to send the message, which is the correct way to send messages using the grammy library. The method logs the sent message details using the logger.log method, which is a good practice for tracking and debugging purposes.

apps/graph-store/src/message_reaction/message_reaction.controller.ts (2)

13-13: LGTM!

The import statement for EventsInterceptor is syntactically correct and aligns with the change in interception strategy mentioned in the summary.


16-16: LGTM!

The @UseInterceptors(EventsInterceptor) decorator is correctly applied to the MessageReactionController class, reflecting the change in interception strategy mentioned in the summary.

apps/graph-store/src/edited_message/edited_message.controller.ts (3)

16-16: LGTM!

The import statement for EventsInterceptor is syntactically correct and the import path is valid.


31-31: LGTM!

The formatting change in the constructor improves the readability of the code and does not impact the functionality.


19-19: Verify the behavior of the new interceptor.

The change from RmqInterceptor to EventsInterceptor is significant and may impact how events are processed or logged within the application.

Please ensure that the new interceptor handles the events as expected and doesn't introduce any bugs or performance issues. Consider running the following verification steps:

  1. Review the implementation of EventsInterceptor to understand how it differs from RmqInterceptor.
  2. Test the edited message functionality thoroughly to ensure that the events are intercepted and handled correctly.
  3. Monitor the application logs to verify that the events are being logged as expected.
  4. Perform load testing to ensure that the new interceptor doesn't introduce any performance issues.
Verification successful

Verified: EventsInterceptor is correctly implemented and used.

The change from RmqInterceptor to EventsInterceptor is consistent with the codebase. The EventsInterceptor is properly implemented in libs/common/src/rmq/interceptors/events.interceptor.ts and is used consistently across multiple controllers in different services. It utilizes the RmqService for message acknowledgment, which is the expected behavior for RabbitMQ message processing.

Key observations:

  • The interceptor is located in the common module, making it reusable across the application.
  • It's applied to various controllers, including EditedMessageController, ensuring consistent message handling.
  • The implementation uses RmqService for acknowledging messages, maintaining the required RabbitMQ functionality.

This change appears to be a refactoring or renaming that maintains the same functionality as the previous RmqInterceptor. The extensive use of RabbitMQ configurations and services throughout the codebase further supports this conclusion.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation and usage of EventsInterceptor.

# Test 1: Search for the EventsInterceptor class definition.
# Expect: The class should be defined in the @app/common module.
fd EventsInterceptor.ts @app/common --exec cat | less

# Test 2: Search for the usage of EventsInterceptor in the codebase.
# Expect: The interceptor should be used consistently across the application.
rg --type typescript -C 5 $'@UseInterceptors\(EventsInterceptor\)'

# Test 3: Search for the RMQ_EVENTS constant in the codebase.
# Expect: The constant should be used in the EventsInterceptor class.
rg --type typescript -C 5 RMQ_EVENTS

Length of output: 331


Script:

#!/bin/bash
# Description: Verify the implementation and usage of EventsInterceptor and RMQ_EVENTS

# Search for the EventsInterceptor file
echo "Searching for EventsInterceptor file:"
fd EventsInterceptor.ts

# Display the content of the EventsInterceptor file
echo -e "\nContent of EventsInterceptor file:"
fd EventsInterceptor.ts -x cat {}

# Search for usage of EventsInterceptor in the codebase
echo -e "\nUsage of EventsInterceptor:"
rg -C 3 "@UseInterceptors\(EventsInterceptor\)"

# Search for RMQ_EVENTS constant in the codebase
echo -e "\nUsage of RMQ_EVENTS constant:"
rg -C 3 "RMQ_EVENTS"

Length of output: 4737


Script:

#!/bin/bash
# Description: Further investigate EventsInterceptor and RabbitMQ configurations

# Search for the events.interceptor.ts file
echo "Searching for events.interceptor.ts file:"
fd events.interceptor.ts

# Display the content of the events.interceptor.ts file
echo -e "\nContent of events.interceptor.ts file:"
fd events.interceptor.ts -x cat {}

# Search for RabbitMQ-related constants and configurations
echo -e "\nRabbitMQ-related constants and configurations:"
rg -C 3 -e "RabbitMQ" -e "RABBITMQ" -e "rmq" -e "amqp"

# Search for any Interceptor-related imports in the common module
echo -e "\nInterceptor-related imports in common module:"
rg -C 3 "import.*Interceptor" apps/common

Length of output: 25579

package.json (3)

23-23: LGTM!

The addition of @nestjs/axios dependency is a good choice for enhancing the HTTP request handling capabilities within the NestJS framework. The version ^3.0.3 is a stable release and should not cause any compatibility issues.


32-32: LGTM!

The addition of axios dependency is a good choice for making HTTP requests outside of the NestJS context. This change provides flexibility to make HTTP requests independently of the NestJS framework. The version ^1.7.7 is a stable release and should not cause any compatibility issues.


33-33: LGTM!

The update of grammy dependency from version ^1.22.4 to ^1.30.0 is a good choice for potentially improving functionality and performance of the Telegram bot framework. This change reflects an enhancement in the application's dependency management. The version ^1.30.0 is a stable release and should not cause any compatibility issues.

docker-compose.yml (5)

Line range hint 1-17: LGTM!

The changes to the telegram-common service configuration, including the build target update and volume addition, align with the PR objective of transitioning to a more development-focused setup. These modifications will facilitate easier access to local files during development.


71-71: Improved healthcheck for the neo4j service.

The updated healthcheck test command using wget to check the availability of the Neo4j web interface is a more reliable method compared to the previous command. This change enhances the robustness of the healthcheck mechanism for the neo4j service.


78-92: Updated command format and added new service.

The changes to the command format for the telegram-bot, telegram-events, and telegram-graph services, along with the introduction of the new telegram-question service using the development command format, align with the PR objectives of transitioning to a more development-focused setup and enhancing functionality.


104-104: Added volume for Neo4j plugins.

The addition of the neo4j_plugins volume provides a dedicated storage space for Neo4j plugins, aligning with the Neo4j service configuration that specifies the use of "apoc" and "graph-data-science" plugins. This change promotes modularity and easier management of Neo4j extensions.


94-98: Verify the integration and security of the external question service.

The addition of the question-service-ext service, which uses an image from a GitHub container registry and exposes port 80, suggests an integration of an external question service into the existing architecture.

Please ensure that:

  1. The integration of this external service aligns with the overall system design and requirements.
  2. The image sourced from the GitHub container registry is trusted and secure.
  3. Proper security measures are in place to protect the exposed endpoint of this service.

Run the following script to verify the integration and security aspects:

apps/graph-store/src/message/message.controller.ts (3)

16-16: LGTM!

The import statement for EventsInterceptor is syntactically correct and follows the project's conventions.


31-31: LGTM!

The reformatting of the constructor improves readability without impacting functionality.


19-19: Verify the impact of the interceptor change.

The usage of the @UseInterceptors(EventsInterceptor) decorator is syntactically correct and follows the NestJS framework conventions.

However, please ensure that the switch from RmqInterceptor to EventsInterceptor does not introduce any unintended side effects or break existing functionality related to message handling.

Consider running the following script to analyze the usage of the EventsInterceptor across the codebase:

Verification successful

Interceptor change verified and consistently implemented

The switch from RmqInterceptor to EventsInterceptor has been successfully verified across the codebase. Key findings:

  • EventsInterceptor is consistently used in multiple services (bot, event-store, graph-store, question-service) with the @UseInterceptors decorator on controller classes.
  • Message handling logic using @MessagePattern(UpdateEvent.MESSAGE) remains intact in relevant services.
  • No traces of RmqInterceptor were found, confirming its complete replacement.

This change appears to be an intentional, system-wide update to the event handling mechanism. The consistent implementation across different services suggests that the impact has been carefully considered and applied uniformly.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage and impact of the EventsInterceptor.

# Test 1: Search for the EventsInterceptor usage. 
# Expect: Usage in relevant message handling contexts.
rg --type typescript -A 5 $'EventsInterceptor'

# Test 2: Search for message handling logic. 
# Expect: No breaking changes or unintended side effects.
rg --type typescript -A 10 $'@MessagePattern\(UpdateEvent\.MESSAGE\)'

Length of output: 186


Script:

#!/bin/bash
# Description: Verify the usage and impact of the EventsInterceptor using grep.

# Test 1: Search for the EventsInterceptor usage.
# Expect: Usage in relevant message handling contexts.
grep -r -n -A 5 "EventsInterceptor" .

# Test 2: Search for message handling logic.
# Expect: No breaking changes or unintended side effects.
grep -r -n -A 10 "@MessagePattern(UpdateEvent.MESSAGE)" .

# Test 3: Search for RmqInterceptor usage to compare with EventsInterceptor.
# Expect: Possible remnants of previous implementation or complete replacement.
grep -r -n -A 5 "RmqInterceptor" .

Length of output: 12662

apps/graph-store/src/chat_member/chat_member.controller.ts (2)

28-28: LGTM!

The decorator change aligns with the import change. As mentioned in the previous comment, ensure that the replacement of RmqInterceptor with EventsInterceptor does not introduce any unintended side effects or break existing functionality.


5-5: Verify the impact of replacing RmqInterceptor with EventsInterceptor.

The import statement is correct. However, ensure that the replacement of RmqInterceptor with EventsInterceptor does not introduce any unintended side effects or break existing functionality.

Run the following script to verify the usage of RmqInterceptor and EventsInterceptor:

Verification successful

Verified: EventsInterceptor replacement is correct and consistent

The replacement of RmqInterceptor with EventsInterceptor in the ChatMemberController is verified to be correct and consistent with the rest of the codebase. Key findings:

  • RmqInterceptor is no longer used anywhere in the codebase.
  • EventsInterceptor is widely used across multiple controllers in different services.
  • The import statement and usage in chat_member.controller.ts match other controllers' implementations.

This change aligns with the overall architecture and doesn't introduce any inconsistencies or unintended side effects.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of `RmqInterceptor` and `EventsInterceptor`.

# Test 1: Search for the usage of `RmqInterceptor`. Expect: No occurrences.
rg --type typescript -A 5 $'RmqInterceptor'

# Test 2: Search for the usage of `EventsInterceptor`. Expect: Only occurrences in the `ChatMemberController` class.
rg --type typescript -A 5 $'EventsInterceptor'

Length of output: 158


Script:

#!/bin/bash
# Description: Verify the usage and definitions of `RmqInterceptor` and `EventsInterceptor`.

# Test 1: Search for the usage of `RmqInterceptor`.
echo "Searching for RmqInterceptor usage:"
rg --glob '*.ts' -A 5 'RmqInterceptor'

# Test 2: Search for the definition of `RmqInterceptor`.
echo "Searching for RmqInterceptor definition:"
rg --glob '*.ts' -A 5 'class RmqInterceptor'

# Test 3: Search for the usage of `EventsInterceptor`.
echo "Searching for EventsInterceptor usage:"
rg --glob '*.ts' -A 5 'EventsInterceptor'

# Test 4: Search for the definition of `EventsInterceptor`.
echo "Searching for EventsInterceptor definition:"
rg --glob '*.ts' -A 5 'class EventsInterceptor'

# Test 5: Search for the import of `EventsInterceptor` in chat_member.controller.ts
echo "Searching for EventsInterceptor import in chat_member.controller.ts:"
rg --glob 'chat_member.controller.ts' 'import.*EventsInterceptor'

Length of output: 10755

Comment on lines 18 to 22
test(text: string): Promise<AxiosResponse<QuestionResult>> {
return this.httpService.axiosRef.post(this.uri, {
text,
});
}
Copy link

Choose a reason for hiding this comment

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

Add error handling and logging.

The test method correctly sends a POST request to the uri with the text parameter in the request body, and returns a promise that resolves to an AxiosResponse containing a QuestionResult.

However, consider adding error handling and logging to improve the robustness and observability of the service.

Here's an example of how you can add error handling and logging:

import { Logger } from '@nestjs/common';

// ...

@Injectable()
export class QuestionServiceService {
  private readonly logger = new Logger(QuestionServiceService.name);

  // ...

  async test(text: string): Promise<AxiosResponse<QuestionResult>> {
    try {
      const response = await this.httpService.axiosRef.post(this.uri, {
        text,
      });
      this.logger.log(`Received response from ${this.uri}: ${JSON.stringify(response.data)}`);
      return response;
    } catch (error) {
      this.logger.error(`Error sending request to ${this.uri}: ${error.message}`, error.stack);
      throw error;
    }
  }
}

import { QuestionServiceService } from './question-service.service';

describe('QuestionServiceController', () => {
let questionServiceController: QuestionServiceController;
Copy link

Choose a reason for hiding this comment

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

Address the unused variable.

The questionServiceController variable is assigned a value but never used, as indicated by the static analysis hint. This is likely due to the commented-out test case.

Consider one of the following solutions:

  1. Enable the commented-out test case to utilize the questionServiceController variable.
  2. If the test case is not needed, remove the variable declaration to keep the code clean.
-let questionServiceController: QuestionServiceController;
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let questionServiceController: QuestionServiceController;
Tools
GitHub Check: lint

[failure] 6-6:
'questionServiceController' is assigned a value but never used

message_id,
text: msg,
chat: { id: chat_id },
} = ctx.update?.message;
Copy link

Choose a reason for hiding this comment

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

Fix the unsafe usage of optional chaining.

The static analysis tool has correctly identified an unsafe usage of optional chaining on line 26. If ctx.update or ctx.update.message is undefined, accessing properties on it will throw a TypeError.

To fix this, you can use optional chaining and nullish coalescing together to provide a default value when the property is undefined:

-    } = ctx.update?.message;
+    } = ctx.update?.message ?? {};

This way, if ctx.update or ctx.update.message is undefined, an empty object will be used as a default value, preventing the TypeError.

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} = ctx.update?.message;
} = ctx.update?.message ?? {};
Tools
Biome

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Outside diff range and nitpick comments (4)
apps/question/src/dto/QuestionText.ts (1)

1-3: LGTM!

The QuestionText class follows a simple and clear DTO pattern, encapsulating the text content of a question. The structure and syntax are correct.

Consider marking the text property as readonly if immutability is desired:

export class QuestionText {
-  text: string;
+  readonly text: string;
}

This ensures that the text property can only be assigned during initialization and cannot be modified afterwards, promoting immutability and reducing the risk of unintended mutations.

apps/question/test/app.e2e-spec.ts (1)

6-24: Add more test cases to cover the actual functionality.

The test suite is set up correctly and ensures that the basic routing and response functionality of the QuestionController is working as expected. However, it only tests a single endpoint with a hardcoded response.

Consider adding more test cases to cover the actual functionality of the QuestionController and test other endpoints as well. This will ensure that the QuestionController is thoroughly tested and working as expected.

apps/question/src/question.controller.spec.ts (1)

19-24: Add more meaningful test cases and fix the typo in the commented-out expectation.

The current test case is a placeholder that only checks if the questionController instance is truthy. Consider adding more meaningful test cases that cover the functionality of the QuestionController.

Also, the commented-out expectation has a typo in the class name. It should be questionController instead of questionServiceController.

Apply this diff to fix the typo in the commented-out expectation:

-// expect(questionServiceController.message ()).toBe('Hello World!');
+// expect(questionController.message()).toBe('Hello World!');
apps/question/src/question.controller.ts (1)

21-49: Consider adding error handling.

The message method could benefit from error handling to catch and log any potential errors during processing. This will help diagnose issues and prevent unhandled exceptions.

Wrap the core logic inside a try-catch block:

@MessagePattern(UpdateEvent.MESSAGE)
async message(@Payload() ctx: Context): Promise<void> {
  try {
    // existing logic
  } catch (error) {
    this.logger.error(`Error processing message ${message_id} from ${chat_id}: ${error.message}`);
    // optionally, send an error response back to the user
  }
}
Tools
Biome

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 64afacf and be21c18.

Files selected for processing (13)
  • apps/bot/src/main.ts (0 hunks)
  • apps/question/src/dto/QuestionResult.ts (1 hunks)
  • apps/question/src/dto/QuestionText.ts (1 hunks)
  • apps/question/src/main.ts (1 hunks)
  • apps/question/src/question.controller.spec.ts (1 hunks)
  • apps/question/src/question.controller.ts (1 hunks)
  • apps/question/src/question.module.ts (1 hunks)
  • apps/question/src/question.service.ts (1 hunks)
  • apps/question/test/app.e2e-spec.ts (1 hunks)
  • apps/question/test/jest-e2e.json (1 hunks)
  • apps/question/tsconfig.app.json (1 hunks)
  • docker-compose.yml (3 hunks)
  • nest-cli.json (1 hunks)
Files not reviewed due to no reviewable changes (1)
  • apps/bot/src/main.ts
Files skipped from review as they are similar to previous changes (1)
  • docker-compose.yml
Additional context used
Biome
apps/question/src/question.controller.ts

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Additional comments not posted (14)
apps/question/src/dto/QuestionResult.ts (1)

1-4: LGTM!

The QuestionResult class is well-structured and provides a clear representation of a question result. The use of a union type for label ensures type safety and restricts the possible values to 'QUESTION' or 'STATEMENT'. The score property being of type number is appropriate for representing a numeric score value.

Exporting the class makes it accessible for use in other parts of the application, promoting code reuse and maintainability.

apps/question/test/jest-e2e.json (1)

1-9: LGTM!

The Jest configuration settings are appropriate for E2E testing in a TypeScript environment. The settings ensure that only relevant test files are executed during testing and that TypeScript and JavaScript files are compiled before running the tests.

apps/question/tsconfig.app.json (1)

1-16: LGTM!

The TypeScript configuration for the apps/question application looks good:

  • Extending the base configuration at ../../tsconfig.json allows for sharing common settings across projects.
  • Disabling declaration generation with "declaration": false is appropriate for an application project.
  • Setting the output directory to ../../dist/apps/question keeps the build output organized.
  • Including all TypeScript files in the src directory ensures all relevant files are compiled.
  • Excluding node_modules, dist, test, and **/*spec.ts prevents unnecessary files from being compiled.

The configuration follows best practices and is consistent with a standard TypeScript application setup.

apps/question/src/main.ts (1)

5-12: LGTM!

The bootstrap function follows the recommended practices for setting up a NestJS application with microservices:

  • It creates an instance of the NestJS application using the QuestionModule.
  • It retrieves an instance of RmqService and uses it to configure a microservice connection based on a specified queue for the TGQuestionService.
  • The application then starts all microservices, allowing it to handle incoming messages through the configured RabbitMQ service.

This setup is crucial for enabling microservice communication within the application architecture.

apps/question/src/question.service.ts (2)

7-23: LGTM!

The QuestionService class has a clear purpose and follows best practices:

  • It adheres to the single responsibility principle by focusing on handling HTTP requests related to questions.
  • It leverages dependency injection for configuration and HTTP handling, promoting loose coupling and testability.
  • It is properly annotated with @Injectable(), making it available for dependency injection.

18-22: LGTM!

The test method is implemented correctly:

  • It has a clear purpose of making a POST request with the provided text.
  • It uses the HttpService from NestJS to make the request, which is a good practice.
  • The return type is properly annotated, providing clarity on the expected response.
apps/question/test/app.e2e-spec.ts (1)

1-4: LGTM!

The necessary modules are imported correctly for setting up the testing module and making HTTP requests to the application.

apps/question/src/question.module.ts (4)

1-12: LGTM!

The imports are relevant and necessary for the module. The code segment looks good.


14-24: LGTM!

The QuestionModule definition looks good. The imports, configurations, and module registrations are set up correctly.


25-26: LGTM!

The QuestionController and QuestionService declarations are correct. They will handle the incoming requests and business logic related to questions.


27-28: LGTM!

The QuestionModule class is exported correctly. The code segment looks good.

apps/question/src/question.controller.spec.ts (1)

1-3: LGTM!

The imports are correct and necessary for setting up the testing module.

nest-cli.json (1)

48-56: LGTM!

The addition of the "question" service configuration in the nest-cli.json file follows the established structure and pattern of other service configurations. This change enables the proper integration and utilization of the "question" service within the NestJS framework, facilitating its development and deployment as part of the application architecture.

The configuration specifies the necessary details, such as the service type, root directory, entry file, source root, and TypeScript configuration path, ensuring consistency and compatibility with the existing setup.

Overall, this is a well-structured and beneficial addition to the project configuration.

apps/question/src/question.controller.ts (1)

21-49: The method implementation looks good overall.

The message method follows a clear flow of receiving a message, processing it, constructing a response, and sending it back. The use of the QuestionService to process the message text and the ClientProxy to send the response back to the Telegram bot is a good approach.

Tools
Biome

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Comment on lines 14 to 16
questionController = app.get<QuestionServiceController>(
QuestionServiceController,
);
Copy link

Choose a reason for hiding this comment

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

Fix the typo in the class name.

There is a typo in the class name used to retrieve the questionController instance. It should be QuestionController instead of QuestionServiceController.

Apply this diff to fix the typo:

-questionController = app.get<QuestionServiceController>(
-  QuestionServiceController,
-);
+questionController = app.get<QuestionController>(
+  QuestionController,
+);
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
questionController = app.get<QuestionServiceController>(
QuestionServiceController,
);
questionController = app.get<QuestionController>(
QuestionController,
);

message_id,
text: msg,
chat: { id: chat_id },
} = ctx.update?.message;
Copy link

Choose a reason for hiding this comment

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

Fix the unsafe usage of optional chaining.

The static analysis tool has flagged the use of optional chaining at line 26 as potentially unsafe. If ctx.update is undefined, it will lead to a runtime error.

To fix this, add a null check before accessing ctx.update.message:

-    } = ctx.update?.message;
+    } = ctx.update?.message || {};
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} = ctx.update?.message;
} = ctx.update?.message || {};
Tools
Biome

[error] 26-26: Unsafe usage of optional chaining.

If it short-circuits with 'undefined' the evaluation will throw TypeError here:

(lint/correctness/noUnsafeOptionalChaining)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between be21c18 and 9b00549.

Files selected for processing (2)
  • apps/question/src/question.controller.spec.ts (1 hunks)
  • libs/common/src/rmq/interceptors/events.interceptor.spec.ts (1 hunks)
Files skipped from review as they are similar to previous changes (1)
  • apps/question/src/question.controller.spec.ts
Additional comments not posted (1)
libs/common/src/rmq/interceptors/events.interceptor.spec.ts (1)

29-31: LGTM!

This is a good sanity check to ensure the interceptor is properly instantiated and defined.

Comment on lines +33 to +64
// it('should call ack method of RmqService when intercepting', () => {
// const mockContext = {
// switchToRpc: jest.fn().mockReturnThis(),
// getContext: jest.fn().mockReturnValue({
// getChannelRef: jest.fn(),
// getMessage: jest.fn(),
// }),
// } as unknown as ExecutionContext;
// const mockCallHandler = {
// handle: jest.fn().mockReturnValue(of(null)), // Mock returning an observable
// } as CallHandler;

// // Intercept the call
// interceptor.intercept(mockContext, mockCallHandler);

// // You can assert that the ack method is called synchronously

// // If you want to assert behavior from the observable, you can subscribe to it
// // and add your assertions inside the subscribe block
// mockCallHandler.handle().subscribe({
// next: () => {
// // Assert behavior here
// },
// error: () => {
// // Handle error if needed
// },
// complete: () => {
// // Handle completion if needed
// expect(rmqService.ack).toHaveBeenCalled();
// },
// });
// });
Copy link

Choose a reason for hiding this comment

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

Complete and enable the commented-out test case.

This test case provides a good structure for validating the interceptor's behavior when processing messages. However, it is currently incomplete and commented out.

Please complete the test case by:

  1. Uncomment the test case.
  2. Add the necessary assertions to validate the ack method is called on the RmqService.
  3. Handle any errors or completions appropriately.

Enabling this test case will help ensure the interceptor's interaction with the message queue service is thoroughly validated.

@cyri113 cyri113 merged commit d77ba84 into main Sep 17, 2024
4 checks passed
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.

1 participant