talis/tripod-php — pull request #4 by lordtatty (2014-05-14 16:18:51+00:00)
Title: XIP3135 - Ensure writes only read from primary

This issue is caused if a repset is being used, the tripod instance is set to SECONDARY or SECONDARY_PREFERRED, and a new document is written to it. In MongoTripod::lockSingleDocument() it first locks the document and then attempts to load it so it can be modified. If the document does not exist then it will create the document containing just the resource id and context and then loads the newly created document. In the latter case it will usually fail as it is trying to read from secondary and it is unlikely that the new document will have propagated to secondary by then.

The solution is to ensure it is only reading the document from primary. There are two possible approaches here. The one I prefer and have implemented here is the more defensive of the two, which sets the read preference to primary when calling saveChanges(), and then reverts to back to whatever it had previously been set to when the write operation is completed. This ensures that any read operation occurring during the write will read only from primary. The minor downside to this is that the switching of read preferences will occur with every call to saveChanges().

The more slimline option is to only do the switching of read preferences at the specific point where a new document is created in MongoTripod::lockSingleDocument(). This will mean fewer instances where this has to happen, although would mean that all other read operations that happen during the write time could potentially be affected by replication lag.