Use agenda with Meteor

Hi, I am trying to use agendajs with Meteor for some async jobs.

They say in the docs that to initialize you should use one of the forms:
const agenda = new Agenda({db: {address: mongoConnectionString}});

// Or override the default collection name:
// const agenda = new Agenda({db: {address: mongoConnectionString, collection: ‘jobCollectionName’}});

// or pass additional connection options:
// const agenda = new Agenda({db: {address: mongoConnectionString, collection: ‘jobCollectionName’, options: {ssl: true}}});

// or pass in an existing mongodb-native MongoClient instance
// const agenda = new Agenda({mongo: myMongoClient});

My question is if there is a way to reuse the meteor mongo client or if there are reasons not to do it.
I tried const { client } = MongoInternals.defaultRemoteCollectionDriver().mongo; const agenda = new Agenda({mongo: client});

but it didn’t work

I don’t have an answer but what would you win by reusing the connection?

I simply use agenda = new Agenda({db: {address: process.env.MONGO_URL}}).

You need to use the db property instead of the client property. :slight_smile:
Snippet from one my apps:

import Agenda from 'agenda';
import { MongoInternals } from 'meteor/mongo';

const { db: mongo } = MongoInternals.defaultRemoteCollectionDriver().mongo;
const agenda = new Agenda({ mongo });
1 Like

Hi Nathan,

thanks the connection works perfectly!
Quick additional question: how do you define your jobs in agenda? Specifically, if the jobs function does some db-operation, it throws the “Cannot await without a Fiber” error. Do you use wrapAsync/bindEnvironment inside the job function, or do you have a nicer solution?

Currently I do:

agenda.define(“new task”, Meteor.bindEnvironment((job, done) => {

I use rawCollection() for all database calls that don’t require pub/sub since I prefer to stick with the official Node.js driver API and I find myself using aggregate a lot. As a result, I don’t need to bind the environment, so my jobs look like the following code. I also export the job function (doSomething) so I can run integration tests on it.

fooCollection.js

import { Mongo } from 'meteor/mongo';

const fooCollection = new Mongo.Collection('foo');
export default fooCollection;

export function rawFooCollection() {
  return fooCollection.rawCollection();
}

someJob.js

import { rawFooCollection } from '../../../collections/userProposals/userProposals';
import agenda from '../agenda';

const someJob = 'someJob';
agenda.define(someJob, async (job, done) => {
  await doSomething();
  done();
});

agenda.every('5 minutes', someJob);

export async function doSomething() {
  const someData = await rawFooCollection()
    .find()
    .toArray();

  // do stuff with data
}
2 Likes