From 0aeba83a66df537091cc5446e8c6fd785554ce03 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Tue, 2 Jul 2024 12:41:15 +0300 Subject: [PATCH] docs: update scheduled jobs docs (#7905) - Update scheduled jobs docs to support updated definition + remove coming soon notice - Update scheduled jobs everywhere else they're used. --- .../scheduled-jobs/execution-number/page.mdx | 40 +++++++++++++ .../book/app/basics/scheduled-jobs/page.mdx | 60 +++++-------------- www/apps/book/app/basics/workflows/page.mdx | 17 +++--- www/apps/book/sidebar.mjs | 9 +++ .../pricing/examples/page.mdx | 4 +- .../app/recipes/commerce-automation/page.mdx | 47 ++++++++++----- .../app/recipes/subscriptions/page.mdx | 1 - 7 files changed, 104 insertions(+), 74 deletions(-) create mode 100644 www/apps/book/app/advanced-development/scheduled-jobs/execution-number/page.mdx diff --git a/www/apps/book/app/advanced-development/scheduled-jobs/execution-number/page.mdx b/www/apps/book/app/advanced-development/scheduled-jobs/execution-number/page.mdx new file mode 100644 index 0000000000..dbcca6f573 --- /dev/null +++ b/www/apps/book/app/advanced-development/scheduled-jobs/execution-number/page.mdx @@ -0,0 +1,40 @@ +export const metadata = { + title: `${pageNumber} Scheduled Jobs Number of Executions`, +} + +# {metadata.title} + +In this chapter, you'll learn how to set a limit on the number of times a scheduled job is executed. + +## numberOfExecutions Option + +The export configuration object of the scheduled job accepts an optional property `numberOfExecutions`. Its value is a number indicating how many times the scheduled job can be executed during the Medusa application's runtime. + +For example: + +export const highlights = [ + ["9", "numberOfExecutions", "The number of times the job should be executed."] +] + +```ts highlights={highlights} +export default async function myCustomJob() { + console.log("I'll be executed three times only.") +} + +export const config = { + name: "hello-world", + // execute every minute + schedule: "* * * * *", + numberOfExecutions: 3, +} +``` + +The above scheduled job has the `numberOfExecutions` configuration set to `3`. + +So, it'll only execute 3 times, each every minute, then it won't be executed anymore. + + + +If you restart the Medusa application, the scheduled job will be executed again until reaching the number of executions specified. + + diff --git a/www/apps/book/app/basics/scheduled-jobs/page.mdx b/www/apps/book/app/basics/scheduled-jobs/page.mdx index 2d4cc81602..b1e492a3cf 100644 --- a/www/apps/book/app/basics/scheduled-jobs/page.mdx +++ b/www/apps/book/app/basics/scheduled-jobs/page.mdx @@ -6,12 +6,6 @@ export const metadata = { In this chapter, you’ll learn about scheduled jobs and how to use them. - - -Scheduled jobs are coming soon. - - - ## What is a Scheduled Job? A scheduled job is a function executed at a specified interval of time in the background of your Medusa application. It’s like a cron job that runs during the application's runtime. @@ -22,30 +16,23 @@ For example, you can synchronize your inventory with an Enterprise Resource Plan ## How to Create a Scheduled Job? - - -- [Redis](https://redis.io/) is installed and Redis server is running. - - - A scheduled job is created in a TypeScript or JavaScript file under the `src/jobs` directory. For example, create the file `src/jobs/hello-world.ts` with the following content: ```ts title="src/jobs/hello-world.ts" -import { ScheduledJobConfig } from "@medusajs/medusa" - // the scheduled-job function export default function () { console.log("Time to say hello world!") } // the job's configurations -export const config: ScheduledJobConfig = { +export const config = { name: "hello-world", // execute every minute schedule: "* * * * *", } + ``` A scheduled job file must export: @@ -59,20 +46,7 @@ This scheduled job executes every minute and logs into the terminal `Time to say ### Test Scheduled Jobs -To test out your scheduled job: - -1. Uncomment the following line in the `medusa-config.js` file: - -```js title="medusa-config.js" -module.exports = defineConfig({ - projectConfig: { - redisUrl: REDIS_URL, - // ... - }, -}) -``` - -2. Start the Medusa application: +To test out your scheduled job, start the Medusa application: ```bash npm2yarn npm run dev @@ -81,12 +55,9 @@ npm run dev After a minute, the following message will be logged to the terminal: ```bash -info: Processing scheduled job: hello-world Time to say hello world! ``` -The first line indicates that the application is executing the scheduled job. The second line is the text logged by the scheduled job. - --- ## When to Use Scheduled Jobs @@ -115,32 +86,31 @@ The scheduled job function receives an object parameter that has a `container` p For example: export const highlights = [ - ["12", "resolve", "Resolve the Product Module's main service."], - ["12", "ModuleRegistrationName.PRODUCT", "The resource registration name imported from `@medusajs/modules-sdk`."] + ["11", "resolve", "Resolve the Product Module's main service."], + ["11", "ModuleRegistrationName.PRODUCT", "The resource registration name imported from `@medusajs/modules-sdk`."] ] ```ts title="src/jobs/hello-world.ts" highlights={highlights} import { - ScheduledJobArgs, - ScheduledJobConfig, -} from "@medusajs/medusa" -import { IProductModuleService } from "@medusajs/types" -import { ModuleRegistrationName } from "@medusajs/modules-sdk" + IProductModuleService, + MedusaContainer, +} from "@medusajs/types" +import { ModuleRegistrationName } from "@medusajs/utils" -export default async function ({ - container, -}: ScheduledJobArgs) { - const productModuleService: IProductModuleService = +export default async function myCustomJob( + container: MedusaContainer +) { + const productModuleService: IProductModuleService = container.resolve(ModuleRegistrationName.PRODUCT) - const [, count] = await productModuleService.listAndCount() + const [, count] = await productModuleService.listAndCountProducts() console.log( `Time to check products! You have ${count} product(s)` ) } -export const config: ScheduledJobConfig = { +export const config = { name: "hello-world", // execute every minute schedule: "* * * * *", diff --git a/www/apps/book/app/basics/workflows/page.mdx b/www/apps/book/app/basics/workflows/page.mdx index c9844f9efa..28080c26bb 100644 --- a/www/apps/book/app/basics/workflows/page.mdx +++ b/www/apps/book/app/basics/workflows/page.mdx @@ -156,16 +156,13 @@ To execute the workflow, invoke it passing the Medusa container as a parameter. - ```ts title="src/jobs/message-daily.ts" highlights={[["10"], ["11"], ["12"], ["13"], ["14"], ["15"]]} - import { - type ScheduledJobConfig, - type ScheduledJobArgs, - } from "@medusajs/medusa" + ```ts title="src/jobs/message-daily.ts" highlights={[["7"], ["8"], ["9"], ["10"], ["11"], ["12"]]} + import { MedusaContainer } from "@medusajs/types" import myWorkflow from "../workflows/hello-world" - export default async function handler({ - container, - }: ScheduledJobArgs) { + export default async function myCustomJob( + container: MedusaContainer + ) { const { result } = await myWorkflow(container) .run({ input: { @@ -176,10 +173,10 @@ To execute the workflow, invoke it passing the Medusa container as a parameter. console.log(result.message) } - export const config: ScheduledJobConfig = { + export const config = { name: "run-once-a-day", schedule: `0 0 * * *`, - } + }; ``` diff --git a/www/apps/book/sidebar.mjs b/www/apps/book/sidebar.mjs index 947f758e18..3c2220c64b 100644 --- a/www/apps/book/sidebar.mjs +++ b/www/apps/book/sidebar.mjs @@ -179,6 +179,15 @@ export const sidebar = sidebarAttachHrefCommonOptions( }, ], }, + { + title: "Scheduled Jobs", + children: [ + { + path: "/advanced-development/scheduled-jobs/execution-number", + title: "Execution Number", + }, + ], + }, { title: "Workflows", children: [ diff --git a/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx b/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx index f12ee76334..f6d6787460 100644 --- a/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx +++ b/www/apps/resources/app/commerce-modules/pricing/examples/page.mdx @@ -163,7 +163,7 @@ In this document, you’ll find common examples of how you can use the Pricing M } from "@medusajs/pricing" export async function GET( - request: Request, + request: Request ) { const pricingModuleService = await initializePricingModule() @@ -381,7 +381,7 @@ In this document, you’ll find common examples of how you can use the Pricing M } from "@medusajs/pricing" export async function GET( - request: Request, + request: Request ) { const pricingModuleService = await initializePricingModule() diff --git a/www/apps/resources/app/recipes/commerce-automation/page.mdx b/www/apps/resources/app/recipes/commerce-automation/page.mdx index 219fec1b14..0d0c862bc2 100644 --- a/www/apps/resources/app/recipes/commerce-automation/page.mdx +++ b/www/apps/resources/app/recipes/commerce-automation/page.mdx @@ -436,19 +436,13 @@ Medusa also provides Notification Module Providers that integrate with third-par As your commerce store grows, you'll likely need to synchronize data across different systems. For example, you need to synchronize data with an ERP system or a data warehouse. -You can do that by: +To implement that: -- Creating a workflow that implements the synchronization steps, along with retry and rollback logic. -- Creating a scheduled job that executes the workflow automatically at the specified time pattern. - - - -Scheduled jobs are coming soon. - - +- Create a workflow that implements the synchronization steps, along with retry and rollback logic. +- Create a scheduled job that executes the workflow automatically at the specified time pattern. } @@ -633,6 +627,33 @@ export const syncProductsWorkflowHighlight = [ 3. Sync the retrieved products with a third-party service. It's assumed that the connection to the third-party service is implemented within a custom module's main service. 4. Update the last sync date of the store to the current date. + Then, create a scheduled job at `src/jobs/sync-products.ts` that executes the workflow at the specified interval: + + ```ts + import { MedusaContainer } from "@medusajs/types" + import { + syncProductsWorkflow, + } from "../workflows/sync-products" + + export default async function syncProductsJob( + container: MedusaContainer + ) { + await syncProductsWorkflow(container) + .run({ + input: { + name: "John", + }, + }) + } + + export const config = { + name: "sync-products", + // execute every minute + schedule: "0 0 * * *", + numberOfExecutions: 3, + } + ``` + --- @@ -842,12 +863,6 @@ To do that, create a subscriber that listens to the `product.created`, and send You can also create a scheduled job that checks whether the number of new products has exceeded a set threshold, then sends out the newsletter. - - -Scheduled jobs are coming soon. - - - - The `order.placed` event isn't emitted yet. -- Scheduled jobs are coming soon.