AjSharp distribuido: Primeros pasos

Published on Author lopez2 Comments

Fue un gran fin de semana, con code kata. En la tarde del sábado, comencé a jugar con serialización de comandos en mi intérprete AjSharp:

En ese momento estaba usando Windows Communication Foundation, con simple BasicHttpBindind y address. Elegí serializar comandos y expresiones en arreglos de bytes, usando BinaryFormatter, y enviarlos via WCF básico (No me gusta pelearme con serialización WCF).

Entonces, el domungi, escribí una implementación usando remoting. Es una mejor aproximación a esta situación: remoting me de soporte “out-of-the.box” para serialización de grafos de objetos, y el manejo de MarshalByRefObject, lo que es bueno para mi proyecto.

Mis primeros intentos usando remoting:

Noten el uso de las nuevas keywords expression y command. En este comando:

a = expression b+c;

se asigna una expresión b+c (pendiente de evaluación) a una variable local a. Podemos evaluarla con:

result = a.Evaluate(Machine.Environment);

(Machine es la máquina actual en ejecución, tiene un .Environment global, donde están los bindings para b y c, sus valores asociados).

El comando:

a = command PrintLine(“Hello, world”);

no imprime un mensaje. Almacena el comando en una variable local, para ser ejecutado más adelante como:

a.Execute(Machine.Environment);

En el ejemplo de arriba, podemos arrancar a un servidor programáticamente. Podemos también crear el objeto proxy a ese servidor en el cliente. Y entonces, podemos invocar comandos, o evaluar expressiones, en el otro servidor. Después de tener eso andando, agregué el llamado de funciones, pasando argumentos al servidor. Esta es la principal interface que fue surgiendo, IHost:

    public interface IHost
    {
        // Host Id
        Guid Id { get; }
        // Host Invocation
        void Execute(ICommand command);
        object Evaluate(IExpression expression);
        object Invoke(ICallable function, params object[] arguments);
        // Others... Work in progress... to review
    }

Un host se ejecuta en una máquina, y expone el acceso a esa máquina, con invocaciones de comandos, funciones y evaluaciones de expresiones. Hay host que son locales (class Host), y hosts que exponen su funcionalidad via remoting (RemotingHostServer), y que se consumen desde su correspondiente cliente proxy (RemotingHostClient). Estoy también trabajando en tener esas clases en WCF: hay un WcfHostServer, WcfHostClient, pero tengo que luchar con temas de serialización, todavía.

Debería agregar el pasar strings conteniendo commandos y expresiones, y que el servidor receptor los parsee y ejecute/evalúe (sería más fácil que enviar lo que estoy enviando ahora, el ICommand, IExpression ya armado).

Después de las pruebas exitosas de arriba, agregué “syntax sugar”: no hay que minimizar el efecto de una buena sintaxis, que puede simplificar el uso de una característica. Agregué la keyword at en AjSharp:

Podemos invocar un comando en el otro server usando:

at <host> <command>;

o podemos evaluar una expresión en otro servidor y devolver el resultado:

localvar = at <host> <expression>;

Tengo que trabajar más en algunos detalles de serialización. Resolví parte del callback al servidor. Esto es:

at host { adam = new DynamicObject(); adam.Name = “Adam”; adam.Age = 800; }

myadam = at host adam;

adam se crea en el host remoto. La variable local myadam, cuando uso remoting, es en realidad un transparent proxy que apunta al DynamicObject que todavía está en el host donde fue creado (hasta ahora, los DynamicObject los he puesto descendiendo de MarshalByRefObject; estoy pensando cambiar esta decisión, y hacer que se serializen por defecto, y agregar un método, tipo obj.AsProxy() para generar una referencia MarshalByRefObject explícitamente cuando el programador así lo solicite). Pero el transparent proxy que recibo no puede ser invocado directamente: no tiene un canal asociado de comunicación. Así que agregué un wrapper a ese objeto cuando lo recibo en el cliente. Si invocamos algo de myadam, como en:

PrintLine(myadam.Name);

myadam.Name = “NewAdam”;

el wrapper redirecciona todo a que se ejecute en el servidor que fue invocado, y la operación se ejecuta en el servidor.

Como siempre, pueden bajar y examinar el código desde:

http://code.google.com/p/ajcodekatas/source/browse/

en el directorio trunk/AjLanguage.

Tengo que confesar que estoy orgulloso de este avance en mi intérprete. Podría extender, llegado el caso, esta capacidad para otros intérpretes, como AjIo,, AjTalk (era la idea inicial de AjTalk, tener un Smalltalk-like VM con objetos distribuidos). Nació sólo como una idea, pero va tomando forma, un lenguaje distribuido es el camino a explorar para poder aprovechar más máquinas en algunas tareas. El proyecto es un bebé todavía, pero es mi bebé, y me divierte mucho codificarlo.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Leave a Reply

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