I'm using MongoDB Atlas. I'm have this URL for connecting: mongodb+srv://<LOGIN>:<PASSWORD>@<URL>/<DB>?retryWrites=true&w=majority&authSource=admin
.
I'm using this stack: flask, gunicorn, pymongo, mongoengine (i don't think that it is related, because mongoengine actually uses pymongo).
gunicorn config:
- sync workers,
- threads = 1,
- workers count = 8
When connecting, i'm using connect=False
because pymongo itself is not fork-safe. With connect=False
it will connect to the DB before first operation. It need to be set to False
, because gunicorn uses pre-fork model.
But I am faced with the following situation:
- On first request (endpoint makes some DB operations) i'm getting this error:
pymongo.errors.OperationFailure: Authentication failed., full error: {'ok': 0, 'errmsg': 'Authentication failed.', 'code': 8000, 'codeName': 'AtlasError'}
- On second request everything is fine (i.e., DB operations were successfully completed).
- If you press many times on F5, then sometimes you will occur a "Authentication failed" error, and sometimes everything will be fine.
If i'm set connect=True
, everything will be fine. I'm never seen this "Authentication failed" error.
But then i'm getting this warning message: UserWarning: MongoClient opened before fork. Create MongoClient only after forking. See PyMongo's documentation for details: https://pymongo.readthedocs.io/en/stable/faq.html#is-pymongo-fork-safe
.
So, obviously, connect
need to be set to False
.
I'm tested with two workers. Looks like this situation occurs:
- Let's say i have two gunicorn sync workers with following pid's: 22429 and 22430.
- I'm getting request. Worker 22429 handles it. Everything is fine, because it is first worker and looks like it successfully made a DB connection.
- I'm pressing F5, worker 22429 again handles it and everything is fine.
- I'm pressing F5 again, and now worker 22430 handles it. It throws an error "Authentication failed."
- I'm pressing F5 again, worker 22430 handles it. Now everything is fine, because that worker has made a connection.
- Now, all my workers (i have only two) were connected to the DB. Doesn't matter how many times i'm press on F5, every request will be successfully completed.
But why it happens on first reques? From pymongo: "if connect=False, then connect on the first operation.". If i'm understanding it right, pymongo should connect before actual first operation, successfully completed the connection, and only then perform that operation.
Then why my first DB operation fails for each worker? How i should handle this?