Leveraging Agenda.js for Efficient Email Scheduling in Node.js Backend
Tags: node, learning, database, webdev
Published: 2024-06-05 19:07:35

## Introduction
In the realm of backend development with Node.js, efficiently managing asynchronous tasks is crucial for maintaining application robustness and responsiveness. Node.js thrives on handling many requests concurrently, but long-running asynchronous operations (like database calls or network requests) can block the main thread, hindering responsiveness. This is where _background jobs_ come in.

[Agenda](https://www.npmjs.com/package/agenda) , a powerful MongoDB-based job scheduling library, excels at managing these background jobs. It allows you to schedule tasks to run asynchronously in the background, freeing up the main thread to handle user requests promptly. This article focuses on how to set up and configure Agenda in a Node.js backend to schedule email reminders. Sending email reminders is a perfect example of how Agenda.js can streamline these asynchronous background processes.


## Understanding Agenda
Agenda.js is a flexible job scheduling library for Node.js, designed to work seamlessly with MongoDB. It allows developers to define, schedule, and manage jobs, making it an excellent choice for tasks such as email reminders, data processing, and more.

## Setting Up Agenda.js
Let's start by integrating Agenda.js into our Node.js backend.

## Step 1:Install Agenda.js

```
npm install agenda
```

## Step 2: Configure Agenda.js
Next, configure Agenda.js to connect to your MongoDB instance. Create a file named connect.js for this configuration

```
const { Agenda } = require('agenda');
const { MongoClient, ServerApiVersion } = require('mongodb');

// Configure Agenda
const agenda = new Agenda({
  db: { address: "mongodb+srv://<YOUR_MONGO_USERNAME>:<YOUR_MONGO_PASSWORD>@cluster0.mongodb.net/<YOUR_DATABASE_NAME>?retryWrites=true&w=majority", collection: 'agendaJobs' },
});

async function connectToMongoDB() {
  const uri = "mongodb+srv://<YOUR_MONGO_USERNAME>:<YOUR_MONGO_PASSWORD>@cluster0.mongodb.net/<YOUR_DATABASE_NAME>?retryWrites=true&w=majority";

  const client = new MongoClient(uri, {
    serverApi: {
      version: ServerApiVersion.v1,
      strict: true,
      deprecationErrors: true,
    }
  });

  try {
    await client.connect();
    await client.db("admin").command({ ping: 1 });
    console.log("Connected to MongoDB!");
    return client;
  } catch (err) {
    console.error(`Error connecting to MongoDB: ${err}\n`);
    throw err;
  }
}

module.exports = { connectToMongoDB, agenda };
```

Replace YOUR_MONGO_USERNAME, YOUR_MONGO_PASSWORD, and YOUR_DATABASE_NAME with your actual MongoDB credentials and database name.

## Defining and Scheduling Jobs with Agenda.js:
Now, let's define a job in Agenda.js and schedule it. In this example, we will schedule an email reminder.

## Step 3: Define the Job
Define the job that sends an email reminder. Add the following code to your main application file or create a new file for handling tasks:
```
const { ObjectId } = require('mongodb');
const nodemailer = require('nodemailer');
const { agenda, connectToMongoDB } = require('./connect');
require('dotenv').config();

// Define the 'sendEmail' job
agenda.define('sendEmail', async (job) => {
  const { toSender, email_subject, messageContent } = job.attrs.data;

  try {
    const transporter = nodemailer.createTransport({
      host: "smtp.gmail.com",
      port: 587,
      secure: false,
      auth: {
        user: process.env.EMAIL_USERNAME,
        pass: process.env.EMAIL_PASSWORD,
      },
      tls: {
        rejectUnauthorized: false,
      },
    });

    const message = {
      to: toSender,
      subject: email_subject,
      html: messageContent
    };

    await transporter.sendMail(message);
    console.log("Email sent successfully");
  } catch (error) {
    console.error('Error sending email:', error);
    throw new Error("Email could not be sent");
  }
});
```
Update process.env.EMAIL_USERNAME, process.env.EMAIL_PASSWORD, and the database name in connectToMongoDB to match your configuration.

## Step 4: Schedule the Job
Create a function to schedule the email reminder job when a new task is added. Here’s an example function for adding a task and scheduling the email:
```
async function addTask(req, res) {
  const { taskTitle, endDatetime, taskDescription, creationTime, taskStatus } = req.body;
  let client;

  try {
    client = await connectToMongoDB();
    const database = client.db('<YOUR_DATABASE_NAME>'); // Update this to match your database name
    const tasksCollection = database.collection('<YOUR_COLLECTION_NAME>'); // Update this to match your collection name
    await tasksCollection.insertOne({
      taskTitle,
      taskDescription,
      endDatetime,
      creationTime,
      taskStatus,
    });

    // Schedule the email reminder
    await agenda.schedule(new Date(endDatetime), 'sendEmail', {
      toSender: "<RECIPIENT_EMAIL_ADDRESS>", // Update this to the actual recipient's email address
      email_subject: 'Task Reminder',
      messageContent: 'This is a reminder for your task.',
    });

    res.json({ status: true, message: 'Task created and email reminder scheduled' });
  } catch (error) {
    console.error('Error adding task:', error);
    res.json({ status: false, message: 'An error occurred while adding the task' });
  } finally {
    await client.close();
  }
}

module.exports = { addTask };



```
Note: Update  **_RECIPIENT_EMAIL_ADDRESS_**, **_YOUR_DATABASE_NAME_**, and **_YOUR_COLLECTION_NAME_**to match your configuration.

## Conclusion
By integrating Agenda.js into your Node.js backend, you can efficiently manage and schedule tasks, such as sending email reminders. Agenda.js's seamless integration with MongoDB makes it a powerful tool for handling asynchronous operations, enhancing both application functionality and user experience.