Drb / ActiveRecord as Application Server for Qt/Ruby client

Pau Garcia i Quiles wrote:

Quoting Adam Keys <adam@therealadam.com>:

I prefer a 3-tier approach, with all the buisness logic on the
server, just like you would do with J2EE. Centralisation of code is
a good thing I think.

You're already using ActiveRecord..why not throw the rest of the
Rails stack in and use REST, XML-RPC or SOAP?

The problem with QtRuby and DRb, XML-RPC, EventMachine, etc
is each one of them has its own event loop.

Once you call $qapp.exec in QtRuby, you application enters
the Qt event loop and you cannot call anything outside that
loop. The same goes for XMLRPC4R and the server.serve call:
once you call myserver.serve, your application waits in an
event loop, so you cannot run $qapp.exec because QtRuby does
not work with Ruby threads. The only approach you can take to "fix"
this is described here:
http://rubyforge.org/forum/message.php?msg_id=3329

The explanation is here:
http://rubyforge.org/forum/message.php?msg_id=3341

But you should realize this is more of an accident than a feature.

The best solution for this problem is to implement your own
protocol using QtRuby. If your QtRuby application is actually
a Korundum application, another approach would be to have two
independent applications (the Korundum app and the
XML-RPC/EventMachine/whatever
listener) and have them communicate through DCOP. If your
application is a QtRuby 4 one, you may use DBUS as well but
take in account the Ruby-DBUS bindings are quite old.

Hi,

My initial idea was to use Qt on the client only, where no server process is listening at all. When opening windows, reponding to user activity in general, I thought it would be possible to call the Drb Server, and get an ActiveRecord object, very simply, and then populate the Qt controls with the data found in the marshalled object.

require 'drb'
DRb.start_service()
obj = DRbObject.new(nil, 'druby://localhost:9000')
puts obj.getflowers

I haven't had the time to test that, so I miss a point maybe, but I don't see exactly how your explanation applies in this context...

···

On Aug 4, 2006, at 12:20 PM, Philippe Lang wrote:

---------------
Philippe Lang
Attik System

Philippe Lang wrote:

Pau Garcia i Quiles wrote:

Quoting Adam Keys <adam@therealadam.com>:

I prefer a 3-tier approach, with all the buisness logic on the
server, just like you would do with J2EE. Centralisation of code is
a good thing I think.

You're already using ActiveRecord..why not throw the rest of the
Rails stack in and use REST, XML-RPC or SOAP?

The problem with QtRuby and DRb, XML-RPC, EventMachine, etc
is each one of them has its own event loop.

Once you call $qapp.exec in QtRuby, you application enters
the Qt event loop and you cannot call anything outside that
loop. The same goes for XMLRPC4R and the server.serve call:
once you call myserver.serve, your application waits in an
event loop, so you cannot run $qapp.exec because QtRuby does
not work with Ruby threads. The only approach you can take to "fix"
this is described here:
http://rubyforge.org/forum/message.php?msg_id=3329

The explanation is here:
http://rubyforge.org/forum/message.php?msg_id=3341

But you should realize this is more of an accident than a feature.

The best solution for this problem is to implement your own
protocol using QtRuby. If your QtRuby application is actually
a Korundum application, another approach would be to have two
independent applications (the Korundum app and the
XML-RPC/EventMachine/whatever
listener) and have them communicate through DCOP. If your
application is a QtRuby 4 one, you may use DBUS as well but
take in account the Ruby-DBUS bindings are quite old.

Hi,

My initial idea was to use Qt on the client only, where no server process is listening at all. When opening windows, reponding to user activity in general, I thought it would be possible to call the Drb Server, and get an ActiveRecord object, very simply, and then populate the Qt controls with the data found in the marshalled object.

require 'drb'
DRb.start_service()
obj = DRbObject.new(nil, 'druby://localhost:9000')
puts obj.getflowers

I haven't had the time to test that, so I miss a point maybe, but I don't see exactly how your explanation applies in this context...

---------------
Philippe Lang
Attik System

That general idea will work, and DRb is a good Ruby RPC framework.

However, ActiveRecord expects the database to be locally-available and is quite "chatty" with the database. When DRb sends an instance of an ActiveRecord across the wire, the client unmarshals it and loads the ActiveRecord::Base class, and ActiveRecord::Base tries to initialize its table columns by checking the database schema. This obviously doesn't work so well unless your client has direct access to the database.

You can work around this by adding 'include DRbUndumped' to your ActiveRecord subclasses. This essentially makes DRb send a stub to your client, and then every method invocation is a remote call. That works OK for limited use, but bogs down when your client makes many remote calls.

This is a long way of saying that any moderately-complex remote GUI client will need its own "remote transfer objects". Either SOAP Structs or just your own simple Ruby classes.

I think this presentation (PDF) is a helpful summary:
http://www.vanruby.com/system/files?file=20051025-soap4r-emil_marceta.pdf

Doesn't QTRuby have a way to spawn a callback thread off of the main event loop? Kind of like Swing's invokeLater() or Fox's Timers and Chores? I'd think that you would want to do that for your remote calls.

Scott

···

On Aug 4, 2006, at 12:20 PM, Philippe Lang wrote:

Quoting Scott Willson <scott@butlerpress.com>:

Doesn't QTRuby have a way to spawn a callback thread off of the main
event loop? Kind of like Swing's invokeLater() or Fox's Timers and
Chores? I'd think that you would want to do that for your remote calls.

Qt::Timer. Its behavior is described in Rubyforge-Forum messages I told you in the previous message.