Рубрики
Без рубрики

Как планировать функции в Node.js / Express и MongoDB

Если вы когда-либо хотели планировать задачи функций в приложении Node.js и не смогли найти прямого способа выполнения этого, то вы найдете эту статью очень полезную.

Автор оригинала: Miguel Kouam.

Если вы когда-либо хотели расписать функции в вашем приложении Node.js и не смогли найти простой способ выполнить это, то вы найдете эту статью очень полезную.

Исходный код: https://github.com/migueLedric/agenda-server-starter.

Я наткнулся Agenda.js работая над личным проектом (приложение Rideshare). Я искал обновлять статус автоматически, отправлять напоминания пассажирам за несколько часов до времени отправления, подскажите их оставлять отзыв после поездки и многое другое.

Я не хотел пользоваться заданиями CRON, но вместо этого есть все в Nodejs и иметь возможность обновлять (или удалять) эти задания, такие как обновление простого документа базы данных.

Запланированные задания сохраняются как документы в вашей коллекции «Работа». Вы можете редактировать запланированное время работы или удалить его, чтобы он вообще не работает.

У каждого документа есть Nextrunat Свойство, именно дата и время выполнятся функция задания. Вы можете выполнить любые операции Mongodb Crud в документе.

Здесь я прохожу тебя через настройку повестки дня-стартера-сервера.

Файлы:

controllers/
    rideController.js
jobs/
    - agenda.js
    jobs_list/
        - archiveRideJob.js
routes/
    - routes.js
- server.js
- package.json
- .env

Package.json.

{
  "name": "agenda-server-starter",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "agenda": "^3.0.0",
    "dotenv": "^8.2.0",
    "express": "^4.17.1",
    "express-mongo-db": "^2.0.4",
    "mongodb": "^3.5.3"
  },
  "devDependencies": {
    "nodemon": "^2.0.2"
  }
}

Поскольку это не учебное пособие по поводу создания сервера Express.js, я собираюсь прыгнуть прямо в то, как настроить agenda.js, чтобы расписание рабочих мест/функций.

Для начала необходимо создать файл конфигурации повестки дня, который подключается к вашей базе данных и выполняет определенные задания.

Работа/agenda.js.

let Agenda = require("agenda");

// set the collection where the jobs will be save
// the collection can be name anything
let url = process.env.DB_URL  // DB_URL="mongodb://127.0.0.1:27017/test-db"
let agenda = new Agenda({ db: {address: process.env.DB_URL, collection: 'jobs'}}); 
 
// list the different jobs availale throughout your app
let jobTypes = ["archiveRideJob"];

// loop through the job_list folder and pass in the agenda instance to
// each job so that it has access to its API.
jobTypes.forEach( type => {
    // the type name should match the file name in the jobs_list folder
    require('./jobs_list/'+ type)(agenda);
})

if(jobTypes.length) {
    // if there are jobs in the jobsTypes array set up 
    agenda.on('ready', async () => await agenda.start());
}

let graceful = () => {
    agenda.stop(() => process.exit(0));
}

process.on("SIGTERM", graceful);
process.on("SIGINT", graceful);

module.exports = agenda;

.env.env.

DB_URL="mongodb://127.0.0.1:27017/test"
MONGO_URL="mongodb://127.0.0.1:27017"
DB_NAME="test"

Теперь давайте определим нашу работу.

Хотя вы можете определить свою работу внутри только одного файла, разделение каждая задание в его файле позволяет легко масштабироваться или иметь больше смысла для меня.

В повестке дня вы определяете работу, а затем вы можете запланировать или обработать их, как вы хотите на протяжении всего вашего приложения.

Давайте посмотрим на файл работы ArchiverideJob.

Работа/рабочие места/archiveridejob.js

let MongoClient = require("mongodb").MongoClient;

module.exports = (agenda) => {
    agenda.define("archive ride", (job, done) => {
        console.log("Archiving ride ...")

        // to be able to that you need to grab the ride id which is on the job document in the jobs collection in the database.
        // first let's connect to mongo db server
        //MONGO_URL="mongodb://127.0.0.1:27017"
        let client = new MongoClient(process.env.MONGO_URL) 
        
        client.connect((err) => {
            if(!err) {
                console.log('connection to db successful');
                
                // connect to the database
                // DB_NAME="test"
                let db = client.db(process.env.DB_NAME);
                
                // get the data passed when scheduling the job in the controller
                let rideId = job.attrs.data.rideId; 
                
                db.collection('rides').findOneAndUpdate({_id: rideId}, { $set: { status: 'expired' }}, (error) => {
                    if(!error) {
                        console.log('Successfully archived ride. rideId: ', rideId);
                        client.close();
                        done();
                    } else {
                        console.log("Error archiving ride ID: ", rideId);
                        console.log(error);
                        client.close();
                        done();
                    }
                })
            } else {
                console.log(err);
                client.close();
                done();
            }
        })
    })
}

Здесь я использую родной драйвер Node.js для MongoDB (не мангусты ORM). Если вы используете Mongoose, то вам нужно импортировать свои модели в этом файле и выполнять свои операции CRUD.

Итак, во-первых, мы определяем нашу задачу «Архив езды».

agenda.define('archive ride', function(job, done) {
    // your code goes here
    })

Далее я создаю подключение к моей базе данных.

let client = new MongoClient(process.env.MONGO_URL)
...
...
let db = client.db(process.env.DB_NAME);

Опять же, если вы используете ORM (Object Relational Mapper), как Mongoose, то вам не нужно создавать это соединение.

db.collection('rides').findOneAndUpdate({_id: rideId},
                    { $set: { status: 'expired' }}, function (error) {
                    if(!error) {
                    ....
                    ....
                        done();
                    }
                    ...
                    ...
                })

Это это для определения работы.

Теперь нам нужно запланировать нашу работу, когда пользователь создает поездку. Мы делаем это в нашем контроллере.

Контроллеры/RideController.js.

let agenda = require('../jobs/agenda');

module.exports = {
    postRide: (req, res) => {
            // you ride data when someone posts a ride
            let myRide = {
                departureDate: new Date(Date.now()), // aslo the archive date
                rideData: "Some data"
            }
            
            // get the database object from the request object see server.js
            let db = req.db;

            // create a new ride document the ride data
            db.collection('rides').insertOne({...myRide}, (ride, err) => {
                if(!err) {
                    // if the ride is successfully saved in the database, schedule a job with a unique id in the job collection
                    agenda.schedule(
                        myRide.departureDate, // date the function will execute
                        "archive ride", 
                        { rideId: ride.insertedId } // add additional information to be accessed by the job function: job.attrs.data.rideId;
                    );
                    res.send("Hello World!")
                } else {
                    console.log(err)
                    res.send("Hello Error!")
                }
            })
    }
}

Есть много способов планирования и выполнения рабочих мест с помощью agenda.js. Здесь я использую agenda.schedule (); Чтобы запланировать работу, которая должна быть выполнена в будущей дате, которую я указал. В качестве альтернативы вы можете использовать Pogenda.Now () (), чтобы немедленно выполнить задание. Перейдите к документации для [других методов]. (Https://github.com/agenda/agenda#creating-jobs).

Если вам интересно промежуточное программное обеспечение подключения к базе данных, я добавил этот пакет NPM Экспресс-Mongo-DB Отказ (Очень необязательно)

Вот как настроены маршруты и сервер:

маршруты/маршруты

const router = require("express").Router();

// import the controllers/functions to run when requesting a specific end point
let rideController = require('../controllers/rideController');


// run the function postRide in rideController when requestion "/" endpoint
router.get('/', rideController.postRide);


module.exports = router; // to be imported in server.js and used with route middleware

server.js.

let express = require('express')
require('dotenv').config(); // make environment variables available throughout the app
let expressMongoDB = require('express-mongo-db') // attach the mongodb instance to the request object

// importing routes
let indexRoutes = require('./routes/routes');

let app = express();
let port = 3000

// connects to the database and attach a db object to the request object
app.use(expressMongoDB(process.env.DB_URL)) // e.g: DB_URL="mongodb://127.0.0.1:27017/test"

app.use('/', indexRoutes)

app.listen(port, () => {
    console.log(`Server is listenung on port ${port}...`)
})

Вот и все. Если у вас есть вопросы или предложения, оставьте комментарий ниже.