What to do with Save & Replication conflicts
When customers start developing new Domino applications, the distributed nature of Domino can pose a stumbling block. Suddenly the unheard of replication conflict crops up and wants to be dealt with. A customer recently asked:
" I need to check with you about the Conflict Handling in Lotus Notes application. Default I will set the Conflict Handling to Create Conflicts, but I found my application have create more and more replication or save conflict documents. What can I do for all these replication or save conflict documents, and I found some information in conflict documents is not in original document? How can I prevent the system to generate conflict document?"
Before going into details, lets have a closer look how Notes handles its data. There's quite some hierarchy involved:
" I need to check with you about the Conflict Handling in Lotus Notes application. Default I will set the Conflict Handling to Create Conflicts, but I found my application have create more and more replication or save conflict documents. What can I do for all these replication or save conflict documents, and I found some information in conflict documents is not in original document? How can I prevent the system to generate conflict document?"
Before going into details, lets have a closer look how Notes handles its data. There's quite some hierarchy involved:
- to replicate two databases need to have the same replica id. The replica id is created when a database is created and only can be changed using the C API (or a wrapper around it). When a NSF is copied on the file system, you actually create a replica (but you wouldn't do that, would you?
- Inside a database 2 documents need to have the same document unique id (UNID), which is created from a time stamp at document creation time. The UNID is actually read/write in LotusScript and Java and a certain gentleman can teach you about creative
abuse of this capability. In addition in the document properties a sequence number is stored that gets incremented when a document is changed. Together with the last modification date this forms the patented Notes replication. - Inside the document the Notes items are stored. This are not just field values in a schema (like in an RDBMS) but little treasure troves of information. An item has a name, an array of values, a data type, an actual length and a sequence number. Notes can (and does) use this sequence number to see what items have been altered (note the difference: a form contains fields, a document contains items)
- Create conflicts (no $ConflictAction item)
The "loser" document is converted into a response document of the winner document and an item $Conflict is created. The conflicts are shown in in views unless excluded by view selection formula (& !@isAvailable($Conflict)
). Conflict resolution is manual (an agent you write is considered manual too) - Merge conflicts ($ConflictAction = "1")
If a document has been edited concurrently but different field have been altered, then they are merged into the one document and no conflict is created. If the same fields are altered a conflict is still generated.
Sounds good? In practise I often see this fail, when true distributed edits by users are the conflict cause, since applications habitually contain a field "LastEditedBy" with @UserName as formula - a lesson to be learned when designing distributed apps: update only what is really necessary - Merge/No Conflicts ($ConflictAction = "3")
Same as above: if different fields have been altered, then they are merged. If the same fields were altered the loser document is silently discarded. One could argue: why not merge at least the different fields. But that would create rather a data mess - No Conflicts ($ConflictAction = "2")
The radical solution: the winner takes it all, the loser disappears and nobody will ever know. I haven't seen a good use case for that, but the world is big
- Using document locking prevents them when edits happen on the same server
- Also make sure, that you scheduled agent don't run on two servers concurrently
- A nice rookie mistake is to use
NotesDocument.save(...)
in a querySave (or postSave without closing the form) event - Domino will (or has) saved the document, get out of its way - Recheck your application flow: Can you limit the current allowed editor using Author fields/items? Quite often removing access in querySave combined with an agent altering access "on documents changed" makes a lot of sense
- Check your forms: are there fields that are "computed" and changed by agents? You could/should set them to "computed when composed"
- Avoid
NotesDocument.computeWithForm(..)
in agents unless you are sure it isn't the source of your conflict - If your business logic mandates that you have multiple concurrent edits, consider to implement the inversion of logging pattern (with XPages you can make that real snappy)
- last not least: replicate more often or consider to cluster your servers
Posted by Stephan H Wissel on 02 January 2013 | Comments (6) | categories: Show-N-Tell Thursday