transactions on pharo objects

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

transactions on pharo objects

Peter Uhnák
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Esteban A. Maringolo
I think it is a tricky thing to do "in memory transactions", even
without thinking about databases.
You have to define what to keep and where to place the "original"
values (inst. vars.) of the object.

As a general purpose solution if you can do that, you end up
implementing a mini gemstone in Pharo :)

But what's sure is that you should have a mini object-table of the
"touched" objects or do "explicit" registration of these objects like
GLORP allows you to do.

e.g.

| p |
p := Person new.
System transaction: [:tx |
  tx register: p.
  p name: 'Nobody'.
  p age: 70.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

I'm using System here, to make it compatible with GemStone.
#transaction: could be implemented in terms of #beginTransaction,
#commitTransaction and internally use #abortTransaction if an
unhandled Error is signalled.

Regards!

Esteban A. Maringolo
El lun., 30 jul. 2018 a las 10:17, Peter Uhnák (<[hidden email]>) escribió:

>
> Hi,
>
> is there some library or approach how to do transactions in pharo?
> And I don't mean database transactions, but directly in memory on Pharo objects... e.g.
>
> p := Person new.
>
> transaction do: [
>     p name: 'Nobody'.
>     p age: 70.
> ] on: Error do: [
>     transaction rollback.
> ].
>
> self assert: p name equals: 'Nobody'.
> self assert: p age equals: 70.
>
> transaction do: [
>     p name: 'Somebody'.
>     p age: 1 / 0.
> ] on: Error do: [
>     transaction rollback.
> ].
>
> self assert: p name equals: 'Nobody'.
> self assert: p age equals: 70.
>
> Any pointers appreciated.
>
> Thanks,
> Peter

Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

SergeStinckwich
In reply to this post by Peter Uhnák

On Mon, Jul 30, 2018 at 2:17 PM Peter Uhnák <[hidden email]> wrote:
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter


--
Serge Stinckwich
UMI UMMISCO 209 (SU/IRD/UY1)
"Programs must be written for people to read, and only incidentally for machines to execute."
http://www.doesnotunderstand.org/
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Sean P. DeNigris
Administrator
In reply to this post by Peter Uhnák
Peter Uhnák wrote
> is there some library or approach how to do transactions… directly in
> memory on Pharo
> objects

Magritte? It uses the Memento pattern to verify all changes before
committing to real object.



-----
Cheers,
Sean
--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Cheers,
Sean
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Esteban A. Maringolo
El lun., 30 jul. 2018 a las 11:03, Sean P. DeNigris
(<[hidden email]>) escribió:
>
> Peter Uhnák wrote
> > is there some library or approach how to do transactions… directly in
> > memory on Pharo
> > objects
>
> Magritte? It uses the Memento pattern to verify all changes before
> committing to real object.

But you need Magritte, and define descriptions, and references, and
access the objects via Magritte Accessors, etc.
I think that works for an UI of a somehow limited form, but not as a
general purpose (as I guess Peter is looking for).

Also for forms, but without metadata, Dolphin used a "BufferedModel"
object, which means that if you have an MVP/MVC, instead of using your
original model, you work on this "buffer", which internally has the
original and a copy, and all messages are sent to the copy and once
you "apply" the changes they are applied back to the original model,
and if you don't apply, the copy is discarded and the original model
left unmodified.

But again, I guess Peter is looking for something else.

Regards!

Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Richard O'Keefe
In reply to this post by Peter Uhnák
Basically, what you are talking about is Software Transactional Memory.
there *is* STM support for Pharo at
although the last version there is from 2012, and there have been major changes to Pharo
since then, so it probably doesn't work any longer.

You could probably make a TransactionalObject class with a 'lastTransaction'
instance variable, and a noteChange method that checks if lastTransaction ==
Transaction current, and if not, pushes self -> self shallowCopy onto a stack
inside Transaction and sets lastTransaction to Transaction current.  Then to
roll back a transaction, peel back original -> backup records from the stack
and do original copyFrom: backup for each of them.

Please don't ask me to think about combining this with concurrency.

On 31 July 2018 at 01:16, Peter Uhnák <[hidden email]> wrote:
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter

Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

NorbertHartl
In reply to this post by Peter Uhnák


Am 30.07.2018 um 15:16 schrieb Peter Uhnák <[hidden email]>:

Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Should this work image wide or per process? 

Norbert
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

NorbertHartl
In reply to this post by Sean P. DeNigris


> Am 30.07.2018 um 16:02 schrieb Sean P. DeNigris <[hidden email]>:
>
> Peter Uhnák wrote
>> is there some library or approach how to do transactions… directly in
>> memory on Pharo
>> objects
>
> Magritte? It uses the Memento pattern to verify all changes before
> committing to real object.
>
This only works for simple use cases where there is one flow that creates the memento and keeps it like in a web form. The problem with the memento is that it is hard to make all objects give a memento when they are aquired.

Norbert
>
> -----
> Cheers,
> Sean
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>


Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

NorbertHartl
In reply to this post by Richard O'Keefe


Am 31.07.2018 um 06:57 schrieb Richard O'Keefe <[hidden email]>:

Basically, what you are talking about is Software Transactional Memory.
there *is* STM support for Pharo at
although the last version there is from 2012, and there have been major changes to Pharo
since then, so it probably doesn't work any longer.

You could probably make a TransactionalObject class with a 'lastTransaction'
instance variable, and a noteChange method that checks if lastTransaction ==
Transaction current, and if not, pushes self -> self shallowCopy onto a stack
inside Transaction and sets lastTransaction to Transaction current.  Then to
roll back a transaction, peel back original -> backup records from the stack
and do original copyFrom: backup for each of them.

Please don't ask me to think about combining this with concurrency.

You could delegate the transaction list and other objects to a process specific variable. But the biggest problem with a copy approach is that all identity checks fail with the copied objects

Norbert
On 31 July 2018 at 01:16, Peter Uhnák <[hidden email]> wrote:
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter

Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

tesonep@gmail.com
Hello, 
  A lot of time ago, we have implemented a basic support for STM in Java (it is written in Scala... dark dark dark ages). We have used aspect oriented programming to intercept the reading and writing of the instance variables of the classes that support the transactions.
We kept a dictionary with the values for the transactions in course and a version, and the original object has the "commited" values. On a commit you can apply the changes to the object iff there is no conflict version.

I think a similar implementation could be done in Pharo using Slots in a couple of hours. Also, you should use process specific values to detect and handle in witch transaction you are.
Depending how much you want to guarantee ACID properties, you will have simpler or complex implementation. In those days, we only wanted only isolation.

Sadly, the details of the implementation are in a Master Thesis in Spanish, I doubt they will be useful, but still I can point you to the source code of the solution. 
By the way, this is still in use as a part of a tool to teach UI design.


Cheers,
Pablo

On Tue, Jul 31, 2018 at 8:48 AM Norbert Hartl <[hidden email]> wrote:


Am 31.07.2018 um 06:57 schrieb Richard O'Keefe <[hidden email]>:

Basically, what you are talking about is Software Transactional Memory.
there *is* STM support for Pharo at
although the last version there is from 2012, and there have been major changes to Pharo
since then, so it probably doesn't work any longer.

You could probably make a TransactionalObject class with a 'lastTransaction'
instance variable, and a noteChange method that checks if lastTransaction ==
Transaction current, and if not, pushes self -> self shallowCopy onto a stack
inside Transaction and sets lastTransaction to Transaction current.  Then to
roll back a transaction, peel back original -> backup records from the stack
and do original copyFrom: backup for each of them.

Please don't ask me to think about combining this with concurrency.

You could delegate the transaction list and other objects to a process specific variable. But the biggest problem with a copy approach is that all identity checks fail with the copied objects

Norbert
On 31 July 2018 at 01:16, Peter Uhnák <[hidden email]> wrote:
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter



--
Pablo Tesone.
[hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Richard O'Keefe
In reply to this post by NorbertHartl
Norbert Hartl wrote:
 the biggest problem with a copy approach is that all identity checks fail with the copied objects

The scheme I proposed *hides* the (shallow) copies.  The only thing ever done with them is
to copy their contents back into the original objects.  There are therefore no "identity checks
... with the copied objects" for anyone to care about.

On 31 July 2018 at 18:47, Norbert Hartl <[hidden email]> wrote:


Am 31.07.2018 um 06:57 schrieb Richard O'Keefe <[hidden email]>:

Basically, what you are talking about is Software Transactional Memory.
there *is* STM support for Pharo at
although the last version there is from 2012, and there have been major changes to Pharo
since then, so it probably doesn't work any longer.

You could probably make a TransactionalObject class with a 'lastTransaction'
instance variable, and a noteChange method that checks if lastTransaction ==
Transaction current, and if not, pushes self -> self shallowCopy onto a stack
inside Transaction and sets lastTransaction to Transaction current.  Then to
roll back a transaction, peel back original -> backup records from the stack
and do original copyFrom: backup for each of them.

Please don't ask me to think about combining this with concurrency.

You could delegate the transaction list and other objects to a process specific variable. But the biggest problem with a copy approach is that all identity checks fail with the copied objects

Norbert
On 31 July 2018 at 01:16, Peter Uhnák <[hidden email]> wrote:
Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter


Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Richard Sargent
Administrator
In reply to this post by Esteban A. Maringolo
Esteban A. Maringolo wrote

> I think it is a tricky thing to do "in memory transactions", even
> without thinking about databases.
> You have to define what to keep and where to place the "original"
> values (inst. vars.) of the object.
>
> As a general purpose solution if you can do that, you end up
> implementing a mini gemstone in Pharo :)
>
> But what's sure is that you should have a mini object-table of the
> "touched" objects or do "explicit" registration of these objects like
> GLORP allows you to do.
>
> e.g.
>
> | p |
> p := Person new.
> System transaction: [:tx |
>   tx register: p.
>   p name: 'Nobody'.
>   p age: 70.
> ].

It seems to me that the fundamental problem with the idea of registering
each object with the transaction (or anything else) is that it requires
white-box knowledge of what every invoked behaviour will do and touch. The
above example is so minimal, it looks easy.

I think if you really want transactional Smalltalk, you need to use one
designed expressly for that purpose.
(And fortunately, there is one.)



> self assert: p name equals: 'Nobody'.
> self assert: p age equals: 70.
>
> I'm using System here, to make it compatible with GemStone.
> #transaction: could be implemented in terms of #beginTransaction,
> #commitTransaction and internally use #abortTransaction if an
> unhandled Error is signalled.
>
> Regards!
>
> Esteban A. Maringolo
> El lun., 30 jul. 2018 a las 10:17, Peter Uhnák (&lt;

> i.uhnak@

> &gt;) escribió:
>>
>> Hi,
>>
>> is there some library or approach how to do transactions in pharo?
>> And I don't mean database transactions, but directly in memory on Pharo
>> objects... e.g.
>>
>> p := Person new.
>>
>> transaction do: [
>>     p name: 'Nobody'.
>>     p age: 70.
>> ] on: Error do: [
>>     transaction rollback.
>> ].
>>
>> self assert: p name equals: 'Nobody'.
>> self assert: p age equals: 70.
>>
>> transaction do: [
>>     p name: 'Somebody'.
>>     p age: 1 / 0.
>> ] on: Error do: [
>>     transaction rollback.
>> ].
>>
>> self assert: p name equals: 'Nobody'.
>> self assert: p age equals: 70.
>>
>> Any pointers appreciated.
>>
>> Thanks,
>> Peter





--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Esteban A. Maringolo


El mié., 1 de ago. de 2018 20:52, Richard Sargent <[hidden email]> escribió:
Esteban A. Maringolo wrote
> As a general purpose solution if you can do that, you end up
> implementing a mini gemstone in Pharo :)
>
> But what's sure is that you should have a mini object-table of the
> "touched" objects or do "explicit" registration of these objects like
> GLORP allows you to do.


It seems to me that the fundamental problem with the idea of registering
each object with the transaction (or anything else) is that it requires
white-box knowledge of what every invoked behaviour will do and touch. The
above example is so minimal, it looks easy.

I agree with that. Deciding when to what to copy and what to preserve is always tricky unless yo decide to copy the whole object graph which would be terrible. Very much like what to proxy and what to forward in GemBuilder.

I think if you really want transactional Smalltalk, you need to use one
designed expressly for that purpose.
(And fortunately, there is one.)

That's why I say this is tricky and you'll probably end up implementing a mini-GemStone.

I don't know what it means in terms of programming, but having a transactional object memory would be a useful thing to work with. 

Regards,

Esteban.
Reply | Threaded
Open this post in threaded view
|

Re: transactions on pharo objects

Carlo-2
In reply to this post by Peter Uhnák
Hi

This research from VPRI may be useful: Worlds: Controlling the Scope of Side Effects and Experiments with Worlds (Alessandro Warth, Yoshiki Ohshima, Ted Kaehler, and Alan Kay)
They had a JS and Squeak version running which can be found at http://www.tinlizzie.org/~awarth/worlds/

Regards
Carlo

On 30 Jul 2018, at 15:16, Peter Uhnák <[hidden email]> wrote:

Hi,

is there some library or approach how to do transactions in pharo?
And I don't mean database transactions, but directly in memory on Pharo objects... e.g.

p := Person new.

transaction do: [
    p name: 'Nobody'.
    p age: 70.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

transaction do: [
    p name: 'Somebody'.
    p age: 1 / 0.
] on: Error do: [
    transaction rollback.
].

self assert: p name equals: 'Nobody'.
self assert: p age equals: 70.

Any pointers appreciated.

Thanks,
Peter