connect-mongostore
connect-mongostore copied to clipboard
There is a small chance for a concurrency dirty read problem
While working on a local machine (very low latency) between frontend and backend, I had the following rare case:
When the ".set" gets called, there is some time between submitting the save (upsert) request to the database and between getting the callback that the data is actually updated. Between this short period of time, there is a chance to get a dirty read from a new concurrent request.
I think this should solve it: When .set is called, the session object for the specific sid should be left in memory temporarily, if a get request is triggered then, that get request should return this temporary session in memory and not read from db. When the callback of the .set is called and the actual data is updated to the database at that point you can get rid of the temporary session object that you left in memory, so subsequent .get calls will fetch again from database now...
Of course there are cases where you get subsequent saves (.set) some sort of reference counting on the temp session object in memory should resolve this. The problem doesn't stop here but this solves part of it. Two concurrent calls will start with two .get, each receiving a different copy in memory, at this point one of the two will finish first and will save the new updated session object, when the next calls is also done and wants to save it's copy, the first ones save is lost...
Furthermore you should add some defense mechanism to the .save. The session object read should have the last timestamp when the data in Mongo was updated. Upon saving, that timestamp to be saved should be the same with the timestamp that is already there, (add to filter, if they don't match, update count = 0) otherwise, in between a newer session state was saved from a different source. Not sure how to react in this situation, but at least we shouldn't overwrite the session data in this case as a probably newer version already is there in the database. In RDB environments, ideally, the database takes care of this concurrency problem.
Thank you.