Help! RPC / Call / Deferred not playing ball ...

#1

Hi, I don’t know if it’s the heat, but I just can’t seem to see what I’m doing wrong - if anyone has any pointers the would be most welcome … simple bit of code, something to allow me to hold volatile per-session meta-data;

@wamp.register(u'ionman.session.get')
def session_get(self, sid):
    return self.sessions.get(sid, None)

``

@defer.inlineCallbacks
def getSessionDeferred(self, session_id):
    """Handle a deferred call to get the session details."""
    session = yield self.server.call(u'ionman.session.get', session_id)
    uid = ObjectId(session.get('uid', None))
    user = self.db.users.find_one({'_id': uid})
    log.msg("User1=",user)
    defer.returnValue(user)

def getSession(self, details):
    """Read a user record based on caller details."""
    user = self.getSessionDeferred(details.caller)
    log.msg("User2=",user)
    return user

``

User1= displays the correct / expected information [so the background code works]

User2= displays <Deferred at 0x4a7e8e0>

Essentially getSessionDeferred is returning a “deferred” object, rather than the value it “should” be passing back via “returnValue”.

… it’s like “returnValue” isn’t actually waiting …

I’m expecting user1 and user2 to display the same information … I’m obviously doing something really dumb … but for some reason I can’t seem to see it …

Any ideas?

0 Likes

#2

Ok, I’m not going to pretend I know why, but it seems that if the deferred call is in the top level of an @wamp.register, it will execute correctly “in-line”, but if it’s called from a function, the resulting return is a “deferred” rather than the result of the deferred. I’d love an explanation if anyone has one … in the meantime I’ve rejigged my code slightly from;

@wamp.register(u'nac.rpc.request.clone')
def nac_rpc_request_clone(self, argv, details):
    user = self.getSession(details)
    if not user: return self.fail('no such user')

``

Which as failing, because “user” was coming back as a deferred object to;

@wamp.register(u'nac.rpc.request.clone')
@rpc_function
def nac_rpc_request_clone(self, argv, session=None, user=None):
    ....

``

With the following decorator … I’m quite happy with the solution (in fact I prefer it), but I’d love to understand why I need it … ???

def rpc_function(f):
“”“Generic RPC function call wrapper.”""
@inlineCallbacks
def function(*args, **kwargs):
try:
session = yield args[0].server.call(u’ionman.session.get’, kwargs[‘details’].caller)
user = args[0].db.users.find_one({’_id’: ObjectId(session.get(‘uid’, None))})
if not user:
returnValue((‘FAIL’,‘unable to resolve user’))
returnValue(f(*args, **{‘session’: session, ‘user’: user}))
except Exception, e:
log.err()
returnValue((‘FAIL’,e.message))

return function    

``

0 Likes

#3

Ok, trying again … this returns a deferred object - can anyone tell me why?

@wamp.register(u’my.topic’)
@inlineCallbacks
def my_topic(self, argv, details):
result = yield session.call(u’another.random.topic’)
returnValue(result)

``

If I add the following decorator between @wamp and @inline, it works fine …

def rpc_callback(f):
“”“RPC inlineCallback Shim.”""
@inlineCallbacks
def function(*args, **kwargs):
ret = f(*args, **kwargs)
if isinstance(ret,Deferred):
result = yield DeferredList([ret])
ret = result[0][1]
returnValue(ret)
return function

@wamp.register(u’my.topic’)
@rpc_callback
@inlineCallbacks
def my_topic(self, argv, details):
result = yield session.call(u’another.random.topic’)
returnValue(result)

``

I can live with this solution, but it feels like I’m doing something wrong … I’m vaguely expecting the first code fragment to return the value from the call, as opposed to a Deferred … ??

0 Likes