Code address github.com/MoceptWeb/e… Make sure you are at least familiar with the Egg document before you read it, otherwise it’s a waste of time

Egg Timed task

There are many situations where you need to execute certain scripts on a regular basis (or just once), and this is where you can take advantage of egg’s Schedule functionality

How to write

schedule

  • {app_root}/app/schedule.js
    // Use the schedule attribute to set the execution interval of scheduled tasks
  static get schedule() {
    return {
      interval: '5m'.// 5 min interval
      type: 'worker'.// Worker type: Only one worker on each machine will perform this scheduled task
    };
  }
  async subscribe() {
    this.ctx.logger.info('schedule updateOa2User begin')
    const res = await this.ctx.service.portal.oa.updateOa2User();
    this.ctx.logger.info('schedule updateOa2User finish')}Copy the code

Automatic startup determines which scheduled tasks to start

Configure immediate in get schedule() : If this parameter is set to true, the scheduled task is executed immediately after the application is started and ready

  app.beforeStart(async () => {
    // await app.runSchedule('updateOa2User'); updatePortal2User await app.runSchedule('updatePortal2User');
  });

Copy the code

service

  • {app_root}/app/service/portal/oa.js

Used to connect

// Helper. js connects to a sqlServer connection
const mssql = require('mssql')
let pool = await mssql.connect(config)

// App.js connection error log
  mssql.on('error', err => {
    console.log('database err', err)
    app.logger.error(err);
    // ... error handler
  })
Copy the code

Multiple operations in asynchrony that are all completed asynchronously

  • For example, one asynchronous operation after another on a data, but finally get all the asynchronous results

Do not do synchronous operation in asynchrony, otherwise the execution order will be unexpected!!

    async updateUser(oaUser) {
        const self = this;
        letpromiseAll = []; Oauser.foreach (oa => {promise.push (promise.resolve (self.updateUserByName(oa))); }); await Promise.all(promiseAll); }Copy the code
  • {app_root}/app/service/portal/portal.js

Multiple operations in asynchrony that are all completed asynchronously

If you need to fetch all the data step by step (synchronous in this case) before you do all the other asynchronous operations, then you need to encapsulate the synchronous operations as promises to support asynchronous operations

async readLine(target) {
      let array = [];
      const self = this;
      const file = await new Promise(function (resolve, reject) {
        lineReader.eachLine(target, function(line, last) {
            // line.split(/\s/)[0]
            let data = line.split(/\s/)
            if(data[2]) {
                array.push({
                    user_id: self.ctx.helper.trim(data[0].'"'),
                    mail: self.ctx.helper.trim(data[1].'"'),
                    user_center_id: self.ctx.helper.trim(data[2].'"'),})}if(last) {
                resolve(array)
            }
        })
      })

      return file;

  }

/ / use
const fileData = await this.readLine(target);
    let promiseAll = [];
    fileData.forEach(portal= > {
      promiseAll.push(Promise.resolve(self.updateUserByPortalId(portal)));
    });
await Promise.all(promiseAll);
Copy the code

mysql

  • SQL placeholders
 const res = await conn.query('update t_user set mail = ? where user_id = ? ', [oaUser.email, user.user_id]);
Copy the code
  • The SQL transaction
    async sqlBeginTransaction() {
        const conn = await this.app.mysql.beginTransaction();

        try {
            const res = await conn.query('update t_user set mail = ? where user_id = ? ', [oaUser.email, user.user_id]);
            if(res && res.affectedRows === 1) {
               await conn.commit();
            } else if(res.affectedRows > 1){
                // this.ctx.logger.error(' ')
               await conn.rollback()                
            } else {
                await conn.rollback()                
            }
        } catch (err) {
        // error, rollback
          await conn.rollback(); // rollback call won't throw err throw err; }}Copy the code

extend

  • {app_root}/app/extend/helper.js

Unified encapsulation of various data connection and error information

test

  • {app_root} / app/test/service/portal/portal. Test. Js to be perfect

Unit Test Instructions

config

Keep in mind that the configuration for more environments is different

Unit tests use config.unittest.js

Why do I write that

TODO analysis source code

Expand and optimize

  • Encapsulate the pure database in the Service to the Model

  • The optimization of task message queue based on RedIS does not need to start the task manually

  • Write egg-mssql to connect to sqlserver