Hi, the should: raise: MagmaCommitConflictError in #testTriggerACommitConflictUsersCommitAfterEachOtherButWithTheSameVersionOfObjectInitiallyLoaded :
self should: [secondSession commit. "6.7. User 2 commits his transaction"] raise: MagmaCommitConflictError.
fails because secondSession crossed a transaction boundary (via its #begin) after firstSession's commit. Second session would see the results of firstSession's commit, and therefore there is no conflict. A commit-conflict would have occurred if secondSession had sent #begin BEFORE firstSession's commit..
Regards, Chris
On Tue, Dec 8, 2009 at 2:18 PM, Bart Gauquie bart.gauquie@gmail.com wrote:
Dear all,
I've been trying out the MagmaCommitConflictError in Magma. I'm experiencing following which I do not understand. I've attached a changeset with a test case reproducing the behaviour I do not understand. If I follow the steps outlined at: http://wiki.squeak.org/squeak/2636%C2%A0a%C2%A0MagmaCommitConflictError is thrown. (see testTriggerACommitConflictSequenceAsDescribedOnWiki and a little modification on that: testTriggerACommitConflictLoadObjectBeforeStartingATransaction) If I however execute testTriggerACommitConflictUsersCommitAfterEachOtherButWithTheSameVersionOfObjectInitiallyLoaded
|firstSession secondSession mockObjectRefByFirstSession mockObjectRefBySecondSession| [firstSession := (MagmaRemoteLocation host: 'localhost' port: self databasePort) newSession. firstSession connectAs: 'firstSessionUser'. firstSession commit: [ firstSession root at: 'mockObject' put: (SomeMockDomainObject new aField: 'aField content'; yourself)].
secondSession := (MagmaRemoteLocation host: 'localhost' port: self databasePort) newSession. secondSession connectAs: 'secondSessionUser'.
mockObjectRefByFirstSession := firstSession root at: 'mockObject'. "User 1 is loading the object" mockObjectRefBySecondSession := secondSession root at: 'mockObject'. "User 2 is loading the same version of the object as User 1"
firstSession begin. "1. User 1 begins a transaction." mockObjectRefByFirstSession aField: 'aField updated by user 1'. "3. User 1 changes Object A." firstSession commit. "4. User 1 commits his transaction."
secondSession begin. "2. User 2 begins a transaction." mockObjectRefBySecondSession aField: 'aField updated by user 2'. "5. User 2 changes Object A."
self should: [secondSession commit. "6.7. User 2 commits his transaction"] raise: MagmaCommitConflictError.
firstSession refresh. self assert: 'aField updated by user 1' equals: ((firstSession root at: 'mockObject') aField). self assert: 'aField updated by user 1' equals: ((secondSession root at: 'mockObject') aField). self assert: 'aField updated by user 1' equals: (mockObjectRefBySecondSession aField).
] ensure: [[firstSession commit: [ firstSession root removeAll]. firstSession disconnect] ensure: [secondSession disconnect]]
It failes and I dont understand why. The test is what you get in a typical web application. User 1 has a session on the database. User 2 has another session. Both opened an item. Both are editing it and then first user1 commits his changes. User 2 wants to commit his changes but did not see the updated data of User 1. The test failes at : self should: [secondSession commit. "6.7. User 2 commits his transaction"] raise: MagmaCommitConflictError. => MagmaCommitConflictError is not thrown. Which is something I do not understand. User 2 is trying to commit a change on an object some other session already changed. So User 2 is trying to update a stale version. Is there a reason why no MagmaCommitConflictError is thrown? Furthermore, if you proceed on the failing MagmaCommitConflictError; refresh the firstSession; i notice that the changes made by Session2 effectively got committed; which surprises me even more. Because that means that the changes made by User 1 got overridden by the changes of User 2 without User 2 even knowing. If I read the information on the wiki, this behaviour is correct since Magma will only detect if during a transaction (after begin has been called) some other session has committed changes on the object being changed. Off course this is not the kind of behaviour you have if you're developing web applications since there, the transactions are very short. Is there a way to detect if an object was updated by another transaction, but not within my own transaction; so that stale updates do not happen. I suppose there is some version on a persisted object you can check and if the last committed version of an object is higher than the version in the current session, this also means a magmacommitconflicterror? But I havent found any info about that yet? Thanks for any help. Kind Regards, Bart -- imagination is more important than knowledge - Albert Einstein Logic will get you from A to B. Imagination will take you everywhere - Albert Einstein Learn from yesterday, live for today, hope for tomorrow. The important thing is not to stop questioning. - Albert Einstein The true sign of intelligence is not knowledge but imagination. - Albert Einstein Gravitation is not responsible for people falling in love. - Albert Einstein
Magma mailing list Magma@lists.squeakfoundation.org http://lists.squeakfoundation.org/mailman/listinfo/magma