Cronjob 停止执行 nodejs

Car*_*nco 5 javascript linux cron node.js docker

大家好,我有一个让我感到压力很大的错误,哈哈。所以基本上我有一个 nodejs 应用程序,它向电子商务网站发出请求以检索订单,我们的流程基本上是这样的:我们向该网站发出 GET 请求,我们检索正在等待的订单,然后我们“接受”它们我们可以读取送货地址,然后我们解析订单、其产品和送货地址,以便我们的系统可以注册它。所有这些现在每 5 分钟完成一次,每 10 分钟一次,因为我们减少了它减少丢失订单的数量:(,所以无论如何这是通过我们在 NodeJS 上安排的 cron 作业完成的。这是 cron:*/5 * * * *

这个应用程序是用 NodeJs LTS 编写的,并在 ubuntu docker 容器中运行。

这是调度 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
}
Run Code Online (Sandbox Code Playgroud)

这是 cron 调用的函数:

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);
                }
        }
}
Run Code Online (Sandbox Code Playgroud)

这是读取订单的代码:

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 [];
       }
   }
Run Code Online (Sandbox Code Playgroud)

这是端点级别的代码:

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;
  }
);
Run Code Online (Sandbox Code Playgroud)

下面是发生的情况,您可以看到我在第一次迭代中接受了两个订单,然后在第二次迭代中接受了另一个订单,它只接受订单并且它永远不会超出此 getOrders 函数,并且日志中也没有错误: (这里似乎没有确定的模式,当我们在 10 分钟时配置 cron 时,我注意到一个模式,每次 cron 运行时,订单都没有从 getOrders 函数中退出,并且永远不会注册。

在此处输入图片说明

小智 1

您应该将 try catch 放在包装函数中,consumeRegisterOrders因为它可能会抛出错误并且您的计划作业将被终止。

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);
}
Run Code Online (Sandbox Code Playgroud)