Master Distributed Task Scheduling with MidwayJS Task Component

This guide explains how to install, configure, and use the @midwayjs/task module for distributed and delayed task scheduling in Midway, covering Redis setup, code examples for cron jobs, local tasks, manual triggers, progress tracking, logging, and troubleshooting.

Node Underground
Node Underground
Node Underground
Master Distributed Task Scheduling with MidwayJS Task Component

Installation

First install the Midway task component: $ npm install @midwayjs/task -S Then import it in configuration.ts:

// src/configuration.ts
import { Configuration } from '@midwayjs/decorator';
import * as task from '@midwayjs/task';
import { join } from 'path';

@Configuration({
  imports: [task],
  importConfigs: [join(__dirname, 'config')]
})
export class AutoConfiguration {}

Configuration

Add the task settings in config.default.ts:

export const taskConfig = {
  redis: `redis://127.0.0.1:32768`, // task depends on Redis
  prefix: 'midway-task', // keys are prefixed to avoid conflicts
  defaultJobOptions: {
    repeat: {
      tz: "Asia/Shanghai"
    }
  }
};

Business Code Examples

Distributed Cron Task

import { Provide, Inject, Task } from '@midwayjs/decorator';

@Provide()
export class UserService {
  @Inject()
  helloService: HelloService;

  // Executes every minute as a distributed task
  @Task({ repeat: { cron: '* * * * *' } })
  async test() {
    console.log(this.helloService.getName());
  }
}

Local Cron Task

import { Provide, Inject, TaskLocal } from '@midwayjs/decorator';

@Provide()
export class UserService {
  @Inject()
  helloService: HelloService;

  // Executes every second locally
  @TaskLocal('* * * * * *')
  async test() {
    console.log(this.helloService.getName());
  }
}

Manual Triggered Task

Define a task class with an async execute method:

import { Provide, Inject, Queue } from '@midwayjs/decorator';

@Queue()
@Provide()
export class HelloTask {
  @Inject()
  service;

  async execute(params) {
    console.log(params);
  }
}

Trigger it with a delay:

import { QueueService } from '@midwayjs/task';
import { Provide, Inject } from '@midwayjs/decorator';

@Provide()
export class UserTask {
  @Inject()
  service;
  @Inject()
  queueService: QueueService;

  async execute(params) {
    // Trigger after 3 seconds
    const xxx = await this.queueService.execute(HelloTask, params, { delay: 3000 });
  }
}

Progress Reporting

During long‑running jobs (e.g., video processing) you can update progress via job.progress and later query it:

import { QueueService } from '@midwayjs/task';
import { Provide, Controller, Get, Query } from '@midwayjs/decorator';

@Provide()
@Controller()
export class HelloController {
  @Inject()
  queueService: QueueService;

  @Get('/get-queue')
  async getQueue(@Query() id: string) {
    return await this.queueService.getClassQueue(TestJob).getJob(id);
  }
}

Logging and Operations

Midway Task creates two log files:

midway-task.log

midway-task-error.log

Logs are emitted at the start and end of each task, local task, or queue process, and on errors:

logger.info(`task start.`);
// on error
logger.error(`${e.stack}`);
logger.info(`task end.`);

Local tasks use similar messages ( local task start., local task end.), and queue processes use queue process start. / queue process end..

For troubleshooting, each log entry includes a traceId (job ID for tasks/queues, generated UUID for local tasks). Searching the same traceId across logs lets you correlate related events.

Internal Service Code

You can inject the logger or the request context to log inside services:

import { App, Inject, Provide, Queue } from "@midwayjs/decorator";
import { Application } from "@midwayjs/koa";

@Queue()
@Provide()
export class QueueTask {
  @App()
  app: Application;

  @Inject()
  logger;

  async execute(params) {
    this.logger.info(`====>QueueTask execute`);
    this.app.getApplicationContext().registerObject(`queueConfig`, JSON.stringify(params));
  }
}

Or using the context directly:

import { App, Inject, Provide, Queue } from "@midwayjs/decorator";
import { Application } from "@midwayjs/koa";

@Queue()
@Provide()
export class QueueTask {
  @App()
  app: Application;

  @Inject()
  ctx;

  async execute(params) {
    this.ctx.logger.info(`====>QueueTask execute`);
    this.app.getApplicationContext().registerObject(`queueConfig`, JSON.stringify(params));
  }
}

Sample log output:

2021-07-30 13:00:13,101 INFO 5577 [Queue][12][QueueTask] queue process start.
2021-07-30 13:00:13,102 INFO 5577 [Queue][12][QueueTask] ====>QueueTask execute
2021-07-30 13:00:13,102 INFO 5577 [Queue][12][QueueTask] queue process end.

Additional Notes

The cron expression format used by the task component follows the standard * * * * * * pattern (second optional, then minute, hour, day of month, month, day of week).

For more Midway features, refer to the official documentation:

https://www.midwayjs.org/doc

backendRedistask schedulingNode.jsBullMidwayJS
Node Underground
Written by

Node Underground

No language is immortal—Node.js isn’t either—but thoughtful reflection is priceless. This underground community for Node.js enthusiasts was started by Taobao’s Front‑End Team (FED) to share our original insights and viewpoints from working with Node.js. Follow us. BTW, we’re hiring.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.