Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/services/discourse/core.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,22 @@ async function createDiscourseSchedule(platformId: string, endpoint: string): Pr
await schedule.trigger();
return schedule.scheduleId;
} catch (error) {
logger.error(error, 'Failed to create discourse schedule');
throw new ApiError(590, 'Failed to create discourse schedule');
logger.error(error, 'Failed to create discourse schedule.');
throw new ApiError(590, 'Failed to create discourse schedule.');
}
}

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.');
Comment on lines +33 to +38

Copy link
Copy Markdown

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.');
}
}

}
}

export default {
getPropertyHandler,
createDiscourseSchedule,
deleteDiscourseSchedule,
};
11 changes: 10 additions & 1 deletion src/services/platform.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,15 @@ const updatePlatform = async (
* @returns {Promise<HydratedDocument<IPlatform>>}
*/
const deletePlatform = async (platform: HydratedDocument<IPlatform>): Promise<HydratedDocument<IPlatform>> => {
switch (platform.name) {
case PlatformNames.Discourse: {
if (platform.metadata?.scheduleId) {
await discourseService.coreService.deleteDiscourseSchedule(platform.metadata.scheduleId);
}
}
default: {
}
}
Comment on lines +147 to +155

Copy link
Copy Markdown

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)

return await platform.remove();
};

Expand All @@ -157,7 +166,7 @@ const deletePlatformByFilter = async (filter: object): Promise<HydratedDocument<
if (!platform) {
throw new ApiError(httpStatus.NOT_FOUND, 'Platform not found');
}
return await platform.remove();
return await deletePlatform(platform);
};

function getMetadataKey(platformName: string): string {
Expand Down
12 changes: 12 additions & 0 deletions src/services/temporal/discourse.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ class TemporalDiscourseService extends TemporalCoreService {
throw new Error(`Failed to create Temporal schedule: ${(error as Error).message}`);
}
}

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

Copy link
Copy Markdown

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}`);
}
}


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

Copy link
Copy Markdown

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);
}
}

}

export default new TemporalDiscourseService();