Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move db request (which uses yield) in an other function?

I'm playing with tornado and mongodb, with the asynchronous driver motor. When working with callbacks everything's fine. Then I discovered the possibility to use motor.Op or tornado.gen.Task to perform a request in one function only:

So this is working:

class Contact_handler(Main_handler):

    @web.asynchronous
    @gen.coroutine
    def get(self, other_id):

        event = events.Event_send_contact_request(self.user_id)
        result = yield motor.Op(db.users.update,
                     {'_id': ObjectId(other_id)},
                     {'$push': {'evts': event.data}}
                    )

        self.finish("ok")

But I'd like to move this database request in its own function in another module. The problem is that I don't understand really how the yield is working here (despite I read a LOT of questions about yield). So this is what I tried, but it's not working:

#------ file views.py -------------

class Contact_handler(Main_handler):

    def get(self, other_id):

        event = events.Event_send_contact_request(self.user_id)
        result = model.push_event_to_user(other_id, event)

        self.finish("ok")

And the call in another function:

#------ file model.py -------------

@gen.coroutine
def push_event_to_user(user_id, event):

    ## Ajout de la demande dans les events du demandé:
    yield motor.Op(db.users.update,
                     {'_id': ObjectId(user_id)},
                     {'$push': {'evts': event}}
                    )

If I investigate with pdb:

(Pdb) l
157             event = events.Event_send_contact_request(self.user_id)
158             result = model.push_event_to_user(other_id, event)
159             
160             import pdb; pdb.set_trace()
161             
162  ->         self.finish("ok")
163         

(Pdb) result
<tornado.concurrent.TracebackFuture object at 0xa334b8c>
(Pdb) result.result()
*** Exception: DummyFuture does not support blocking for results

Any help appreciated, thanks.

like image 274
ybycode Avatar asked Oct 05 '22 05:10

ybycode


1 Answers

I found another way of doing this, thanks to this post that uses of tornado.gen.Return. I still need to yield in my main function, but the coroutine is simple.

Here is my code now:

#------ file views.py -------------

@web.asynchronous
@gen.coroutine
class Contact_handler(Main_handler):

    def get(self, other_id):

        event = events.Event_send_contact_request(self.user_id)
        result = yield model.push_event_to_user(other_id, event)

        self.finish("ok")

And the call in another function:

#------ file model.py -------------

@gen.coroutine
def push_event_to_user(user_id, event):

    ## Ajout de la demande dans les events du demandé:
    result = yield motor.Op(db.users.update,
                            {'_id': ObjectId(user_id)},
                            {'$push': {'evts': event}}
                           )
    raise gen.Return(result)
like image 135
ybycode Avatar answered Oct 13 '22 10:10

ybycode