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

delete temporal schedule for discourse. #412

Merged
merged 1 commit into from
Dec 1, 2024
Merged

Conversation

cyri113
Copy link
Contributor

@cyri113 cyri113 commented Nov 26, 2024

Adds the function of deleting the temporal schedule associated with the discourse extraction.

Summary by CodeRabbit

  • New Features

    • Introduced a function to delete discourse schedules by their ID.
    • Added methods to pause and delete schedules within the Temporal Discourse service.
    • Enhanced platform deletion logic to handle associated discourse schedules.
  • Bug Fixes

    • Improved error logging for schedule creation.

These changes enhance the management of discourse schedules and streamline platform deletions, improving overall user experience.

Copy link

coderabbitai bot commented Nov 26, 2024

Walkthrough

The changes introduce a new function, deleteDiscourseSchedule, to the core.service.ts file, enabling the deletion of a discourse schedule by its scheduleId with error handling. The createDiscourseSchedule function's error logging was also slightly modified. In platform.service.ts, the deletePlatform function was updated to incorporate logic for handling Discourse platforms, including calling the new deletion function. Additionally, two new methods, pauseSchedule and deleteSchedule, were added to the TemporalDiscourseService class in discourse.service.ts.

Changes

File Path Change Summary
src/services/discourse/core.service.ts - Added async function deleteDiscourseSchedule(scheduleId: string): Promise<void>
- Updated error logging in createDiscourseSchedule
src/services/platform.service.ts - Modified deletePlatform to include a switch-case for handling PlatformNames.Discourse and call deleteDiscourseSchedule
- Updated deletePlatformByFilter to call modified deletePlatform
src/services/temporal/discourse.service.ts - Added public async pauseSchedule(scheduleId: string): Promise<void>
- Added public async deleteSchedule(scheduleId: string): Promise<void>

Possibly related PRs

  • 390 discourse platform + violation detection module #396: Modifications to src/services/discourse/core.service.ts, including updates to createDiscourseSchedule, which relates to the new deleteDiscourseSchedule function.
  • Add temporal #407: Changes in src/services/temporal/discourse.service.ts that introduce a createSchedule method relevant to the discourse scheduling context.

Suggested reviewers

  • Behzad-rabiei

Poem

🐰 In the meadow where schedules play,
A new function hops in today!
Deleting with care, oh what a sight,
Discourse schedules, take flight!
With pause and delete, we dance with glee,
In the code's embrace, so wild and free! 🌼


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 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 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: 4

🧹 Outside diff range and nitpick comments (1)
src/services/discourse/core.service.ts (1)

28-30: Consider using a standard HTTP status code

The error code 590 is outside the standard HTTP status code range (100-599). Consider using a more standard error code, such as 500 for internal server errors or 503 for service unavailable.

-    throw new ApiError(590, 'Failed to create discourse schedule.');
+    throw new ApiError(503, 'Failed to create discourse schedule.');
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ba9d132 and e54c1eb.

📒 Files selected for processing (3)
  • src/services/discourse/core.service.ts (1 hunks)
  • src/services/platform.service.ts (2 hunks)
  • src/services/temporal/discourse.service.ts (1 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
src/services/platform.service.ts

[error] 148-152: This case is falling through to the next case.

Add a break or return statement to the end of this case to prevent fallthrough.

(lint/suspicious/noFallthroughSwitchClause)

🔇 Additional comments (5)
src/services/temporal/discourse.service.ts (1)

30-40: Consider architectural implications of schedule management.

A few architectural considerations for the schedule management implementation:

  1. Should we ensure cleanup of any in-progress workflows when deleting a schedule?
  2. Consider implementing a status check before operations to prevent race conditions between pause/delete operations.
  3. Consider adding a method to list active schedules for better management.

Let's verify the usage pattern:

✅ Verification successful

Schedule management implementation appears sufficient with existing safeguards

Based on the verification results:

  1. The schedule operations are part of a larger system with proper transaction management, as seen in the announcement service.
  2. Schedule operations (create/pause/delete) are atomic operations provided by the Temporal client, which handles race conditions internally.
  3. The system already implements proper error handling and rollback mechanisms through database transactions.

The initial architectural concerns are addressed:

  • Cleanup: Temporal handles workflow cleanup internally when a schedule is deleted
  • Race conditions: Temporal's schedule handle operations are atomic
  • Management: The system has comprehensive schedule lifecycle management through create, pause, and delete operations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for potential race conditions or cleanup patterns in schedule management

# Look for places where pause and delete are called in sequence
rg -A 5 "pauseSchedule.*deleteSchedule"

# Check for any cleanup patterns in workflow definitions
ast-grep --pattern 'class $_ implements WorkflowInterface {
  $$$
  cleanup() {
    $$$
  }
  $$$
}'

Length of output: 144


Script:

#!/bin/bash
# Let's try a broader search to understand the schedule management patterns

# Search for schedule-related method calls
rg -B 2 -A 2 "schedule\.(pause|delete|getHandle)"

# Look for workflow implementations
rg -l "implements.*Workflow"

# Search for any error handling or cleanup patterns around schedule operations
rg -B 2 -A 2 "(try|catch).*schedule"

# Look for schedule creation patterns to understand lifecycle
rg -B 2 -A 2 "createSchedule"

Length of output: 3096


Script:

#!/bin/bash
# Let's examine the error handling and transaction patterns in schedule-related operations

# Check the implementation of createSchedule for error handling
rg -B 5 -A 10 "createSchedule.*Promise.*{" 

# Look for transaction patterns around schedule operations
rg -B 3 -A 3 "startTransaction|commitTransaction|abortTransaction"

# Check for any schedule-related error handling in the discourse service
rg -B 3 -A 3 "catch.*schedule" src/services/temporal/discourse.service.ts

# Look for any schedule cleanup or status check implementations
rg -B 3 -A 3 "schedule.*status|schedule.*check"

Length of output: 5202

src/services/discourse/core.service.ts (2)

45-45: LGTM!

The export addition follows the existing pattern and correctly exposes the new functionality.


33-38: Verify temporal workflow integration

Let's verify that the temporal workflow properly handles the schedule deletion.

✅ Verification successful

Let me gather more information about the temporal workflow integration.


Let me do one final check to verify the client initialization and error handling.


Temporal workflow integration is properly implemented

The deletion functionality is correctly integrated with the temporal workflow:

  • The deleteDiscourseSchedule function properly calls the temporal service
  • The temporal service correctly obtains the client, gets the schedule handle, and calls the delete method
  • Error handling is implemented at the service level with appropriate logging
  • The implementation follows the same pattern as other schedule operations (e.g., pause)
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for references to deleteSchedule to ensure proper integration
rg -A 5 "deleteSchedule" --type ts

# Look for any potential error handling in temporal workflow
ast-grep --pattern 'catch (error) {
  $$$
  deleteSchedule($$$)
  $$$
}'

Length of output: 1029


Script:

#!/bin/bash
# Check the temporal client initialization and error handling
ast-grep --pattern 'class TemporalDiscourseService {
  $$$
  getClient() {
    $$$
  }
  $$$
}'

# Look for schedule handle usage patterns
rg -A 5 "schedule.getHandle" --type ts

# Check for any tests related to schedule deletion
rg -A 5 "deleteSchedule.*test" --type ts

Length of output: 1041


Script:

#!/bin/bash
# Check temporal client initialization
rg -A 10 "class TemporalDiscourseService" --type ts

# Look for any workflow definitions that might be related
rg -A 5 "workflow.ts" --type ts

# Check for any schedule-related interfaces or types
rg -A 5 "interface.*Schedule" --type ts

Length of output: 1064

src/services/platform.service.ts (2)

169-169: LGTM!

Good change to reuse the deletePlatform function, ensuring consistent cleanup across all deletion paths.


Line range hint 147-169: Verify all Discourse platform deletion paths

Let's ensure all Discourse platform deletions go through this code path and no deletion bypasses the schedule cleanup.

✅ Verification successful

Let me gather more specific information about the deletion paths.


All Discourse platform deletions are properly handled

The verification shows that all platform deletions are centralized and properly handled:

  • All platform deletions go through platformService.deletePlatform() or deletePlatformByFilter() which internally calls deletePlatform()
  • The deletion logic in platform.service.ts properly handles Discourse schedule cleanup
  • There are no direct platform removals bypassing this logic - the only platform.remove() call is within the verified deletePlatform method
  • The platform controller's delete endpoint routes through the same service methods
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Find all platform deletion code paths

# Search for direct platform removals
echo "Checking for direct platform removals:"
rg -l "platform.*remove\(\)" --type ts

# Search for other deletion methods
echo "Checking for other deletion methods:"
rg -l "delete.*[Pp]latform" --type ts

# Search for Discourse-specific operations
echo "Checking for Discourse-specific operations:"
rg -l "PlatformNames\.Discourse" --type ts

Length of output: 849


Script:

#!/bin/bash
# Check platform deletion implementations and routes
echo "=== Platform Service Deletion Methods ==="
rg "delete.*[Pp]latform" src/services/platform.service.ts -B 2 -A 2

echo -e "\n=== Platform Controller Deletion Methods ==="
rg "delete.*[Pp]latform" src/controllers/platform.controller.ts -B 2 -A 2

echo -e "\n=== Platform Routes ==="
rg "delete.*[Pp]latform" src/routes/v1/platform.route.ts -B 2 -A 2

# Check if there are any other methods that might remove platforms
echo -e "\n=== Other Platform Removal Methods ==="
rg "platform.*remove" --type ts -B 2 -A 2

Length of output: 2780

🧰 Tools
🪛 Biome (1.9.4)

[error] 148-152: This case is falling through to the next case.

Add a break or return statement to the end of this case to prevent fallthrough.

(lint/suspicious/noFallthroughSwitchClause)

Comment on lines +30 to +34
public async pauseSchedule(scheduleId: string): Promise<void> {
const client: Client = await this.getClient();
const handle = client.schedule.getHandle(scheduleId);
await handle.pause();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling and input validation.

The method needs additional safeguards for production reliability:

  1. Error handling for invalid scheduleId or network failures
  2. Input validation
  3. Method documentation

Consider this improved implementation:

+ /**
+  * Pauses a Discourse schedule by its ID
+  * @param scheduleId - The ID of the schedule to pause
+  * @throws Error if the schedule cannot be paused or doesn't exist
+  */
  public async pauseSchedule(scheduleId: string): Promise<void> {
+   if (!scheduleId) {
+     throw new Error('Schedule ID is required');
+   }
    const client: Client = await this.getClient();
-   const handle = client.schedule.getHandle(scheduleId);
-   await handle.pause();
+   try {
+     const handle = client.schedule.getHandle(scheduleId);
+     await handle.pause();
+   } catch (error) {
+     throw new Error(`Failed to pause schedule ${scheduleId}: ${(error as Error).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
public async pauseSchedule(scheduleId: string): Promise<void> {
const client: Client = await this.getClient();
const handle = client.schedule.getHandle(scheduleId);
await handle.pause();
}
/**
* Pauses a Discourse schedule by its ID
* @param scheduleId - The ID of the schedule to pause
* @throws Error if the schedule cannot be paused or doesn't exist
*/
public async pauseSchedule(scheduleId: string): Promise<void> {
if (!scheduleId) {
throw new Error('Schedule ID is required');
}
const client: Client = await this.getClient();
try {
const handle = client.schedule.getHandle(scheduleId);
await handle.pause();
} catch (error) {
throw new Error(`Failed to pause schedule ${scheduleId}: ${(error as Error).message}`);
}
}

Comment on lines +36 to +40
public async deleteSchedule(scheduleId: string): Promise<void> {
const client: Client = await this.getClient();
const handle = client.schedule.getHandle(scheduleId);
await handle.delete();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance deletion method with error handling, validation, and logging.

As this is the core functionality for the PR's objective of deleting temporal schedules, it needs to be robust and auditable.

Consider this enhanced implementation:

+ /**
+  * Deletes a Discourse schedule by its ID
+  * @param scheduleId - The ID of the schedule to delete
+  * @throws Error if the schedule cannot be deleted or doesn't exist
+  */
  public async deleteSchedule(scheduleId: string): Promise<void> {
+   if (!scheduleId) {
+     throw new Error('Schedule ID is required');
+   }
    const client: Client = await this.getClient();
-   const handle = client.schedule.getHandle(scheduleId);
-   await handle.delete();
+   try {
+     const handle = client.schedule.getHandle(scheduleId);
+     // Verify schedule exists before deletion
+     await handle.describe();
+     await handle.delete();
+     console.info(`Successfully deleted Discourse schedule: ${scheduleId}`);
+   } catch (error) {
+     const message = `Failed to delete schedule ${scheduleId}: ${(error as Error).message}`;
+     console.error(message);
+     throw new Error(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
public async deleteSchedule(scheduleId: string): Promise<void> {
const client: Client = await this.getClient();
const handle = client.schedule.getHandle(scheduleId);
await handle.delete();
}
/**
* Deletes a Discourse schedule by its ID
* @param scheduleId - The ID of the schedule to delete
* @throws Error if the schedule cannot be deleted or doesn't exist
*/
public async deleteSchedule(scheduleId: string): Promise<void> {
if (!scheduleId) {
throw new Error('Schedule ID is required');
}
const client: Client = await this.getClient();
try {
const handle = client.schedule.getHandle(scheduleId);
// Verify schedule exists before deletion
await handle.describe();
await handle.delete();
console.info(`Successfully deleted Discourse schedule: ${scheduleId}`);
} catch (error) {
const message = `Failed to delete schedule ${scheduleId}: ${(error as Error).message}`;
console.error(message);
throw new Error(message);
}
}

Comment on lines +33 to +38
async function deleteDiscourseSchedule(scheduleId: string): Promise<void> {
try {
await temporalDiscourse.deleteSchedule(scheduleId);
} catch (error) {
logger.error(error, 'Failed to delete discourse schedule.');
throw new ApiError(590, 'Failed to delete discourse schedule.');
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add input validation and standardize error code

The function implementation looks good but could benefit from these improvements:

  1. Add input validation for scheduleId
  2. Use a standard HTTP status code for consistency
 async function deleteDiscourseSchedule(scheduleId: string): Promise<void> {
+  if (!scheduleId) {
+    throw new ApiError(400, 'Schedule ID is required');
+  }
   try {
     await temporalDiscourse.deleteSchedule(scheduleId);
   } catch (error) {
     logger.error(error, 'Failed to delete discourse schedule.');
-    throw new ApiError(590, 'Failed to delete discourse schedule.');
+    throw new ApiError(503, 'Failed to delete discourse schedule.');
   }
 }
📝 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
async function deleteDiscourseSchedule(scheduleId: string): Promise<void> {
try {
await temporalDiscourse.deleteSchedule(scheduleId);
} catch (error) {
logger.error(error, 'Failed to delete discourse schedule.');
throw new ApiError(590, 'Failed to delete discourse schedule.');
async function deleteDiscourseSchedule(scheduleId: string): Promise<void> {
if (!scheduleId) {
throw new ApiError(400, 'Schedule ID is required');
}
try {
await temporalDiscourse.deleteSchedule(scheduleId);
} catch (error) {
logger.error(error, 'Failed to delete discourse schedule.');
throw new ApiError(503, 'Failed to delete discourse schedule.');
}
}

Comment on lines +147 to +155
switch (platform.name) {
case PlatformNames.Discourse: {
if (platform.metadata?.scheduleId) {
await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
}
}
default: {
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix case fallthrough and add error handling

There are several issues in the platform deletion logic:

  1. The Discourse case falls through to the default case due to missing break statement
  2. No error handling for the schedule deletion operation
  3. The switch statement structure might not scale well as more platforms are added

Apply this diff to fix the immediate issues:

  switch (platform.name) {
    case PlatformNames.Discourse: {
      if (platform.metadata?.scheduleId) {
-        await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
+        try {
+          await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
+        } catch (error) {
+          throw new ApiError(
+            httpStatus.INTERNAL_SERVER_ERROR,
+            `Failed to delete Discourse schedule: ${error.message}`
+          );
+        }
      }
+      break;
    }
    default: {
+      break;
    }
  }

Consider refactoring to use a strategy pattern for platform-specific deletion logic as the number of platforms grows. This would make the code more maintainable and easier to test. Would you like me to provide an example implementation?

📝 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
switch (platform.name) {
case PlatformNames.Discourse: {
if (platform.metadata?.scheduleId) {
await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
}
}
default: {
}
}
switch (platform.name) {
case PlatformNames.Discourse: {
if (platform.metadata?.scheduleId) {
try {
await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
} catch (error) {
throw new ApiError(
httpStatus.INTERNAL_SERVER_ERROR,
`Failed to delete Discourse schedule: ${error.message}`
);
}
}
break;
}
default: {
break;
}
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 148-152: This case is falling through to the next case.

Add a break or return statement to the end of this case to prevent fallthrough.

(lint/suspicious/noFallthroughSwitchClause)

@Behzad-rabiei Behzad-rabiei merged commit c91f46c into main Dec 1, 2024
13 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.

2 participants