Goland mongodb "connection refused" error handling - mongodb

Good day!
I have a service which is running in loop like this:
for {
select {
case <-ctx.Done():
return fmt.Errorf("context error: %w", ctx.Err())
default:
}
task, err := provider.Next(ctx)
if !errors.Is(err, ErrNotFound) {
return fmt.Errorf("next: %w", err)
}
// some work todo
}
Sometimes something happens with my mongodb and I get an error like
connection() : connection(mongorc:27017[-48]) incomplete read of message header: context deadline exceeded"
So I have to check
errors.Is(err, context.DeadlineExceeded).
as well as ErrNotFound.
But If I dont put timeout to mongo requests I get error like
server selection timeout, current topology: { Type: Single, Servers: [{ Addr: localhost:27017, Type: Unknown, State: Connected, Average RTT: 0, Last error: connection() : dial tcp 127.0.0.1:27017: connect: connection refused }, ] }
And I have no idea how to check it - I didnt find any "mongo.Err..." that is up to this error. Is there a way to check it in the code?

Related

Cannot connect to mongodb Error error occurred during connection

im trying to connect to my mongodb from my api written in golang
but every time i run my app it gives me this error:
2022/12/06 19:09:25 server selection error: server selection timeout, current topology: { Type: ReplicaSetNoPrimary, Servers: [{ Addr: ac-tqorttq-shard-00-02.atpezds.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: dial tcp 52.28.222.2:27017: i/o timeout }, { Addr: ac-tqorttq-shard-00-00.atpezds.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: dial tcp 18.197.37.129:27017: i/o timeout }, { Addr: ac-tqorttq-shard-00-01.atpezds.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: dial tcp 18.195.134.220:27017: i/o timeout }, ] }
my code:
func init() {
clientOptions := options.Client().ApplyURI(configs.GetEnv("MONGOURI"))
client, err := mongo.Connect(context.TODO(), clientOptions)
checkErr(err)
err = client.Ping(context.TODO(), nil)
checkErr(err)
fmt.Println("connected to database successfully")
notesCollection = openCollection("notes_collection")
userCollection = openCollection("user_collection")
}
i tried to remove the "+srv" from the connection string then
it gives me this error:
2022/12/06 19:16:46 server selection error: server selection timeout, current topology: { Type: Unknown, Servers: [{ Addr: cluster0.atpezds.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: dial tcp: lookup cluster0.atpezds.mongodb.net: No address associated with hostname }, ] }
hope you guys help me
and thanks
func main() {
client, err := mongo.NewClient(options.Client().ApplyURI("<ATLAS_URI_HERE>"))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
err = client.Ping(ctx, readpref.Primary())
if err != nil {
log.Fatal(err)
}
databases, err := client.ListDatabaseNames(ctx, bson.M{})
if err != nil {
log.Fatal(err)
}
fmt.Println(databases)
}
Check that you are using the correct username and password for your database user, and that you are connecting to the correct database deployment. Check that you are specifying the correct authSource database in your connection string.
Hope this helps!!

Can't connect Go api to MongoDB database | ReplicaSetNoPrimary error

Here is the error showing after "go run main.go"
❯ go run main.go
2022/08/10 20:07:51 server selection error: context deadline exceeded, current topology: { Type: ReplicaSetNoPrimary, Servers: [{ Addr: ac-nldr28t-shard-00-00.pfel30m.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: connection(ac-nldr28t-shard-00-00.pfel30m.mongodb.net:27017[-28]) socket was unexpectedly closed: EOF }, { Addr: ac-nldr28t-shard-00-01.pfel30m.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: connection(ac-nldr28t-shard-00-01.pfel30m.mongodb.net:27017[-27]) socket was unexpectedly closed: EOF }, { Addr: ac-nldr28t-shard-00-02.pfel30m.mongodb.net:27017, Type: Unknown, Last error: connection() error occurred during connection handshake: connection(ac-nldr28t-shard-00-02.pfel30m.mongodb.net:27017[-26]) socket was unexpectedly closed: EOF }, ] }
exit status 1

mongo golang driver sever selection timeout

I have launched the mongodb helm chart (standalone mode , set rootPassword, username, password in values.yaml) and I tried launching just the docker container too, I'm hitting the same error.
func (s *Session) ConnectToDB(u, p string) (*mongo.Client, error) {
var err error
uri := fmt.Sprintf("%s:%s", mongoDBURL, mongoDBPort)
auth := new(options.Credential)
auth.Username = u
auth.Password = p
opts := options.Client().ApplyURI(uri).SetAuth(*auth)
opts.SetConnectTimeout(-1)
opts.SetDirect(true)
s.Ctx = context.TODO()
//opts.SetMaxPoolSize(5) # TODO
if s.Client, err = mongo.Connect(s.Ctx, opts); err != nil {
msg := fmt.Sprintf("error connecting to mongo: %v", err)
log.Printf(msg)
return nil, fmt.Errorf(msg)
}
err = s.Client.Ping(s.Ctx, nil)
if err != nil {
log.Fatal(err). <<<<< Fails with error
}
s.Collection = getCollection(s
)
The URL:port is
mongoDBPort = "27017"
mongoDBURL = "localhost"
I have tried, "mongodb://mongodb.spektra-system.svc.cluster.local" too. The Client ping fails with error
server selection error: server selection timeout, current topology: { Type: Single, Servers: [{ Addr: localhost:27017, Type: Unknown, Average RTT: 0, Last error
: connection() error occured during connection handshake: dial tcp: i/o timeout }, ] }
Should I set something in the values.yaml ??? Not sure why this fails. I'm using mongo golang diver 1.5
Googling around I found directConnect=true is required, didn't help .

Sails application fails to connect localhost mongo db

My sails application not able to connect to locally running mongo db instance
local.js is like below
module.exports.connections = {
sailsMongoDBServer: {
adapter: 'sails-mongo',
host: '127.0.0.1',
port: 27017,
database: 'dp-manager-db'
}
}
Error :
2019-03-06T12:32:01.081Z - error:
{ message:
'The hook `orm` is taking too long to load.\nMake sure it is triggering its `initialize()` callback, or else set `sails.config.orm._hookTimeout to a higher value (currently 20000)',
stack:
'Error: The hook `orm` is taking too long to load.\nMake sure it is triggering its `initialize()` callback, or else set `sails.config.orm._hookTimeout to a higher value (currently 20000)\n at Timeout.tooLong [as _onTimeout] (E:\\workspace_DpForm\\Eclipse\\dpm-app\\node_modules\\sails\\lib\\app\\private\\loadHooks.js:85:21)\n at ontimeout (timers.js:436:11)\n at tryOnTimeout (timers.js:300:5)\n at listOnTimeout (timers.js:263:5)\n at Timer.processTimers (timers.js:223:10)',
code: 'E_HOOK_TIMEOUT' }
2019-03-06T12:32:03.521Z - error: A hook (`orm`) failed to load!
E:\workspace_DpForm\Eclipse\dpm-app\node_modules\mongodb\lib\mongo_client.js:224
throw err

Node and Mongoose - Not reconnecting if mongod was not running when first tried to connect

Im using docker-composer and Im finding issues with execution order of services. The main issue happens when my express app tries to connect to mongod but this is not yet ready.
The issue can be reproduced easily by running first the nodejs application but not mongod (manually forcing this case).
My app uses mongoose and try to establish connection to mongod. Because mongod is not up and running, the app throws an error about it.
$ nodemon server/app.js
24 Apr 21:42:05 - [nodemon] v1.7.0
24 Apr 21:42:05 - [nodemon] to restart at any time, enter `rs`
24 Apr 21:42:05 - [nodemon] watching: *.*
24 Apr 21:42:05 - [nodemon] starting `node server/app.js`
Listening on port 8000
disconnected
connection error: { [MongoError: connect ECONNREFUSED] name: 'MongoError', message: 'connect ECONNREFUSED' }
Starting mongod later seems to reconnect.
24 Apr 21:51:28 - [nodemon] v1.7.0
24 Apr 21:51:28 - [nodemon] to restart at any time, enter `rs`
24 Apr 21:51:28 - [nodemon] watching: *.*
24 Apr 21:51:28 - [nodemon] starting `node server/app.js`
Listening on port 8000
disconnected
connection error: { [MongoError: connect ECONNREFUSED] name: 'MongoError', message: 'connect ECONNREFUSED' }
connected
reconnected
Despite of that, operations that require access to mongo will not come through... neither error is shown
This is the code to connect to mongo using mongoose:
// Starting mongo
mongoose.connect(config.database, {
server:{
auto_reconnect:true,
reconnectTries: 10,
reconnectInterval: 5000,
}
});
// Listening for connection
var mongo = {};
var db = mongoose.connection;
db.on('connected', console.error.bind(console, 'connected'));
db.on('error', console.error.bind(console, 'connection error:'));
db.on('close', console.error.bind(console, 'connection close.'));
db.once('open', function() {
console.log("We are alive");
});
db.on('reconnected', function(){
console.error('reconnected');
});
db.on('disconnected', console.error.bind(console, 'disconnected'));
And here is the route that will try to get data from mongo but fail.
router.post('/auth', function(req, res){
User.findOne({name: req.body.name})
.then(function(user){
if(!user)
{
res.status(401).send({ success: false, message: 'Authentication failed. User not found.' });
}
...
How can I recover from running nodejs before mongo is ready?.
In my case, I created separate function only for mongoose connect method:
const connect = () => {
mongoose.connect('mongodb://localhost:27017/myapp', {
useNewUrlParser: true,
reconnectTries: Number.MAX_VALUE,
reconnectInterval: 500,
poolSize: 10,
});
};
I'm calling it at the same start. I also added Event Handler for error event:
mongoose.connection.on('error', (e) => {
console.log('[MongoDB] Something went super wrong!', e);
setTimeout(() => {
connect();
}, 10000);
});
If mongoose fails to connect because MongoDB is not running, error event handler is fired and setTimeout schedules "custom" reconnect.
Hope it helps.
How long does it take before mongod is ready? Because it seems like this is an edge case issue, where mongod might take a couple of seconds to get ready; and when mongoose is connected it serves requests as expected. Just trying to understand why the slight delay (probably a only a few seconds) is necessary to resolve?
But here is a solution anyway:
You could set up an express middleware to check if mongoose is ready and throw an error if not:
app.use(function(req,res,next){
if (mongoose.Connection.STATES.connected === mongoose.connection.readyState){
next();
} else {
res.status(503).send({success:false, message: 'DB not ready' });
}
});
This should go before you inject your router.
I had the same issue with Mongoose 5+. I was able to get this working by creating a retry function using set timeout.
const mongoose = require('mongoose');
const {
MONGO_USERNAME,
MONGO_PASSWORD,
MONGO_HOSTNAME,
MONGO_PORT,
MONGO_DB,
MONGO_DEBUG,
MONGO_RECONNECT_TRIES,
MONGO_RECONNECT_INTERVAL,
MONGO_TIMEOUT_MS,
} = process.env;
if (MONGO_DEBUG) {
console.log(`********* MongoDB DEBUG MODE *********`);
mongoose.set('debug', true);
}
const DB_OPTIONS = {
useNewUrlParser: true,
reconnectTries: MONGO_RECONNECT_TRIES,
reconnectInterval: MONGO_RECONNECT_INTERVAL,
connectTimeoutMS: MONGO_TIMEOUT_MS,
};
const DB_URL = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}#${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DB}?authSource=admin`;
// Initialize conenction retry counter
let reconnectTriesAlready = 1;
// Connect to database with timeout and retry
const connectWithRetry = () => {
mongoose.connect(DB_URL, DB_OPTIONS).then(() => {
// Connected successfully
console.log('********* MongoDB connected successfully *********');
// Reset retry counter
reconnectTriesAlready = 1;
}).catch(err => {
// Connection failed
console.error(`********* ERROR: MongoDB connection failed ${err} *********`)
// Compare retries made already to maximum retry count
if (reconnectTriesAlready <= DB_OPTIONS.reconnectTries) {
// Increment retry counter
reconnectTriesAlready = reconnectTriesAlready + 1;
// Reconnect retries made already has not exceeded maximum retry count
console.log(`********* MongoDB connection retry after ${MONGO_RECONNECT_INTERVAL / 1000} seconds *********`)
// Connection retry
setTimeout(connectWithRetry, MONGO_RECONNECT_INTERVAL)
} else {
// Reconnect retries made already has exceeded maximum retry count
console.error(`********* ERROR: MongoDB maximum connection retry attempts have been made already ${DB_OPTIONS.reconnectTries} stopping *********`)
}
})
}
connectWithRetry();