rollbacks in magma

Chris Muller chris at funkyobjects.org
Fri May 19 16:35:44 UTC 2006


Hi,

> Sorry I didn't answer the last mail you sent to me. I wanted to learn
> more about Magma and make more tests before migrate all my data.

An excellent idea with any technology.  Find out about it, make sure it
works the way you need first.  :)

> In test1TransactionCommit a key is added and the removed. The first
> time the test is run, if pass. But the seconds it fails because the
> key is found, and it was supossed to be deleted from the server
> session (and the files).

For local-connections, you need to use #disconnectAndClose, not just
#disconnect, otherwise the files don't get closed and you will not be
able to delete them between tests.

In this test1TransactionCommit I see:

  aServerSession := (MagmaRepositoryController openedOn:
aFullyQualifiedPathString) session.

This is not a proper way to use Magma.  You should *never never never*
access the servers session, it is used by the system and mettling it is
asking for trouble.  If you need multiple locally-connected sessions
you  can use:

  mySecondSession := MagmaSession repositoryController:
(MagmaRepositoryController openedOn: aFullyQualifiedPathString)

For this code:

	self shouldnt:[ aMagmaSession begin.
		self deny: ( aRoot includesKey: 'otra').
		aRoot at: 'otra' put: 'hola'.
		self assert: ( aRoot includesKey: 'otra').
		aMagmaSession commit.
	] raise: MagmaCommitError.
	self assert: ( aRoot includesKey: 'otra').

since it is using a local connection and only one session, you should
never get a MagmaCommitError, so this test will always pass.  Also, you
probably want to disconnect the session before that last assert (aRoot
includesKey: 'otra') because, otherwise, it is only really testing
Dictionary>>#at:put:, not Magma.  You probably want to test
*re-getting* the root from the database has the 'otra' key.

> The other problematic test is test2NestedTransactionAbort.
> The general idea is 1) begin a transaction, add an element without
> commiting 2) begin another transaction inside the first, remove this
> element 3) abort the inner transaction 4)commit the outer. In other
> words, edit an object, edit an object inside the first, cancel this
> change but save the first.
> But after the inner transaction abort, the outer raises an error "No
> transaction to commit"
> Evidently, we are doing something wrong, but we can't find it.
> Would you give us a hint?

Ah, the "nested transactions" are not that sophisticated.  You cannot
abort partial changes, #abort cancels ALL LEVELS of transactions.

The nested transactions are merely to allow code to be more flexible,
so you can have three separate operations:

  BankAccount>>#deposit: anAmount
    MagmaSessionRequest signalCommit: [ balance := balance + anAmount ]

  BankAccount>>#withdraw: anAmount
    MagmaSessionRequest signalCommit: [ balance := balance - anAmount ]

  and

  BankAccount>>#transfer: anAmount to: anotherAccount
    MagmaSessionRequest signalCommit: 
      [ self withdraw: anAmount.
      anotherAccount deposit: anAmount ]

Earlier versions of Magma would signal an MagmaUserError, "Already in a
transaction" if you tried to use transfer:to:.  But all three of these
operations are independently needed, and they all need their own
commit.  So with the "nested transactions" feature is nice that
#transfer:to: does not need to worry whether the session is already in
a transaction.

I hope this helps!

 - Chris

PS - I suggest never to override #finalize.  It is on the class side
here so maybe its ok since it will never get called by the system but
you might want to rename that.



More information about the Magma mailing list