How to check mongodb connection status? - mongodb

How do I check if mongodb is still up from within Meteor? I tried (on the server) to stop mongodb and then write to a collection and read the record again, that works even if mongodb is not connected.
Problem is (on a self-hosted app) if the mongodb crashes the app does not throw an error, but there is no data. I would like to display an error message in that case.

The simplest way would be to create a document at startup and check whether it exists.
Meteor will poll all collections on a regular basis. If the database dies, the control document will be empty and this should trigger a ´removed´ event on the collection.
var control = Meteor.Collection("control-doc");
Meteor.startup(function () {
control.remove({});
control.insert({text: "just to fill"});
control.find().observe({
removed: function(old) {
//send an alert
console.log("alert");
}
})
});
it is not the nicest of tricks but it should work.

Have you tried Meteor.status()? Returns a reactive object with connection status stuff.

Related

Meteor connection lost randomly ,mongo collection find return null

Meteor connection lost randomly ,mongo collection find return null
Data.find({}, {sort: {createdAt: 1}});
safari open web page ,get the current data first ,and wait for few minutes and collection data will refresh, seems that meteor websocket was disconnect or something happened, the find function by mongo can not get data anymore,my tag info on web page will display none data
randomly appear,what should I do that can find the real problem?
what should I do that can find the real problem
You can write a Tracker.autorun routine that automatically refreshes when a reactive datasources "changes". You can then observe the change, for example by logging it to the console.
To get the connection status you have to use Meteor.status(), which is by fact a reactive data source.
Both together allow you to get informed, when the connection changes:
client/main.js
Meteor.startup(() => {
Tracker.autorun(() => {
const connection = Meteor.status() // triggers observer when change
console.log(connection.connected) // true / false
console.log(connection.status) // one of [connected, connecting, failed, waiting, offline]
console.log(reason)
})
})
Readings:
https://docs.meteor.com/api/connections.html#Meteor-status
https://docs.meteor.com/api/tracker.html#Tracker-autorun
Since you tagged vue:
https://guide.meteor.com/vue.html#vue-and-meteor-realtime-data-layer

Meteor - using snychronised non-persistent / in-memory MongoDB on the server

in a Meteor app, having real-time reactive updates between all connected clients is achieved with writing in collections, publishing and subscribing the right data. In normal case this means also database writes.
But what if I would like to sync particular data which does not need to be persistent and I would like to save the overhead of writing in the database ? Is it possible to use mini-mongo or other in-memory caching on the server by still preserving DDP synchronisation to all clients ?
Example
In my app I have a multiple collapsed threads and I want to show, which users currently expanded particular thread
Viewed by: Mike, Johny, Steven ...
I can store the information in the threads collection or make make a separate viewers collection and publish the information to the clients. But there is actually no meaning in making this information persistent an having the overhead of database writes.
I am confused by the collections documentation. which states:
OPTIONS
connection Object
The server connection that will manage this collection. Uses the default connection if not specified. Pass the return value of calling DDP.connect to specify a different server. Pass null to specify no connection.
and
... when you pass a name, here’s what happens:
...
On the client (and on the server if you specify a connection), a Minimongo instance is created.
But If I create a new collection and pass the option object with conneciton: null
// Creates a new Mongo collections and exports it
export const Presentations = new Mongo.Collection('presentations', {connection: null});
/**
* Publications
*/
if (Meteor.isServer) {
// This code only runs on the server
Meteor.publish(PRESENTATION_BY_MAP_ID, (mapId) => {
check(mapId, nonEmptyString);
return Presentations.find({ matchingMapId: mapId });
});
}
no data is being published to the clients.
TLDR: it's not possible.
There is no magic in Meteor that allow data being synced between clients while the data doesn't transit by the MongoDB database. The whole sync process through publications and subscriptions is triggered by MongoDB writes. Hence, if you don't write to database, you cannot sync data between clients (using the native pub/sub system available in Meteor).
After countless hours of trying everything possible I found a way to what I wanted:
export const Presentations = new Mongo.Collection('presentations', Meteor.isServer ? {connection: null} : {});
I checked the MongoDb and no presentations collection is being created. Also, n every server-restart the collection is empty. There is a small downside on the client, even the collectionHanlde.ready() is truthy the findOne() first returns undefined and is being synced afterwards.
I don't know if this is the right/preferable way, but it was the only one working for me so far. I tried to leave {connection: null} in the client code, but wasn't able to achieve any sync even though I implemented the added/changed/removed methods.
Sadly, I wasn't able to get any further help even in the meteor forum here and here

Atomically query for all collection documents + watching for further changes

Our Java app saves its configurations in a MongoDB collections. When the app starts it reads all the configurations from MongoDB and caches them in Maps. We would like to use the change stream API to be able also to watch for updates of the configurations collections.
So, upon app startup, first we would like to get all configurations, and from now on - watch for any further change.
Is there an easy way to execute the following atomically:
A find() that retrieves all configurations (documents)
Start a watch() that will send all further updates
By atomically I mean - without potentially missing any update (between 1 and 2 someone could update the collection with new configuration).
To make sure I lose no update notifications, I found that I can use watch().startAtOperationTime(serverTime) (for MongoDB of 4.0 or later), as follows.
Query the MongoDB server for its current time, using command such as Document hostInfoDoc = mongoTemplate.executeCommand(new Document("hostInfo", 1))
Query for all interesting documents: List<C> configList = mongoTemplate.findAll(clazz);
Extract the server time from hostInfoDoc: BsonTimestamp serverTime = (BsonTimestamp) hostInfoDoc.get("operationTime");
Start the change stream configured with the saved server time ChangeStreamIterable<Document> changes = eventCollection.watch().startAtOperationTime(serverTime);
Since 1 ends before 2 starts, we know that the documents that were returned by 2 were at least same or fresher than the ones on that server time. And any updates that happened on or after this server time will be sent to us by the change stream (I don't care to run again redundant updates, because I use map as cache, so extra add/remove won't make a difference, as long as the last action arrives).
I think I could also use watch().resumeAfter(_idOfLastAddedDoc) (didn't try). I did not use this approach because of the following scenario: the collection is empty, and the first document is added after getting all (none) documents, and before starting the watch(). In that scenario I don't have previous document _id to use as resume token.
Update
Instead of using "hostInfo" for getting the server time, which couldn't be used in our production, I ended using "dbStats" like that:
Document dbStats= mongoOperations.executeCommand(new Document("dbStats", 1));
BsonTimestamp serverTime = (BsonTimestamp) dbStats.get("operationTime");

How to get stream from Mongodb 3.6 $changeStream instead of pulling the cursor using $cmd.getMore?

I am a mongodb driver developer.
Is any way to get a stream for the changes? Like websocket/sse, keep sending data without close it.
Below is the $cmd which sent to mongodb to get a new changes from the server (I am using mongodb-core#3.0.2)
‌
{
"getMore":"5293718446697444994",
"collection":"event",
"batchSize":1
}
Is any way to get a stream for the changes?
According to the official MongoDB driver specifications for ChangeStream, it is an abstraction of a TAILABLE_AWAIT cursor. You may choose to implement it as an extension of an existing tailable cursor implementation.
Extending an existing cursor implementation would provide benefits as you don't have to implement other behaviour/features that comes automatically with a cursor.

How to check if a collection has changed?

I've created a JSON API with Express.js, Mongoose and MongoDB. Currently, there's no way for the clients of the API to check if the data in a collection has changed - they would need to download the whole collection periodically.
How could I allow the clients of the API to check for changes to a collections (inserts, updates, deletions) without downloading the collection itself?
Is there a way of getting the version number of the collection, the last change timestamp or a hash of the collection with Mongoose? What is the best practice solution to this problem?
In current and earlier versions of MongoDB, you have to do it on the application side, maybe using polling.
MongoDB 3.6 has a brand new feature called change stream that allows you to listen changes happening on your collections in real time.
The sample code to listen selected changes happening on your collection is below:
var MongoClient = require('mongodb').MongoClient
, assert = require('assert');
MongoClient.connect("mongodb://172.16.0.110:27017/myproject?readConcern=majority").then(function(client){
var db = client.db('myproject')
var changeStreams = db.collection('documents').watch()
changeStreams.on('change', function(change){
console.log(change)
})
})
If you are using node.js, you need to use following node module to get it working:
"dependencies": {
"mongodb": "mongodb/node-mongodb-native#3.0.0"
}