Version française
Home     About     Download     Resources     Contact us    
Browse thread
hydro: is server-to-server call possible?
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Gerd Stolpmann <gerd@g...>
Subject: Re: hydro: is server-to-server call possible?

Am Donnerstag, den 09.04.2009, 14:42 +0400 schrieb Vsevolod Fedorov:
> Hello!
> 
> I use Hydro implementation of the Ice protocol and stumbled upon the
> following problem:
> I need one server to make calls to another one. But I can not make a
> synchronous call because I am already inside the event loop. And I can
> not make asynchronous call because asynchronous servants seem to be
> unsupported.
> So here the question: can I do this at all? And if yes, then how?

Of course you can.

First, you can always make a synchronous call. Just create a new event
system with Unixqueue.create_unix_event_system, and throw it away after
the call is over. Of course, your server is blocked during this time.

Asynchronous servants are supported (maybe undocumented :-) ). In fact,
all servants are async, and only the "parachute" enforces a synchronous
behavior. parachute is defined by the generator like

let rec parachute =
  (fun userfn ->
    (fun emit_result -> 
      (fun emit_exn -> 
        (fun session -> 
          try ( emit_result (userfn session) )
          with
            | User_exception e -> emit_exn e
            | g -> 
                session # emit_unknown_exception
                  (Hydro_util.exn_to_string g)
        )
      )
    )
  )

(I've substituted readable variable names.)

Now, a synchronous method definition looks like:

method foo arg1 arg2 ... argN =
  parachute
    (fun session ->
        ...
        result
    )

As you see from its definition, parachute "eats up" three more arguments
and hides them from the user. You could also write

method foo arg1 arg2 ... argN emit_result emit_exn session =
  try 
    let result = ... in
    emit_result result
  with
   | User_exception e -> emit_exn e
   | g -> 
        session # emit_unknown_exception (Hydro_util.exn_to_string g)

I hope it becomes now clear how to make the method async. Just don't
call emit_result/emit_exn immediately, but later when you have the
result (or exception). Bypass parachute, whose task is to ensure that
emit_result/emit_exn is immediately called.

Gerd
-- 
------------------------------------------------------------
Gerd Stolpmann * Viktoriastr. 45 * 64293 Darmstadt * Germany 
gerd@gerd-stolpmann.de          http://www.gerd-stolpmann.de
Phone: +49-6151-153855                  Fax: +49-6151-997714
------------------------------------------------------------