Re: Return value from CallMethod, default callback

2009-01-08 Thread Alan Kligman

That's one way to do it. You can do one better( without threading,
that is ) like this, though:

def call( method, request ):
class callbackClass( object ):
def __init__( self ):
self.response = None
def __call__( self, response ):
self.response = response
controller = Controller()
callback = callbackClass()
method( controller, request, callback )
return callback.response

In this case, we're only using one thread and hiding the control flow
inside a class that behaves like a function, where we can retrieve the
return value later and actually return it.

alan

On Jan 8, 2:46 am, Pavel Shramov shra...@mexmat.net wrote:
 On Wed, Jan 07, 2009 at 06:23:31PM -0800, Alan Kligman wrote:

  I poked around a bit and the code above isn't correct (for a couple of
  reasons). But the question remains: should stubs be generated that
  return the response down the callstack instead of passing it through a
  callback function?

 You may use simple wrapper around RpcChannel object (see attachment) so
 all calls are synchronous and behave just like any other python
 function.
 Pavel

  sync.py
 1KViewDownload
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en
-~--~~~~--~~--~--~---



Re: Return value from CallMethod, default callback

2009-01-08 Thread Alan Kligman

That's right. This will only work in code that runs synchronously. If
your program is written to be asynchronous then you will need to pass
a callback, so you wouldn't use this at all.

That's why I brought this up in the first place. If the channel can
tell, based on the callback it receives, where to pass the return
value, then that is more useful and safe.

On Jan 8, 3:48 pm, Pavel Shramov shra...@mexmat.net wrote:
 On Thu, Jan 08, 2009 at 10:00:35AM -0800, Alan Kligman wrote:
  That's one way to do it. You can do one better( without threading,
  that is ) like this, though:

 It's not better but 'looks more simple'. From threading only Condition is
 used which is very cheap compared to network interaction. Your code only
 works for synchronous cases. My first variants looks like Yours.

  def call( method, request ):
  class callbackClass( object ):
  def __init__( self ):
  self.response = None
  def __call__( self, response ):
  self.response = response
  controller = Controller()
  callback = callbackClass()
  method( controller, request, callback )
  return callback.response

  In this case, we're only using one thread and hiding the control flow
  inside a class that behaves like a function, where we can retrieve the
  return value later and actually return it.

 So You must every time check that channel implementation is synchronous.
 And code became unportable to async channels.
 Pavel
--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en
-~--~~~~--~~--~--~---



Re: Return value from CallMethod, default callback

2009-01-07 Thread Kenton Varda
I believe there was a proposal internally that if the caller passes None for
the callback, the RPC implementation should block until completion and then
return the result.  Does that seem like what you want?

On Wed, Jan 7, 2009 at 6:23 PM, Alan Kligman alan.klig...@gmail.com wrote:


 I poked around a bit and the code above isn't correct (for a couple of
 reasons). But the question remains: should stubs be generated that
 return the response down the callstack instead of passing it through a
 callback function?

 On Jan 7, 5:59 pm, Alan Kligman alan.klig...@gmail.com wrote:
  Does it make sense to change
 
  stub.rpc_channel.CallMethod(
  method_descriptor, rpc_controller, request,
  method_descriptor.output_type._concrete_class, callback)
 
  to
 
  return stub.rpc_channel.CallMethod(
  method_descriptor, rpc_controller, request,
  method_descriptor.output_type._concrete_class, callback=lambda
  x:None)
  in python/google/protobuf/service_reflection.py?
 
  If, for example, I'm running in a single thread and my underlying
  channel is blocking, it's strange to pass a callback in when control
  would normally return to the calling method after CallMethod has
  completed synchronously.
 
  Thoughts?
 
  a
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en
-~--~~~~--~~--~--~---



Re: Return value from CallMethod, default callback

2009-01-07 Thread Kenton Varda
Sounds fine to me, but it's up to Petar (cc'd).

On Wed, Jan 7, 2009 at 7:04 PM, Alan Kligman alan.klig...@gmail.com wrote:


 Ya, that's exactly what I'm experimenting with now and precisely what
 I'm looking for. Would be perfect if the callback had a default value
 of None too.

 a

 On Jan 7, 10:02 pm, Kenton Varda ken...@google.com wrote:
  I believe there was a proposal internally that if the caller passes None
 for
  the callback, the RPC implementation should block until completion and
 then
  return the result.  Does that seem like what you want?
 
  On Wed, Jan 7, 2009 at 6:23 PM, Alan Kligman alan.klig...@gmail.com
 wrote:
 
   I poked around a bit and the code above isn't correct (for a couple of
   reasons). But the question remains: should stubs be generated that
   return the response down the callstack instead of passing it through a
   callback function?
 
   On Jan 7, 5:59 pm, Alan Kligman alan.klig...@gmail.com wrote:
Does it make sense to change
 
stub.rpc_channel.CallMethod(
method_descriptor, rpc_controller, request,
method_descriptor.output_type._concrete_class, callback)
 
to
 
return stub.rpc_channel.CallMethod(
method_descriptor, rpc_controller, request,
method_descriptor.output_type._concrete_class,
 callback=lambda
x:None)
in python/google/protobuf/service_reflection.py?
 
If, for example, I'm running in a single thread and my underlying
channel is blocking, it's strange to pass a callback in when control
would normally return to the calling method after CallMethod has
completed synchronously.
 
Thoughts?
 
a
 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en
-~--~~~~--~~--~--~---



Re: Return value from CallMethod, default callback

2009-01-07 Thread Pavel Shramov
On Wed, Jan 07, 2009 at 06:23:31PM -0800, Alan Kligman wrote:
 
 I poked around a bit and the code above isn't correct (for a couple of
 reasons). But the question remains: should stubs be generated that
 return the response down the callstack instead of passing it through a
 callback function?
You may use simple wrapper around RpcChannel object (see attachment) so
all calls are synchronous and behave just like any other python
function.
Pavel

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
Protocol Buffers group.
To post to this group, send email to protobuf@googlegroups.com
To unsubscribe from this group, send email to 
protobuf+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en
-~--~~~~--~~--~--~---

#!/usr/bin/env python
# vim: sts=4 sw=4 et

import threading

class _sync_cb:

Synchronization callback

def __init__(self):
self.c = threading.Condition()

def __call__(self, x): 
self.c.acquire()
self.r = x
self.c.notify()
self.c.release()

def rpc_sync(method):

Make method synchronous by providing synchronization callback

def nm(*args):
cb = _sync_cb()
method(*(args + (cb,)))
cb.c.acquire()
while not hasattr(cb, 'r'):
cb.c.wait()
cb.c.release()

return cb.r
return nm

class RPCSync(object):
 
Wrapper around RpcChannel object that changes default behaviour 
from asynchronous to synchronous. Controller class is provided
once on wrapper creation so typical RPC call looks like.
 response = wrapper.method(request)
On error RuntimeError exception containing ctrl.ErrorText() is raised

def __init__(self, stub, ctrl_class):
self.ctrl_class = ctrl_class
self.stub = stub
for m in self.stub.GetDescriptor().methods:
self.__setattr__(m.name, self._func(m.name))

def _call(self, method, *args, **kwargs):
ctrl = self.ctrl_class()
result = rpc_sync(getattr(self.stub, method))(ctrl, *args, **kwargs)
if ctrl.Failed():
raise RuntimeError(ctrl.ErrorText())
return result

def _func(self, method):
def f(*args, **kwargs):
return self._call(method, *args, **kwargs)
f.__name__ = method
return f