Discuss and resolve questions on Liquid, JavaScript, themes, sales channels, and site speed enhancements.
My API route which polls 3rd party APIs is failing after exactly 30seconds even though I am calling waitUntil repeatedly.
It seems the waitUntil property from the underlying worker API is not working properly.
Very frustrating because everything works locally, but the deployed environment doesn't work.
Please help and provide advice where you can.
Here is the essence of my code:
export async function action({request, params, context}: ActionFunctionArgs) {
const body = (await request.json()) as TrainingCompleteResponse;
// Moving this below the action led to some webhook handling bugs for me. Maybe moving it above so it's defined before it's used would work too? Leaving it here for now.
const handleEvent = async (
body: TrainingCompleteResponse,
context: AppLoadContext,
) => {
// lots of fetches
};
// Kick off event handler asynchronously and use waitUntil() repeatedly until
// handler finishes to prevent worker from killing the handleEvent()
// function early
const handleEventPromise = handleEvent(body, context)
.then(() => {
console.log('Trained model event handler finished successfully');
})
.catch((error) => {
console.error('Error handling trained model event: ', error.message);
});
const refreshWorkerUntilPromiseFinishes = async (
promiseToWaitFor: Promise<any>,
) => {
const pending = {
state: 'pending',
};
function getPromiseState(promise: Promise<any>) {
// We put `pending` promise after the promise to test,
// which forces .race to test `promise` first
return Promise.race([promise, pending]).then(
(value) => {
if (value === pending) {
return value;
}
return {
state: 'resolved',
value,
};
},
(reason) => ({state: 'rejected', reason}),
);
}
let promiseState = await getPromiseState(promiseToWaitFor);
while (promiseState === pending) {
// If promise we want to wait to finish isn't finished, call waitUntil again and wait 15 secs
console.log('calling waitUntil to keep event handling worker alive');
context.waitUntil(handleEventPromise);
await new Promise((r) => setTimeout(r, 15_000));
promiseState = await getPromiseState(promiseToWaitFor);
}
console.log('event handling done');
};
context.waitUntil(refreshWorkerUntilPromiseFinishes(handleEventPromise));
return json(null, 202);
}
As you can see I am calling waitUntil with a promise until the underlying promise is resolved, which should continually extend the life of my worker. However, looking at the logs for this request indicate it lives for exactly 30secs then dies.
Request id:
o2-c993991c-bd5e-43e0-adad-154e3471c468.86685b880b1a43fb
Logs (notice first log seconds time is 19, last is 49, indicating exactly 30secs elapsed):
Shopify and our financial partners regularly review and update verification requiremen...
By Jacqui Mar 14, 2025Unlock the potential of marketing on your business growth with Shopify Academy's late...
By Shopify Mar 12, 2025Learn how to increase conversion rates in every stage of the customer journey by enroll...
By Shopify Mar 5, 2025