Repository: Hexastack/Hexabot
Pull request #871: fix: cleanup languageId from NlpSamples on language deletion
Author: login: abdou6666
Created: 2025-04-02T10:46:01Z | Merged: 2025-04-12T06:02:04Z

# Motivation

On language deletion we must cleanup the `languageId` in `NlpSamples`

Fixes #781

# Type of change:

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# Checklist:

- [x] I have performed a self-review of my own code

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **Refactor**
  - Enhanced the language removal process to better support bulk deletions.
  - Improved data consistency by ensuring associated records are updated accurately when languages are removed.
  - Updated event handling for language deletions to operate at a different timing.
  - Removed obsolete pre-deletion logic for languages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Linked issue #781: 🤔 [ISSUE] - delete language need to update related collections
### Description

### Description
We can notice that the language in included in more that one collection.
Currently, when you delete a language the other linked collection will preserve the invalid ObjectId.
The goal is to update the related collections to remove the language id from him (NlpSample)

### Reproduction steps

```bash
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
```

### Logs

```bash

```

### Browsers

_No response_

### OS

_No response_
Linked issue comments: user: login: yassinedorbozgithub
created_at: 2025-02-19T06:14:22Z
body: Hi @yassine-sallemi 
author_association: COLLABORATOR

Diff:
diff --git a/api/src/i18n/repositories/language.repository.ts b/api/src/i18n/repositories/language.repository.ts
index 091280547..77bf26a70 100644
--- a/api/src/i18n/repositories/language.repository.ts
+++ b/api/src/i18n/repositories/language.repository.ts
@@ -8,10 +8,9 @@
 
 import { Injectable } from '@nestjs/common';
 import { InjectModel } from '@nestjs/mongoose';
-import { Document, Model, Query } from 'mongoose';
+import { Model } from 'mongoose';
 
-import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository';
-import { TFilterQuery } from '@/utils/types/filter.types';
+import { BaseRepository } from '@/utils/generics/base-repository';
 
 import { LanguageDto } from '../dto/language.dto';
 import { Language } from '../schemas/language.schema';
@@ -26,30 +25,4 @@ export class LanguageRepository extends BaseRepository<
   constructor(@InjectModel(Language.name) readonly model: Model<Language>) {
     super(model, Language);
   }
-
-  /**
-   * Pre-delete hook that triggers before an language is deleted.
-   *
-   * @param query The query used to delete the language.
-   * @param criteria The filter criteria used to find the language for deletion.
-   */
-  async preDelete(
-    _query: Query<
-      DeleteResult,
-      Document<Language, any, any>,
-      unknown,
-      Language,
-      'deleteOne' | 'deleteMany'
-    >,
-    _criteria: TFilterQuery<Language>,
-  ): Promise<void> {
-    if (_criteria._id) {
-      const language = await this.find(
-        typeof _criteria === 'string' ? { _id: _criteria } : _criteria,
-      );
-      this.eventEmitter.emit('hook:language:delete', language);
-    } else {
-      throw new Error('Attempted to delete language using unknown criteria');
-    }
-  }
 }
diff --git a/api/src/nlp/services/nlp-sample.service.ts b/api/src/nlp/services/nlp-sample.service.ts
index f2f33e7d5..665f8cc74 100644
--- a/api/src/nlp/services/nlp-sample.service.ts
+++ b/api/src/nlp/services/nlp-sample.service.ts
@@ -12,13 +12,15 @@ import {
   NotFoundException,
 } from '@nestjs/common';
 import { OnEvent } from '@nestjs/event-emitter';
+import { Document, Query } from 'mongoose';
 import Papa from 'papaparse';
 
 import { Message } from '@/chat/schemas/message.schema';
 import { Language } from '@/i18n/schemas/language.schema';
 import { LanguageService } from '@/i18n/services/language.service';
+import { DeleteResult } from '@/utils/generics/base-repository';
 import { BaseService } from '@/utils/generics/base-service';
-import { THydratedDocument } from '@/utils/types/filter.types';
+import { TFilterQuery, THydratedDocument } from '@/utils/types/filter.types';
 
 import { NlpSampleEntityCreateDto } from '../dto/nlp-sample-entity.dto';
 import { NlpSampleCreateDto, TNlpSampleDto } from '../dto/nlp-sample.dto';
@@ -233,16 +235,48 @@ export class NlpSampleService extends BaseService<
    *
    * @param language The language that has been deleted.
    */
-  @OnEvent('hook:language:delete')
-  async handleLanguageDelete(language: Language) {
-    await this.updateMany(
-      {
-        language: language.id,
-      },
+  @OnEvent('hook:language:preDelete')
+  async handleLanguageDelete(
+    _query: Query<
+      DeleteResult,
+      Document<Language, any, any>,
+      unknown,
+      Language,
+      'deleteOne' | 'deleteMany'
+    >,
+    criteria: TFilterQuery<Language>,
+  ) {
+    const deletedLanguages = await this.languageService.find(
+      criteria,
+      undefined,
       {
-        language: null,
+        id: 1,
       },
     );
+    const deletedLanguagesIds = deletedLanguages.map(
+      (deletedLanguage) => deletedLanguage.id,
+    );
+
+    this.logger.debug(
+      `Found ${deletedLanguagesIds.length} languages to clean up`,
+    );
+
+    if (deletedLanguagesIds.length > 0) {
+      await this.updateMany(
+        {
+          language: {
+            $in: deletedLanguagesIds,
+          },
+        },
+        {
+          language: null,
+        },
+      ).then((result) => {
+        this.logger.debug(
+          `Cleaned up languageId from ${result.modifiedCount} NLP samples`,
+        );
+      });
+    }
   }
 
   @OnEvent('hook:message:preCreate')


Reviews:
user: login: MohamedAliBouhaouala
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T15:11:28Z
user: login: IkbelTalebHssan
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T15:21:08Z
user: login: marrouchi
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T09:04:25Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (1)</summary><blockquote>

`240-271`: **Handle pre-deletion of languages and clear references in samples.**
Logic correctly finds the soon-to-be-deleted languages, collects their IDs, and sets them to `null` in related samples. Two suggestions:  
1. Consider removing or explaining the `_query` parameter if not needed, to reduce confusion.  
2. (Optional) Wrap the call to `updateMany` in a try-catch if you anticipate potential errors or connection issues, ensuring consistent cleanup.

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between fd709ff6d47347cbd8a1ac424e015b3ea66bfe68 and f94a11b1511717e7050670c16a981bfea801d49c.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `api/src/i18n/repositories/language.repository.ts` (2 hunks)
* `api/src/nlp/services/nlp-sample.service.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Definitions (1)</summary>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (1)</summary><blockquote>

<details>
<summary>api/src/utils/generics/base-repository.ts (1)</summary>

* `DeleteResult` (38-41)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>api/src/i18n/repositories/language.repository.ts (3)</summary>

`2-2`: **License header update looks fine.**
No issues identified.

---

`12-12`: **Import statement for Mongoose Model.**
No issues noted; appears necessary for repository interaction.

---

`14-14`: **BaseRepository import inclusion.**
No concerns; aligns with the repository pattern.

</details>
<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (1)</summary>

`15-15`: **Refined imports for Mongoose types and DeleteResult.**
These new imports align with the updated logic and usage of Mongoose's `Query` and the custom `DeleteResult`. No issues found.  



Also applies to: 22-22, 24-24

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T08:01:32Z
user: login: marrouchi
body: @abdou6666 Can you please rebase the PR ?
state: CHANGES_REQUESTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T08:07:15Z
user: login: yassinedorbozgithub
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-12T05:48:06Z
user: login: coderabbitai[bot]
body: **Actionable comments posted: 0**

<details>
<summary>♻️ Duplicate comments (1)</summary><blockquote>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (1)</summary><blockquote>

`260-271`: **Properly handles empty deletedLanguagesIds array.**

The implementation now checks if `deletedLanguagesIds` has elements before executing the update, addressing the previous review comments from marrouchi and yassinedorbozgithub. This prevents unnecessary database operations when no languages match the deletion criteria.

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (1)</summary><blockquote>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (1)</summary><blockquote>

`238-272`: **Consider adding logging for this cleanup operation.**

While the implementation is correct, adding logging statements would improve debuggability. Consider logging the number of languages being deleted and the number of samples affected.


```diff
async handleLanguageDelete(
  _query: Query<
    DeleteResult,
    Document<Language, any, any>,
    unknown,
    Language,
    'deleteOne' | 'deleteMany'
  >,
  criteria: TFilterQuery<Language>,
) {
  const deletedLanguages = await this.languageService.find(
    criteria,
    undefined,
    {
      id: 1,
    },
  );
  const deletedLanguagesIds = deletedLanguages.map(
    (deletedLanguage) => deletedLanguage.id,
  );

+ this.logger.debug(`Found ${deletedLanguagesIds.length} languages to clean up`);

  if (deletedLanguagesIds.length > 0) {
    await this.updateMany(
      {
        language: {
          $in: deletedLanguagesIds,
        },
      },
      {
        language: null,
      },
+     ).then(result => {
+       this.logger.debug(`Cleaned up languageId from ${result.modifiedCount} NLP samples`);
+     });
  }
}
```

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between e350afe3d156047c7a1985875996ead8a907eacb and f74066b577a0cdcbd86d1adbcc6b27d6fe85670d.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `api/src/nlp/services/nlp-sample.service.ts` (2 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧬 Code Graph Analysis (1)</summary>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (2)</summary><blockquote>

<details>
<summary>api/src/utils/generics/base-repository.ts (1)</summary>

* `DeleteResult` (40-43)

</details>
<details>
<summary>api/src/utils/types/filter.types.ts (1)</summary>

* `TFilterQuery` (129-137)

</details>

</blockquote></details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: API-Tests
* GitHub Check: Analyze (javascript-typescript)
* GitHub Check: Frontend Tests

</details>

<details>
<summary>🔇 Additional comments (4)</summary><blockquote>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (4)</summary>

`15-15`: **Good imports update to support the new implementation.**

The import changes align well with the updated method implementation. Adding `Document` and `Query` from mongoose, `DeleteResult` from the base repository, and replacing `THydratedDocument` with `TFilterQuery` properly supports the new parameter types in the `handleLanguageDelete` method.



Also applies to: 21-21, 23-23

---

`238-238`: **Improved event handling timing with preDelete hook.**

Changing from `hook:language:delete` to `hook:language:preDelete` is a good improvement. This ensures that NLP samples are cleaned up before the language is actually deleted, preventing potential referential integrity issues.

---

`239-248`: **Enhanced method signature for more flexible language deletion.**

The updated parameter signature allows for handling multiple language deletions in a single operation. The `_query` parameter provides the mongoose query context, while the `criteria` parameter allows for flexible filtering of languages to be deleted.

---

`249-259`: **Good implementation for retrieving deleted languages.**

The implementation effectively retrieves all languages matching the deletion criteria and extracts their IDs. This approach is more robust than handling a single language at a time.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-12T05:55:28Z
user: login: yassinedorbozgithub
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-12T05:56:05Z

Review comments:
diff_hunk: @@ -43,14 +43,17 @@ export class LanguageRepository extends BaseRepository<
       Document<Language, any, any>,
       unknown,
       Language,
-      'deleteOne' | 'deleteMany'
+      'deleteOne'
path: api/src/i18n/repositories/language.repository.ts
user: login: marrouchi
body: Let's remove this function and use OnEvent('hook:language:preDelete') in the NlpSampleService.
const languages = this.languageService.find(criteria)
await this.nlpSampleService.updateMany(criteria, { $set:{ language: null } })
created_at: 2025-04-03T09:04:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -235,11 +237,32 @@ export class NlpSampleService extends BaseService<
    *
    * @param language The language that has been deleted.
    */
-  @OnEvent('hook:language:delete')
-  async handleLanguageDelete(language: Language) {
+  @OnEvent('hook:language:preDelete')
+  async handleLanguageDelete(
+    _query: Query<
+      DeleteResult,
+      Document<Language, any, any>,
+      unknown,
+      Language,
+      'deleteOne' | 'deleteMany'
+    >,
+    criteria: TFilterQuery<Language>,
+  ) {
+    const deletedLanguages = await this.languageService.find(
+      criteria,
+      undefined,
+      {
+        id: 1,
+      },
+    );
+    const deletedLanguagesIds = deletedLanguages.map(
+      (deletedLanguage) => deletedLanguage.id,
+    );
     await this.updateMany(
       {
-        language: language.id,
+        language: {
+          $in: deletedLanguagesIds,
path: api/src/nlp/services/nlp-sample.service.ts
user: login: marrouchi
body: What will be the behavior if deletedLanguagesIds is an empty array ? Ensuring the unit test covers this edge case can be beneficial.
created_at: 2025-04-07T08:06:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -235,11 +237,32 @@ export class NlpSampleService extends BaseService<
    *
    * @param language The language that has been deleted.
    */
-  @OnEvent('hook:language:delete')
-  async handleLanguageDelete(language: Language) {
+  @OnEvent('hook:language:preDelete')
+  async handleLanguageDelete(
+    _query: Query<
+      DeleteResult,
+      Document<Language, any, any>,
+      unknown,
+      Language,
+      'deleteOne' | 'deleteMany'
+    >,
+    criteria: TFilterQuery<Language>,
+  ) {
+    const deletedLanguages = await this.languageService.find(
+      criteria,
+      undefined,
+      {
+        id: 1,
+      },
+    );
+    const deletedLanguagesIds = deletedLanguages.map(
+      (deletedLanguage) => deletedLanguage.id,
+    );
     await this.updateMany(
       {
-        language: language.id,
+        language: {
+          $in: deletedLanguagesIds,
path: api/src/nlp/services/nlp-sample.service.ts
user: login: yassinedorbozgithub
body: I think that we need to add an if condition to check if deletedLanguagesIds  has elements so we  execute the update 
created_at: 2025-04-12T05:48:06Z
author_association: COLLABORATOR

PR comments:
user: login: marrouchi
created_at: 2025-04-07T07:58:19Z
body: @coderabbitai review
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-04-07T07:58:28Z
body: <!-- This is an auto-generated reply by CodeRabbit -->
<details>
<summary>:white_check_mark: Actions performed</summary>

Review triggered.

> Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

</details>
author_association: CONTRIBUTOR
user: login: coderabbitai[bot]
created_at: 2025-04-07T07:58:31Z
body: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- walkthrough_start -->

## Walkthrough
This pull request removes the `preDelete` method from the language repository and refines its import statements. Additionally, it updates the `handleLanguageDelete` method in the NLP sample service. The service now listens for a pre-deletion event, accepts a query and deletion criteria, retrieves related languages based on these parameters, and updates associated samples by setting their language field to null. These changes streamline pre-deletion logic and ensure that related collections are updated according to deletion activities.

## Changes

| Files                                           | Change Summary                                                                                                                                                                                                                          |
|-------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `api/.../language.repository.ts`                | Removed `preDelete` method; updated import statements by removing unused imports (`Document, Query, DeleteResult, TFilterQuery`) while keeping necessary ones (e.g., `Model`, `BaseRepository`).                                  |
| `api/.../nlp-sample.service.ts`                 | Updated `handleLanguageDelete` method signature to accept a `Query` object and `TFilterQuery` criteria; changed event hook from `hook:language:delete` to `hook:language:preDelete`; modified logic to update many samples.       |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant EventBus
    participant NLPSampleService
    participant LanguageService
    participant SampleDB

    EventBus->>NLPSampleService: trigger hook:language:preDelete (Query, Criteria)
    NLPSampleService->>LanguageService: find(deletion criteria)
    LanguageService-->>NLPSampleService: returns deleted languages list
    NLPSampleService->>SampleDB: updateMany (set language field to null for matching samples)
    SampleDB-->>NLPSampleService: update result
```

## Assessment against linked issues

| Objective                                                 | Addressed | Explanation |
|-----------------------------------------------------------|-----------|-------------|
| Update related collections on language deletion (#781)   | ✅        |             |

## Poem
> Oh, I hop with glee in the codewood glen,  
> Removing old methods and streamlining again,  
> I nibble at queries with a joyful tune,  
> Updating samples under the silvery moon,  
> Code flows like carrots, crisp and light.  
> Hoppy coding days, from morning until night!

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f74066b577a0cdcbd86d1adbcc6b27d6fe85670d and 55d1eade0055d114afd4be2ac0bc328bc1c3401c.

</details>

<details>
<summary>📒 Files selected for processing (1)</summary>

* `api/src/nlp/services/nlp-sample.service.ts` (2 hunks)

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (3)</summary>

* GitHub Check: API-Tests
* GitHub Check: Analyze (javascript-typescript)
* GitHub Check: Frontend Tests

</details>

<details>
<summary>🔇 Additional comments (5)</summary><blockquote>

<details>
<summary>api/src/nlp/services/nlp-sample.service.ts (5)</summary>

`15-15`: **Appropriate type additions for the updated method signature**

The new imports for `Document`, `Query`, `DeleteResult`, and `TFilterQuery` properly support the updated method signature and implementation. These types provide better type safety and clarity for the refactored code.



Also applies to: 21-21, 23-23

---

`238-248`: **Good event timing change and improved method signature**

Changing from `hook:language:delete` to `hook:language:preDelete` is a good approach as it ensures the cleanup happens before the actual deletion, preventing reference integrity issues. The updated method signature with mongoose types is more robust and provides better type safety.

---

`249-258`: **Effective language lookup implementation**

The implementation efficiently retrieves all languages matching the deletion criteria and extracts their IDs for later processing. This approach handles both single and bulk deletions properly.

---

`260-262`: **Helpful debug logging**

Adding debug logging for the number of languages to clean up improves observability and helps with troubleshooting.

---

`264-279`: **Effective guard clause and bulk update implementation**

The conditional check on line 264 properly addresses the concern from previous reviewers about handling empty arrays. The bulk update operation is efficient and the logging of modified count provides useful feedback.


The implementation now correctly:
1. Only runs the update when there are languages to process
2. Updates all affected samples in a single operation
3. Logs the result for monitoring purposes

</details>

</blockquote></details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details>
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---



<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=Hexastack/Hexabot&utm_content=871):

- 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 gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@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 generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai plan` to trigger planning for file edits and PR creation.
- `@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](https://docs.coderabbit.ai/guides/configure-coderabbit) 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](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
author_association: CONTRIBUTOR