Questions and discussions about using the Shopify CLI and Shopify-built libraries.
Hello Folks,
I have query , I am making an App in remix and Graphql .Can anyone tell how we can implement Cron Job in Remix (react library )and Graphql in shopify app
Hi Mohit12,
You can implement a Cron Job in your app, but it's not something that is directly related to Remix or GraphQL. It more so depends on the environment where your app is running. However, if you're looking to schedule some tasks, you could do it server-side, where your app is running. Here's a general way of how you can set up a cron job in Node.js environment:
Install the node-cron package: npm install --save node-cron
Import and use it in your Node.js script:
const cron = require('node-cron');
cron.schedule('* * * * *', () => {
console.log('Running a task every minute');
});
In the context of Shopify, you might want to run a task that fetches or updates some data via the Shopify API. In this case, you can use GraphQL queries/mutations within these tasks.
For example:
const cron = require('node-cron');
const { request } = require('graphql-request')
cron.schedule('* * * * *', () => {
const query = `{
shop {
name
primaryDomain {
url
host
}
}
}`
request('https://your-shopify-store.myshopify.com/api/graphql', query)
.then(data => console.log(data))
.catch(err => console.log(err))
});
This will fetch the name and primary domain of your shop every minute. Please note that this is a simplified example. In a real-world scenario, you'd need to handle API authentication and error handling as well.
Hope this helps,
Liam | Developer Advocate @ Shopify
- Was my reply helpful? Click Like to let me know!
- Was your question answered? Mark it as an Accepted Solution
- To learn more visit Shopify.dev or the Shopify Web Design and Development Blog
Hi @Liam
Thanks for this information.
In relation to Remix, where would we add the:
const cron = require('node-cron');
Would this go in the Shopify.server.js or entry.server.jsx or perhaps it could be used in the loader method of a route?
Or would I set up a separate mini application with a server.js file, that would make an api call, inside the cron.schedule(), to one of my remix application’s routes, where I have some business logic that I wish to schedule.
I must say I would prefer to keep everything inside my Remix app.
I cannot see any reason, why I can’t import the node-cron library to a route and use it inside the loader or action method. Both of these are server side methods.
Plus when node-cron is imported, does this require cron to be available on the host? Or does NodeJs just emulate what cron does? I mean a NodeJs server is running 24/7, so it should have some sort of scheduling capability?
Hey @Charles_Roberts, did you figure out where to place the cronjob? I am not sure either. Thanks!
Here is an excerpt from:
app/routes/app.cron.($id).jsx
let job = {}; export async function loader({ request, params }) { const { admin, session } = await authenticate.admin(request); const { shop } = session; if('id' in params){ const action = params.id; createCron(action, shop, process); } return json({ ownerKey: '', action: '', error: '' }); } export async function action({ request, params }) { const { admin, session } = await authenticate.admin(request); const { shop } = session; const formData$ = await request.formData(); const formData = Object.fromEntries(formData$); /** @type {any} */ const data = { ...formData }; const errors = validateCronForm(data); if (errors) { return json({ errors }, { status: 422 }); } const action = formData.action; let cronResponse = {}; let error = ''; if(formData.ownerKey === process.env.OWNER_KEY){ cronResponse = createCron(action, shop, process); if('error' in cronResponse){ // @ts-ignore error = 'Task threw an error'; } } else{ error = 'Owner key did not match'; } return json({ responseData: { ownerKey: formData.ownerKey, action: formData.action === 'start' ? 'started' : 'stopped', error }, errors }); } function createCron(action, shop, process){ const cron = require('node-cron'); const cronTime = process.env.ENVIRONMENT === 'prod' ? '30 1 * * * ' : '30 * * * * * '; let error = false; const tasks = cron.getTasks(); let deferReadOrdersTaskExists = false; for (let [key, value] of tasks.entries()) { if(value.options.name === 'deferReadOrders-task'){ deferReadOrdersTaskExists = true; break; } } if(!deferReadOrdersTaskExists){ job = cron.schedule(cronTime, async function execute() { const date = new Date().toLocaleString(); const days = [14,7,3]; const res = deferReadOrders(days, shop, process); },{ name: 'deferReadOrders-task', scheduled: false }); } try{ action == 'stop' ? job.stop() : job.start(); } catch(error){ job.stop(); error = true; } return json({ cronTime, action, error }); }