Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
Changing objects in Magma
Last updated at 3:59 am UTC on 3 June 2015
Magma utilizes a simple transaction protocol to isolate a batch of object changes that can be saved as a whole or canceled as a whole.

The three important messages of the transaction protocol are:


These messages are sent to a MagmaSession.

Essentials of transactions

When a program executes any of these messages, it is said to be "crossing a transaction boundary," and is the time when the the local image is updated from the Magma repository. All changes committed by other users since your last crossing immediately become visible to the session. For a commit, all individual changes made in your image are saved to the repository and will become visible to all other users as soon as they cross their next transaction boundary.

It may seem evident that, with unfortunate timing of events, one user would be able to overlay changes made by another user. For example, consider the following scenario:

  1. User 1 begins a transaction.
  2. User 2 begins a transaction.
  3. User 1 changes Object A.
  4. User 1 commits his transaction.
  5. User 2 changes Object A.
  6. User 2, cannot yet see User 1's changes, because she has not crossed a transaction boundary since the commit.
  7. User 2 commits.

Magma will detect this conflict and signal a MagmaCommitError back to user 2. This is because she tried to change an object that was changed by User 1 since she began her transaction, invalidating her changes. The failed result object has the conflicting objects (Object A) and the name of each user who changed them (User 1). Additionally, User 2 can now see the new Object A, as changed by User 1, because her commit attempt caused a crossing of a transaction boundary.

At this point, User 2 is still in a transaction, and can now see Object A as committed by User 1. She may now commit again, or abort if appropriate.

Nested Transactions

Magma allows you to say:
  mySession commit:
    [ ...make some changes...
    mySession commit: [ ...make some other changes... ] ]

The inner-commit actually does nothing; only the outer-commit writes all changes to the db. This is to support the requirement that a bank withdrawal be its own usable operation, a bank deposit be its own usable operation, but also transfer from one account to another (which uses the withdrawal code followed by deposit code) to only be committed wholly. You can just use #commit: in all three methods and it will only consider the outermost commit the one that really commits to the database.

Concurrency

In terms of updating a shared persistent model, a "conflict" occurs when a session tries to update an old version of an object. Another session changed the object, therefore Magma cannot allow those changes to be overwritten (not to mention that the new changes may no longer be necessary). Persistent objects in an image are updated each time your session issues a #begin, #commit or #abort.

Transactions in the client may be as long as desired, but keep in mind the Magma server will terminate inactive sessions. What happens when the client comes back is, the connection is re-established automatically.

Part of this reconnection process causes the local image to be updated with all changes from the repository, which could even include objects that were changed by that session (with no conflict). Transactions may even span image saves. You may start an image, connect to a Magma repository, begin a transaction, make some changes, save and exit the image (not yet having committed), reboot the image later (objects in the image are brought up to date with changes by other sessions), continue any further changes, and finally commit successfully.

When a MagmaSession encounters a real commit-conflict, a MagmaCommitError is signaled. This error understands a message to give the details of the failure, #result. The answer of #result is a MaFailedCommitResult, which can answer a collection of #commitConflicts, a collection of MagmaCommitConflicts, each detailing the conflicting object and who changed it.