Ok, there is no difference between V2 and V3 in how DB connections are initiated.
However, in V3, not only Meteor.callAsync is required but also awaiting for it. However you don’t normally call a server side method from another server side method. You can just use a function instead and import/export it wherever you need it.
The best way to store secret DB connection credentials is with env vars (Environment Variables | Meteor API Docs). In this way you can change a variable without having to redeploy code. Most cloud hosts have a page/menu for these variables.
So I would say,
// Anywhere (Isomorphic)
// From here ....
import { Meteor } from 'meteor/meteor'
import { MongoInternals } from 'meteor/mongo'
const options = '?retryWrites=true' +
'&maxIdleTimeMS=5000' +
'&maxPoolSize=30' +
'&readConcernLevel=majority' +
'&readPreference=secondaryPreferred' +
'&w=majority' +
'&heartbeatFrequencyMS=15000'
const connectionUri = process.env.MONGO_YOUR_CONNECTION_URI
const liveConnectionUri = `mongodb+srv://${connectionUri}${options}`
const localConnectionUri = 'mongodb://127.0.0.1:3001/meteor' // or your local meteor mongo DB
const uri = Meteor.isProduction ? liveConnectionUri : localConnectionUri
const driver = {
_driver: new MongoInternals.RemoteCollectionDriver(uri, {})
}
// To here .... you can write in a separate file if you have multiple connections and want to keep them organized. Export { driverOne, driverTwo ... }
const Audits = new Mongo.Collection('audits', driver)
export default Audits
You are correct I didn’t need a Meteor.call to obtain the driver AND I can access it via settings or environment variable; but the issue remains for me, the following code in V3 still does not connect to the secondary database.
When I map the collections it returns a list of collections from the primary database.
import { Mongo, MongoInternals } from 'meteor/mongo';
import { Meteor } from 'meteor/meteor';
let driver;
const mapCollections = async () => {
const { db } = driver.mongo;
const collections = await db.collections();
collections.map((c) => console.log(c.collectionName));
};
if (Meteor.isServer) {
// eslint-disable-next-line new-cap
driver = new MongoInternals.defaultRemoteCollectionDriver(process.env.DB);
mapCollections();
}
const Audits = new Mongo.Collection('audits', { _driver: driver });
export default Audits;
if (Meteor.isServer) {
// eslint-disable-next-line new-cap
driver = new MongoInternals.defaultRemoteCollectionDriver(process.env.DB);
mapCollections();
}
const Audits = new Mongo.Collection('audits', { _driver: driver });
I haven’t used isomorphism for at least 10 years and I don’t remember what is the correct way to initialize a new connection on both client and server. However, if you initialize your driver inside isServer what is the value of the driver otherwise (isClient)?
I think you don’t need to use that isServer at all and use env vars, which are only available on the server anyway.
Also, following the code, at the time you call mapCollections() you haven’t yet initialized the ‘audits’ collection. I suggest you start with less restrictions, run everything on the server side and then move to expanding to the client.