* initialized next.js project * finished markdown sections * added operation schema component * change page metadata * eslint fixes * fixes related to deployment * added response schema * resolve max stack issue * support for different property types * added support for property types * added loading for components * added more loading * type fixes * added oneOf type * removed console * fix replace with push * refactored everything * use static content for description * fixes and improvements * added code examples section * fix path name * optimizations * fixed tag navigation * add support for admin and store references * general enhancements * optimizations and fixes * fixes and enhancements * added search bar * loading enhancements * added loading * added code blocks * added margin top * add empty response text * fixed oneOf parameters * added path and query parameters * general fixes * added base path env variable * small fix for arrays * enhancements * design enhancements * general enhancements * fix isRequired * added enum values * enhancements * general fixes * general fixes * changed oas generation script * additions to the introduction section * added copy button for code + other enhancements * fix response code block * fix metadata * formatted store introduction * move sidebar logic to Tags component * added test env variables * fix code block bug * added loading animation * added expand param + loading * enhance operation loading * made responsive + improvements * added loading provider * fixed loading * adjustments for small devices * added sidebar label for endpoints * added feedback component * fixed analytics * general fixes * listen to scroll for other headings * added sample env file * update api ref files + support new fields * fix for external docs link * added new sections * fix last item in sidebar not showing * move docs content to www/docs * change redirect url * revert change * resolve build errors * configure rewrites * changed to environment variable url * revert changing environment variable name * add environment variable for API path * fix links * fix tailwind settings * remove vercel file * reconfigured api route * move api page under api * fix page metadata * fix external link in navigation bar * update api spec * updated api specs * fixed google lint error * add max-height on request samples * add padding before loading * fix for one of name * fix undefined types * general fixes * remove response schema example * redesigned navigation bar * redesigned sidebar * fixed up paddings * added feedback component + report issue * fixed up typography, padding, and general styling * redesigned code blocks * optimization * added error timeout * fixes * added indexing with algolia + fixes * fix errors with algolia script * redesign operation sections * fix heading scroll * design fixes * fix padding * fix padding + scroll issues * fix scroll issues * improve scroll performance * fixes for safari * optimization and fixes * fixes to docs + details animation * padding fixes for code block * added tab animation * fixed incorrect link * added selection styling * fix lint errors * redesigned details component * added detailed feedback form * api reference fixes * fix tabs * upgrade + fixes * updated documentation links * optimizations to sidebar items * fix spacing in sidebar item * optimizations and fixes * fix endpoint path styling * remove margin * final fixes * change margin on small devices * generated OAS * fixes for mobile * added feedback modal * optimize dark mode button * fixed color mode useeffect * minimize dom size * use new style system * radius and spacing design system * design fixes * fix eslint errors * added meta files * change cron schedule * fix docusaurus configurations * added operating system to feedback data * change content directory name * fixes to contribution guidelines * revert renaming content * added api-reference to documentation workflow * fixes for search * added dark mode + fixes * oas fixes * handle bugs * added code examples for clients * changed tooltip text * change authentication to card * change page title based on selected section * redesigned mobile navbar * fix icon colors * fix key colors * fix medusa-js installation command * change external regex in algolia * change changeset * fix padding on mobile * fix hydration error * update depedencies
6.1 KiB
description, addHowToData
| description | addHowToData |
|---|---|
| Learn how to create a scheduled job in Medusa. The scheduled job in this example will simply change the status of draft products to published. | true |
How to Create a Scheduled Job
In this document, you’ll learn how to create a scheduled job in Medusa.
Overview
Medusa allows you to create scheduled jobs that run at specific times during your backend's lifetime. For example, you can synchronize your inventory with an Enterprise Resource Planning (ERP) system once a day.
This guide explains how to create a scheduled job on your Medusa backend. The scheduled job in this example will simply change the status of draft products to published.
Prerequisites
Medusa Components
It is assumed that you already have a Medusa backend installed and set up. If not, you can follow the quickstart guide to get started. The Medusa backend must also have an event bus module installed, which is available when using the default Medusa backend starter.
1. Create a File
Each scheduled job should reside in a loader, which is a TypeScript or JavaScript file located under the src/loaders directory.
Start by creating the src/loaders directory. Then, inside that directory, create the JavaScript or TypeScript file that you’ll add the scheduled job in. You can use any name for the file.
For the example in this tutorial, you can create the file src/loaders/publish.ts.
2. Create Scheduled Job
To create a scheduled job, add the following code in the file you created, which is src/loaders/publish.ts in this example:
import { AwilixContainer } from "awilix"
const publishJob = async (
container: AwilixContainer,
options: Record<string, any>
) => {
const jobSchedulerService =
container.resolve("jobSchedulerService")
jobSchedulerService.create(
"publish-products",
{},
"0 0 * * *",
async () => {
// job to execute
const productService = container.resolve("productService")
const draftProducts = await productService.list({
status: "draft",
})
for (const product of draftProducts) {
await productService.update(product.id, {
status: "published",
})
}
}
)
}
export default publishJob
:::info
The service taking care of background jobs was renamed in v1.7.1. If you are running a previous version, use eventBusService instead of jobSchedulerService.
:::
This file should export a function that accepts a container and options parameters. container is the dependency container that you can use to resolve services, such as the JobSchedulerService. options are the plugin’s options if this scheduled job is created in a plugin.
You then resolve the JobSchedulerService and use the jobSchedulerService.create method to create the scheduled job. This method accepts four parameters:
- The first parameter is a unique name to give to the scheduled job. In the example above, you use the name
publish-products. - The second parameter is an object which can be used to pass data to the job.
- The third parameter is the scheduled job expression pattern. In this example, it will execute the scheduled job once a day at 12 AM.
- The fourth parameter is the function to execute. This is where you add the code to execute once the scheduled job runs. In this example, you retrieve the draft products using the ProductService and update the status of each of these products to
published.
:::tip
You can see examples of scheduled job expression patterns on crontab guru.
:::
Scheduled Job Name
As mentioned earlier, the first parameter of the create method is the name of the scheduled job. By default, if another scheduled job has the same name, your custom scheduled job will replace it.
If you want to ensure both scheduled jobs are registered and used, you can pass as a fifth parameter an options object with a keepExisting property set to true. For example:
jobSchedulerService.create(
"publish-products",
{},
"0 0 * * *",
async () => {
// ...
},
{
keepExisting: true,
}
)
Pass Data to the Scheduled Job
To pass data to your scheduled job, you can add them to the object passed as a second parameter under the data property. This is helpful if you use one function to handle multiple scheduled jobs.
For example:
jobSchedulerService.create("publish-products", {
data: {
productId,
},
}, "0 0 * * *", async (job) => {
console.log(job.data) // {productId: 'prod_124...'}
// ...
})
3. Run Medusa Backend
:::info
Scheduled Jobs only run while the Medusa backend is running.
:::
Before you run the Medusa backend, make sure to build your code that's under the src directory into the dist directory with the following command:
npm run build
Then, run the following command to start your Medusa backend:
npx medusa develop
If the scheduled job was registered successfully, you should see a message similar to this logged on your Medusa backend:
Registering publish-products
Where publish-products is the unique name you provided to the scheduled job.
Once it is time to run your scheduled job based on the scheduled job expression pattern, the scheduled job will run and you can see it logged on your Medusa backend.
For example, the above scheduled job will run at 12 AM and, when it runs, you can see the following logged on your Medusa backend:
info: Processing scheduled job: publish-products
If you log anything in the scheduled job, for example using console.log, or if any errors are thrown, it’ll also be logged on your Medusa backend.
:::tip
To test the previous example out instantly, you can change the scheduled job expression pattern passed as the third parameter to jobSchedulerService.create to * * * * *. This will run the scheduled job every minute.
:::