0

I'm developing with gae and ndb and I find that I have to write a lot of code for ndb gets and queries. Sometimes I need two versions (sometimes 3 or more).

Suppose I have the following Models and functions inside them:

class MainEnt(ndb.Model):
    """Main entity. The parent is the user_key"""
    name = ndb.StringProperty()
    child = ndb.KeyProperty()

    def get_created_by(self, user_id):
        """Get the MainEnt's created by user_id"""
        # stuff... getting the query and returning the results

    def get_created_by_async(self, user_id):
        """Get async the MainEnt's created by user_id"""
        # stuff... getting the query async and returning a future

    @ndb.tasklet
    def get_childs_async_tasklet(self, mainent_key):
        """Get async the childs of a MainEnt"""
        # stuff... yielding the query async. and raise ndb.Return()...

    @ndb.tasklet
    def get_created_by_async_tasklet(self, user_id):
        """Get async the MainEnt's created by user_id"""
        # stuff... yielding the query async. and raise ndb.Return()...

    @ndb.tasklet
    def get_created_by_async_tasklet_with_childs(self, user_id):
        """Get async the MainEnt's created by user_id and its childs"""
        # stuff... yielding the query async. calling get_childs.. and raise ndb.Return()...

    @ndb.tasklet
    def get_voted_by_async_tasklet(self, user_id):
        """Get async the MainEnt's voted by user_id"""
        # stuff... yielding the query async raise ndb.Return()...

    @ndb.tasklet
    def get_voted_by_async_tasklet_with_childs(self, user_id):
        """Get async the MainEnt's voted by user_id and it's childs"""
        # stuff... yielding the query async, calling get_childs.. and raise ndb.Return()...

    @ndb.tasklet
    def get_created_and_voted_by_async_tasklet(self, user_id):
        """yield get_created_by_async_tasklet and get_voted_by_async_tasklet in parallel"""
        # stuff... yielding the other two functions and return results...

class ChildEnt(ndb.Model):
    name = ndb.StringProperty()

As you see MainEnt have three methods that return the "same" (sometime more) results but are used in different contexts.

1) The sync function only used when I need to get the results and getting that results are the only "ndb operation".

2) The async function only used when I need to get the results but I also perform some other ndb query that I want to overlap.

3) The tasklet async function only used when I need to get the results, get the Child Entities of this results and maybe also performing some other ndb operation.

Because I find writing too many functions...It's correct to only write an async tasklet function that is going to be called in each of the previous situations??

I mean even if I just need the results synchronous I will call the get_created_by_async_tasklet and then call get_results on the future returned by the function.

Is there any inconvenience on performance, error prone, etc... into doing this? I find out much more simple to always use an ndb async tasklet for every query, get, etc... and only call its results if I need too or otherwise perform more async operations and later call get_results.

Hope this is well explained...

Thanks in advance!

janscas
  • 619
  • 4
  • 13

1 Answers1

3

There is nothing wrong with only using async calls, then using get_result immediately if you want the results syncronously. This is exactly what the ndb synchronous functions do:

Here is an example from ndb.Key:

def get(self, **ctx_options):
    """Synchronously get the entity for this Key.

    Return None if there is no such entity.
    """
    return self.get_async(**ctx_options).get_result()
Patrick Costello
  • 3,616
  • 17
  • 22
  • And what about doing all tasklets? – janscas May 29 '14 at 20:54
  • Seems reasonable. Have you read through this document? https://developers.google.com/appengine/docs/python/ndb/async. It has some good examples which look like what you are trying to do. – Patrick Costello May 29 '14 at 21:32
  • Yes, I read all this docs but I don't know if using tasklets imply any drawback on performance or whatever. Thanks! – janscas May 30 '14 at 08:46
  • Patrick... I find out that Query.get_async also uses a tasklet internaly. `@tasklets.tasklet def _get_async(self, **q_options): """Internal version of get_async()."""` – janscas May 30 '14 at 11:56