Objetos transaccionales en AjTalk, introducción rápida

Quiero describir hoy un ejemplo corto, mostrando el manejo de objetos transaccionales en AjTalk, mi Smalltalk-like Virtual Machine interpretada escrita en C#.

¿Qué es un objeto transaccional, en este contexto? Es un objeto, que cuando ejecuta dentro de una transacción en memoria, puede manejar los valores de sus variables de instancia, monitoreando sus cambios. Si la transacción se confirma con commit, los nuevos valores del objeto comienzan a ser visibles para el resto del sistema. Si la transacción se rechaza con rollback, los objetos transaccionales afectados por la misma restauran sus valores originales, los valores que tenían al comienzo de la transacción. Nota: estas transacciones son transacciones en memoria, y no están relacionadas con transacciones en bases de datos.

¿Cómo crear un objeto AjTalk transaccional? Agregué un método al protocolo de Object:

Object methods!

asTransactional
    ^@AjTalk.Transactions.TransactionalObject new: self with: (@AjTalk.Machine current transactionManager)
! !

El objeto es “envuelto” por un decorador, un objeto nativo de .NET del tipo TransactionalObject que es el que hace el trabajo de vigilar los valores de las variables de instancias de objeto decorado. Este decorador recibe todas las peticiones de set y get de valores de instancia, y las maneja para la transacción actual, y para cualquier otra transacción que se esté ejecutando en el sistema, que acceda al objeto via el decorador. Pienso escribir un post describiendo la implementación interna. Nota: si una variable de instancia en un objeto transaccional es modificado por dos transacciones, la primera gana, y la segunda falla.

Dada una clase Rectangle:

Object subclass: #Rectangle instanceVariableNames: ‘width height’
!Rectangle methods!
width
    ^width
!
height
    ^height
!
width: newWidth
    width := newWidth
!
height: newHeight
    height := newHeight
! !

Podemos crear una instancia, poner algún valor, y crear un decorador transaccional:

rect := Rectangle new.
rect width: 500!
rect := rect asTransactional
!

Ahora, la variable rect apunta a una instancia que es transaccional. Pero no hay todavía transacción abierta: su conducta, entonces, es como cualquier otro objeto. ¿Cómo abrimos una transacción? La Machine actual tiene una nueva propiedad, que mantiene un objeto TransactionManager:

tm := @AjTalk.Machine current transactionManager.
console := @System.Console out
!

tm beginTransaction!

La instancia rect, que apunta al decorador transaccional, tiene una referencia al objeto decorador, llamado innerObject. Podemos ver sus valores:

console write: ‘rect width is ‘.
console writeLine: rect width!

console write: ‘inner rect width is ‘.
console writeLine: rect innerObject width!

La salida sería:

rect width is 500
inner rect width is 500

Ahora, cambiemos el ancho del objeto transaccional:

rect width: 700!

Si imprimimos de nuevo los valores, como antes, la salida sería:

rect width is 700
inner rect width is 500

Usualmente, se usa la instancia rect (el decorador) desde todos los procesos. Si uno imprime el valor de rect width en otro proceso/thread (que puede tener o no su propia transacción), obtendrá el valor 500. El nuevo valor 700 no está publicado todavía: es solamente visible desde la transacción actual.

Podemos hacer rollback de la transacción:

tm rollbackTransaction!

Los nuevos valores serán:

rect width is 500
inner rect width is 500

Si hubiéramos confirmado la transacción con commitTransacction, el resultado sería:

rect width is 700
inner rect width is 700

Pueden ejecutar un ejemplo, desde el código del trunk actual. Hay un comando RunTransaction.cmd en el proyecto AjTalk.Console.

Próximos pasos: escribir un post describiendo la implementación de estas características; mejorar el manejo transaccional para hacer retry automático de una transacción fallida.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

This entry was posted in 11722, 12677, 1389, 3462, 8870. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>