-
Notifications
You must be signed in to change notification settings - Fork 4
feat: exec mediawiki workflow on module changes #479
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4,7 +4,7 @@ import { IModule, IModuleUpdateBody, Module, PlatformNames, ModuleNames } from ' | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import platformService from './platform.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import websiteService from './website'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import temporalMediaWiki from './temporal/mediaWiki.service'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Create a module | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {IModule} ModuleBody | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -94,6 +94,9 @@ const updateModule = async ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // if (module.name === ModuleNames.Hivemind && newPlatform.name === PlatformNames.Website) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // await handleHivemindWebsiteCase(newPlatform); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (module.name === ModuleNames.Hivemind && newPlatform.name === PlatformNames.MediaWiki) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await handleHivemindMediaWikiCase(newPlatform); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| existingPlatform.metadata = newPlatform.metadata; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| module.options.platforms.push(newPlatform); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -132,6 +135,27 @@ const handleHivemindWebsiteCase = async (platform: any) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Handle special case for Hivemind module with MediaWiki platform | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {Object} platform - Platform object | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleHivemindMediaWikiCase = async (platform: any) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const platformDoc = await platformService.getPlatformById(platform.platform); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!platformDoc) return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isActivated = platform.metadata?.activated; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const existingWorkflowId = platformDoc.get('metadata.workflowId'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (isActivated === true) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!existingWorkflowId) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const workflowId = await temporalMediaWiki.executeWorkflow(platform.platform); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| platformDoc.set('metadata.workflowId', workflowId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await platformDoc.save(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+142
to
+157
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Handle the deactivation scenario for consistency. The const handleHivemindMediaWikiCase = async (platform: any) => {
const platformDoc = await platformService.getPlatformById(platform.platform);
if (!platformDoc) return;
const isActivated = platform.metadata?.activated;
const existingWorkflowId = platformDoc.get('metadata.workflowId');
if (isActivated === true) {
if (!existingWorkflowId) {
const workflowId = await temporalMediaWiki.executeWorkflow(platform.platform);
platformDoc.set('metadata.workflowId', workflowId);
await platformDoc.save();
}
+ } else if (isActivated === false) {
+ if (existingWorkflowId) {
+ await temporalMediaWiki.terminateWorkflow(existingWorkflowId);
+ platformDoc.set('metadata.workflowId', null);
+ await platformDoc.save();
+ }
}
};📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Delete module | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * @param {HydratedDocument<IModule>} module - module doc | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,42 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| import { Types } from 'mongoose'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { v4 as uuidv4 } from 'uuid'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import { Client } from '@temporalio/client'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| import parentLogger from '../../config/logger'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { queues } from './configs/temporal.config'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { TemporalCoreService } from './core.service'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const logger = parentLogger.child({ module: 'MediaWikiTemporalService' }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| class TemporalMediaWikiService extends TemporalCoreService { | ||||||||||||||||||||||||||||||||||||||||||||
| public async executeWorkflow(platformId: Types.ObjectId) { | ||||||||||||||||||||||||||||||||||||||||||||
| const client: Client = await this.getClient(); | ||||||||||||||||||||||||||||||||||||||||||||
| const payload = { | ||||||||||||||||||||||||||||||||||||||||||||
| platform_id: platformId, | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||
| const workflowHandle = await client.workflow.execute('MediaWikiETLWorkflow', { | ||||||||||||||||||||||||||||||||||||||||||||
| taskQueue: queues.TEMPORAL_QUEUE_PYTHON_HEAVY, | ||||||||||||||||||||||||||||||||||||||||||||
| args: [payload], | ||||||||||||||||||||||||||||||||||||||||||||
| workflowId: `mediawiki/${platformId}/${uuidv4()}`, | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
| logger.info(`Started MediaWiki workflow with ID: ${workflowHandle}`); | ||||||||||||||||||||||||||||||||||||||||||||
| return workflowHandle; | ||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||
| logger.error(`Failed to trigger MediaWiki workflow: ${(error as Error).message}`); | ||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`Failed to trigger MediaWiki workflow: ${(error as Error).message}`); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+13
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainVerify the return type and value of executeWorkflow method. The method returns 🏁 Script executed: #!/bin/bash
# Description: Check the return type of Temporal client.workflow.execute() method
# Expected: Confirm if it returns a WorkflowHandle object or a string ID
# Search for other usages of client.workflow.execute in the codebase
rg -A 10 "client\.workflow\.execute" --type tsLength of output: 2072 🌐 Web query: 💡 Result: In the Temporal TypeScript SDK, the To elaborate, when you call For example, if your workflow function returns a string, then the return type of Here is a simplified example: const result: Promise<string> = client.workflow.execute(myWorkflow, {
taskQueue: "my-task-queue",
args: ["some input"],
});If you want, I can provide more detailed code examples or official documentation references. Would you like that? Fix executeWorkflow return type misuse: In Temporal’s TypeScript SDK, You should either:
Locations to update:
Example using - const workflowHandle = await client.workflow.execute('MediaWikiETLWorkflow', { … });
- logger.info(`Started MediaWiki workflow with ID: ${workflowHandle}`);
- return workflowHandle;
+ const handle = await client.workflow.start('MediaWikiETLWorkflow', { … });
+ logger.info(`Started MediaWiki workflow with ID: ${handle.workflowId}`);
+ return handle;🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| public async terminateWorkflow(workflowId: string): Promise<void> { | ||||||||||||||||||||||||||||||||||||||||||||
| const client: Client = await this.getClient(); | ||||||||||||||||||||||||||||||||||||||||||||
| const handle = client.workflow.getHandle(workflowId); | ||||||||||||||||||||||||||||||||||||||||||||
| const description = await handle.describe(); | ||||||||||||||||||||||||||||||||||||||||||||
| if (description.status.name !== 'TERMINATED' && description.status.name !== 'COMPLETED') { | ||||||||||||||||||||||||||||||||||||||||||||
| await handle.terminate('Terminated due to schedule deletion'); | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+32
to
+39
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling for workflow handle retrieval. The public async terminateWorkflow(workflowId: string): Promise<void> {
const client: Client = await this.getClient();
- const handle = client.workflow.getHandle(workflowId);
- const description = await handle.describe();
- if (description.status.name !== 'TERMINATED' && description.status.name !== 'COMPLETED') {
- await handle.terminate('Terminated due to schedule deletion');
+ try {
+ const handle = client.workflow.getHandle(workflowId);
+ const description = await handle.describe();
+ if (description.status.name !== 'TERMINATED' && description.status.name !== 'COMPLETED') {
+ await handle.terminate('Terminated due to schedule deletion');
+ }
+ } catch (error) {
+ logger.error(`Failed to terminate workflow ${workflowId}: ${(error as Error).message}`);
+ throw new Error(`Failed to terminate workflow ${workflowId}: ${(error as Error).message}`);
}
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export default new TemporalMediaWikiService(); | ||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Verify workflow ID storage compatibility.
The
executeWorkflowmethod likely returns aWorkflowHandleobject, but this line stores it directly asworkflowId. Ensure that the stored value is the correct string identifier that can be used later for workflow termination.🏁 Script executed:
Length of output: 1778
🏁 Script executed:
Length of output: 260
🏁 Script executed:
Length of output: 1655
Ensure you store the string ID from the WorkflowHandle
The
executeWorkflowcall returns aWorkflowHandleobject, not a bare string. You need to pull out itsworkflowIdproperty before persisting it. Otherwise you’ll save the entire handle object and pass it toterminateWorkflow, which expects a string.• File: src/services/module.service.ts
• Around line 152
Suggested diff:
📝 Committable suggestion
🤖 Prompt for AI Agents