Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cronjob stopping execution nodejs

Hello everyone I have a bug that is really stressing me out lol. So basically I have a nodejs application that makes a request to a ecommerce website to retrieve orders, our flow is basically like this: We make a GET request to this website and we retrieve the orders that are waiting_acceptance and we "accept" them so then we can read the shipping address, after that we parse the order, its products and the shipping address so that our system can register it. All this is done every 5 minutes right now, it was at every 10 minutes be we reduced it reduce the number of orders getting lost :(, so anyways this is done through a cron job that we schedule on NodeJS. This is the cron: */5 * * * *

This application is written in NodeJs LTS and run inside a ubuntu docker container.

Here is the code to schedule the cron:

    export function createOrderCrons(): void
{
        cron.schedule(
                process.env.ORDER_REGISTER_TIMELAPSE,
                async () =>
                {
                        await consumeRegisterOrders();
                        cronLogger.info('Runing get orders task');
                },
                cronOptions
        );
        cron.schedule(..........);//redacted
}

Here is the function that the cron calls:

export async function consumeRegisterOrders(): Promise<void>
{
        try
        {
                await Axios.post(`${process.env.HOST}/orders/`);
                cronLogger.info(`${process.env.HOST}/orders/`);
        }
        catch (error)
        {
                if (!HTTP.TOO_MANY_REQUESTS)
                {
                        errorLogger.info('Consume Register Orders endpoint error:', error);
                }
        }
}

Here is the code to read the orders:

export async function getOrders(auth: any): Promise<any[]>
   {
       try
       {
           const orders: IOrder[] = [];
           const ordersToGet: string[] = [];

           const res = await miraklApi.get(
               '/orders?order_state_codes=WAITING_ACCEPTANCE&paginate=false',
               {
                   headers: auth.headers
               }
           );
           errorLogger.info(`orders retrieved from waiting_acceptance ${res.data.orders.length}`);

           for(let i = 0; i < res.data.orders.length; i++)
           {
               const order = res.data.orders[i];
               order.warehouseSialId = auth.warehouseSialId;

               await validateOrder(order, true, auth);
               await ordersToGet.push(order.order_id);
           }
           errorLogger.info(`orders to get with folios ${ordersToGet.length}`);

           if(ordersToGet.length > 0)
           {
               const response = await miraklApi.get(
                   `/orders?order_ids=${ordersToGet.join(',')}&paginate=false`,
                   {
                       headers: auth.headers
                   }
               );

               errorLogger.info(`orders retrieved with address ${response.data.orders.length}`);

               await orders.push(...response.data.orders);
           }
           errorLogger.info(`orders to return ${orders.length}`);
           return await orders;
       }
       catch (error)
       {
           errorLogger.info(`error inside of get orders function ${error}`);
           return [];
       }
   }

Here is the code that is at the endpoint level:

ordersRouter.post(
  '/',
  async(ctx: Context): Promise < void > => {
    try {
      const auth = {
        headers: {
          // eslint-disable-next-line @typescript-eslint/naming-convention
          Authorization: `${
                                                process.env.MIRAKL_API_TOKEN
                                        }`
        },
        warehouseSialId: process.env.WAREHOUSE_ID
      };

      const orders = await getOrders(auth);

      for (let i = 0; i < orders.length; i++) {
        const order = orders[i];
        let task: ITask = null;

        try {

          order.warehouseSialId = auth.warehouseSialId;
          const products: IProduct[] = await mapToMindiProducts(order.order_lines);
          const mappedOrder = await mapToMindiOrder(order, products);
          await registerOrder(mappedOrder);

          if (onfleetIsEnabled) {
            task = await getOnfleetTaskById(order.shipping.externalId);
          }

        } catch (error) {
          errorLogger.info(`error inside of one cycle to register an order ${JSON.stringify(error)}`);
          continue;
        }

        errorLogger.info(`before change status to shipped ${order.order_id}`);
        await sendTaskToMirakl(task, order, auth);
      }
    } catch (e) {
      errorLogger.info(`error at endpoint /orders ${JSON.stringify(e)}`);
    }

    ctx.status = HTTP.OK;
  }
);

Here is a glance at what happens as you can see I accept two orders in the first iteration and then another in the second iteration it only accepts the order and it never reaches outside of this getOrders function and there is no error in the logs either :( There seems to be no sure pattern here, when we had the cron configured at 10 minutes I noticed a pattern where everyother time the cron ran the orders didn't make it out of the getOrders function and would never register.

enter image description here

like image 588
Carlos Franco Avatar asked Nov 07 '22 04:11

Carlos Franco


1 Answers

You should put try catch to wrap up function consumeRegisterOrders since it may throw error and your schedule job will be terminated.

export function createOrderCrons(): void {
    cron.schedule(process.env.ORDER_REGISTER_TIMELAPSE, async () => {
        try {
            await consumeRegisterOrders();
            cronLogger.info('Runing get orders task');
        } catch (err) {
            console.error(err);
        }
    }, cronOptions);
}
like image 148
Nghia Pham Tuan Avatar answered Nov 12 '22 11:11

Nghia Pham Tuan