asynchronous - Tornado async decorators where one depends on another -
i'm trying head around tornado. i'm writing chat application backed mongodb , i'm using motor
non-blocking access it.
what i'm trying achieve is:
- create decorator uses
motor
asynchronously pull user's record mongo - validate credentials (username & token)
- create decorator checks user_id retrieved in 1. above permitted access chat room. requires asynchronous call mongo
motor
retrieve 'chatroom' record. - subscribe chat room if ok
i have decorator 1. working (basically taken http://tornadogists.org/5251927/):
def authenticated_async(f): @functools.wraps(f) @gen.engine def wrapper(self, *args, **kwargs): self.current_user = yield gen.task(self.get_current_user_async) if self.current_user: logging.info("user '%s' (%s) authenticated" % (self.current_user['username'], self.current_user['_id'])) f(self, *args, **kwargs) else: raise tornado.web.httperror(401, "user not authenticated, " "aborting") return wrapper
the trouble second decorator, need access self.current_user
. because set in asynchronous callback, it's not available when validation
decorator (i.e validation decorator called before auth decorator completes).
is not possible me use decorators in way asynchronous functions? need call validation method inside above method after making sure self.current_user
true it's more callback?
i'd ideally have methods in handler wrapped both of these decorators can reuse them elsewhere, i.e.:
class chatsockethandler(tornado.websocket.websockethandler): @gen.coroutine @validate_invitation_access_async @authenticated_async def open(self, invitation_id): # stuff here...
update in fact, there no dependency. user_id provided parameter, , used run both decorators in parallel - 1 confirm authentication, other see whether user id allowed access room. open()
method proceed if self.auth_check == true , self.room_check == true
.
could open()
ever called before async decorators complete though?
you need switch order of decorators validate_invitation_access_async
wrapper has access current_user:
@authenticated_async @validate_invitation_access_async def open(self, invitation_id): # stuff here...
then wrapper inside validate_invitation_access_async
"f" in authenticated_async
: it's called after self.current_user set. note don't need additional gen.engine
decorator, wrappers engines. wrapper like:
def validate_invitation_access_async(f): @gen.engine def wrapper(self, *args, **kwargs): # ... use motor see if user authorized ... # if not, log , redirect. otherwise: f(self, *args, **kwargs)
you should update code use tornado 3's gen.coroutine instead of gen.engine: it's cleaner. leave exercise.
Comments
Post a Comment