Exemple #1
0
def load_stories(game='all',cursor='',pagesize=50,sortorder='-postime'):
    """ Return a page of stories.
        This function makes use of cursor mechanism to fetch pages and cache them for efficient repeated queries.
        Once a page of SuiStory entities are loaded, they are memcached with the cursor.
        If not enough entities are loaded, cursor is None meaning no more pages.
        Stories are sorted for display by postime in descending order.
        Pages are always in memcache of 'Stories', invalidated when a new story is added.
        @param game : game key or all
        @param cursor : from which cursor to fetch, '' = first page
        @param pagesize : how many for a page, default 30
        @param sortorder : postime in descending by default, can be 'title', 'author'
        @return : ([SuiStory,...],cursor) tuple of a list of SuiStory entities or None
    """
    cachekey = 'Stories_%s_%s'%(game,cursor)
    stories = from_cache(cachekey)
    if stories is None:
        if game != 'all':
            query = SuiStory.all().filter('game =',game).order(sortorder)
        else:
            query = SuiStory.all().order(sortorder)
        if cursor != '':
            query.with_cursor(cursor)
        mstories = query.fetch(pagesize)
        if len(mstories) > 0:
            c = None
            if len(mstories) >= pagesize:
                c = query.cursor()
            stories = (mstories,c or '')
            to_cache(cachekey,stories)
        else:
            stories = ([],'')
    return stories
Exemple #2
0
def load_comments0(story,page=0,pagesize=50):
    """ Load a page of comments for a story. Page of comments are also memcached until a new comment is added.
    """
    if isinstance(story,SuiStory):
        skey = story.key()
    elif isinstance(story,basestring):
        skey = db.Key(story)
    else:
        skey = story
    mckey = str(skey)+'_cms'
    comments = from_cache(mckey)
    if comments is None:
        query = SuiComment.all().filter('story =',skey).order('-postime')
        cmts = query.fetch(pagesize)
        if len(cmts) > 0:
            c = None
            if len(cmts) >= pagesize:
                c = query.cursor()
            comments = [(cmts,c)]
            to_cache(mckey, comments)
        else:
            return [([],None)]
    elif page >= len(comments) and comments[-1][1] is not None:
        query = SuiComment.all().filter('story =',skey).order('-postime')
        query.with_cursor(comments[-1][1])
        cmts = query.fetch(pagesize)
        if len(cmts) >= pagesize:
            comments.append((cmts,query.cursor()))
        else:
            comments.append((cmts,None))
        to_cache(mckey,comments)
    return comments[page]
Exemple #3
0
def add_story(me,title,content,game):
    """ save a story in my name.
    """
    if title is None or title == '':
        logging.warning('title is empty')
        raise Exception('No title')
    if content is None or content == '':
        logging.warning('content is empty')
        raise Exception('No content')
    s = SuiStory()
    s.title = title.replace('<','&lt;')
    #s.text = content.replace('<','&lt;').replace('\n','<br/>').replace('\r','')
    s.game = game
    s.author = me.key().name()
    s.aname = me.name
    s.postime = datetime.utcnow()
    s.put()
    #save content text into SuiContent
    c = SuiContent(parent=s)
    if content.find('\n')>=0:
        content = content.replace('\r\n','<br>').replace('\n','<br>');
    c.text = XML_REPTN.sub(filter_tag, content)
    c.length = len(c.text)
    c.put()
    pages = from_cache('Stories_all')
    if pages is not None:
        page1 = pages[0]
        if len(page1[0]) > 40:
            decaches(['Stories_all','NewStories'])
        else:
            page1[0].insert(0,s)
            to_cache('Stories_all',pages)
            decache('NewStories')
Exemple #4
0
def load_comments0(story, page=0, pagesize=50):
    """ Load a page of comments for a story. Page of comments are also memcached until a new comment is added.
    """
    if isinstance(story, SuiStory):
        skey = story.key()
    elif isinstance(story, basestring):
        skey = db.Key(story)
    else:
        skey = story
    mckey = str(skey) + '_cms'
    comments = from_cache(mckey)
    if comments is None:
        query = SuiComment.all().filter('story =', skey).order('-postime')
        cmts = query.fetch(pagesize)
        if len(cmts) > 0:
            c = None
            if len(cmts) >= pagesize:
                c = query.cursor()
            comments = [(cmts, c)]
            to_cache(mckey, comments)
        else:
            return [([], None)]
    elif page >= len(comments) and comments[-1][1] is not None:
        query = SuiComment.all().filter('story =', skey).order('-postime')
        query.with_cursor(comments[-1][1])
        cmts = query.fetch(pagesize)
        if len(cmts) >= pagesize:
            comments.append((cmts, query.cursor()))
        else:
            comments.append((cmts, None))
        to_cache(mckey, comments)
    return comments[page]
Exemple #5
0
def add_comment(me, story, comment):
    """ Add a comment """
    if isinstance(story, basestring):
        skey = db.Key(story)
    else:
        skey = story
    if not comment:
        return
    elif comment.find('\n'):
        comment = comment.replace('\r\n', '<br>').replace('\n', '<br>')
    mckey = str(skey) + '_cms'
    content = from_cache(mckey)
    if content is None:
        content = SuiContent.all().ancestor(skey).fetch(10)
        if not content:
            raise Exception('Story not found')
    c = content[-1]
    cp = 'c%d' % c.count
    c.count += 1
    pfx = '[%s:%s@%s]' % (me.key().name(), me.name,
                          datetime.strftime(datetime.utcnow(),
                                            '%Y-%m-%d %H:%M:%S'))
    setattr(c, cp, '%s%s' % (pfx, XML_REPTN.sub(filter_tag, comment)))
    c.put()
    to_cache(mckey, content)
Exemple #6
0
def add_story(me, title, content, game):
    """ save a story in my name.
    """
    if title is None or title == '':
        logging.warning('title is empty')
        raise Exception('No title')
    if content is None or content == '':
        logging.warning('content is empty')
        raise Exception('No content')
    s = SuiStory()
    s.title = title.replace('<', '&lt;')
    #s.text = content.replace('<','&lt;').replace('\n','<br/>').replace('\r','')
    s.game = game
    s.author = me.key().name()
    s.aname = me.name
    s.postime = datetime.utcnow()
    s.put()
    #save content text into SuiContent
    c = SuiContent(parent=s)
    if content.find('\n') >= 0:
        content = content.replace('\r\n', '<br>').replace('\n', '<br>')
    c.text = XML_REPTN.sub(filter_tag, content)
    c.length = len(c.text)
    c.put()
    pages = from_cache('Stories_all')
    if pages is not None:
        page1 = pages[0]
        if len(page1[0]) > 40:
            decaches(['Stories_all', 'NewStories'])
        else:
            page1[0].insert(0, s)
            to_cache('Stories_all', pages)
            decache('NewStories')
Exemple #7
0
def load_stories(game='all', cursor='', pagesize=50, sortorder='-postime'):
    """ Return a page of stories.
        This function makes use of cursor mechanism to fetch pages and cache them for efficient repeated queries.
        Once a page of SuiStory entities are loaded, they are memcached with the cursor.
        If not enough entities are loaded, cursor is None meaning no more pages.
        Stories are sorted for display by postime in descending order.
        Pages are always in memcache of 'Stories', invalidated when a new story is added.
        @param game : game key or all
        @param cursor : from which cursor to fetch, '' = first page
        @param pagesize : how many for a page, default 30
        @param sortorder : postime in descending by default, can be 'title', 'author'
        @return : ([SuiStory,...],cursor) tuple of a list of SuiStory entities or None
    """
    cachekey = 'Stories_%s_%s' % (game, cursor)
    stories = from_cache(cachekey)
    if stories is None:
        if game != 'all':
            query = SuiStory.all().filter('game =', game).order(sortorder)
        else:
            query = SuiStory.all().order(sortorder)
        if cursor != '':
            query.with_cursor(cursor)
        mstories = query.fetch(pagesize)
        if len(mstories) > 0:
            c = None
            if len(mstories) >= pagesize:
                c = query.cursor()
            stories = (mstories, c or '')
            to_cache(cachekey, stories)
        else:
            stories = ([], '')
    return stories
Exemple #8
0
def get_new_stories(N=10):
    """ Load N latest stories, return [[key,title],..] """
    stories = from_cache('NewStories')
    if stories is None:
        qs = SuiStory.all().order('-postime').fetch(N)
        stories = [[str(q.key()),q.title] for q in qs]
        to_cache('NewStories',stories)  #only when new stories added, invalidate this cache
    return stories
Exemple #9
0
def get_new_stories(N=10):
    """ Load N latest stories, return [[key,title],..] """
    stories = from_cache('NewStories')
    if stories is None:
        qs = SuiStory.all().order('-postime').fetch(N)
        stories = [[str(q.key()), q.title] for q in qs]
        to_cache('NewStories',
                 stories)  #only when new stories added, invalidate this cache
    return stories
Exemple #10
0
def update_gift_cache(op, gid, uid=None):
    gs = from_cache('BD_GIFTS_ALL')
    if gs and not gid in gs:
        if op == 'add':
            gs.append(gid)
        elif op == 'del':
            gs.remove(gid)
        to_cache('BD_GIFTS_ALL', gs)
    gs = from_cache('BD_GIFTS_%s' % uid)
    if gs and not gid in gs:
        if op == 'add':
            gs.append(gid)
        elif op == 'del':
            gs.remove(gid)
        to_cache('BD_GIFTS_%s' % uid)
Exemple #11
0
def update_gift_cache(op,gid,uid=None):
    gs = from_cache('BD_GIFTS_ALL')
    if gs and not gid in gs:
        if op == 'add':
            gs.append(gid)
        elif op == 'del':
            gs.remove(gid)
        to_cache('BD_GIFTS_ALL', gs)
    gs = from_cache('BD_GIFTS_%s'%uid)
    if gs and not gid in gs:
        if op == 'add':
            gs.append(gid)
        elif op == 'del':
            gs.remove(gid)
        to_cache('BD_GIFTS_%s'%uid)
Exemple #12
0
def load_gifts(uid=None):
    """ Load gift ids from SuiBirthdayGift entities and store in memcache by BD_GIFTS_ALL or BD_GIFTS_creatorID
        Maximum number of gifts in use for all is 10000, while any creator can have no more than 20
    """
    if uid:
        gs = from_cache('BD_GIFTS_%s'%uid)
        if not gs:
            es = SuiBirthdayGift.all(keys_only=True).filter('creator =',uid).fetch(50)
            gs = [e.id_or_name() for e in es]
            to_cache('BD_GIFTS_%s'%uid, gs)
    else:
        gs = from_cache('BD_GIFTS_ALL')
        if not gs:
            es = SuiBirthdayGift.all(keys_only=True).fetch(10000)
            gs = [e.id_or_name() for e in es]
            to_cache('BD_GIFTS_ALL', gs)
    return gs
Exemple #13
0
def load_gifts(uid=None):
    """ Load gift ids from SuiBirthdayGift entities and store in memcache by BD_GIFTS_ALL or BD_GIFTS_creatorID
        Maximum number of gifts in use for all is 10000, while any creator can have no more than 20
    """
    if uid:
        gs = from_cache('BD_GIFTS_%s' % uid)
        if not gs:
            es = SuiBirthdayGift.all(keys_only=True).filter('creator =',
                                                            uid).fetch(50)
            gs = [e.id_or_name() for e in es]
            to_cache('BD_GIFTS_%s' % uid, gs)
    else:
        gs = from_cache('BD_GIFTS_ALL')
        if not gs:
            es = SuiBirthdayGift.all(keys_only=True).fetch(10000)
            gs = [e.id_or_name() for e in es]
            to_cache('BD_GIFTS_ALL', gs)
    return gs
Exemple #14
0
def add_comment0(me,story,content):
    """ Add a comment to a story. """
    c = SuiComment()
    c.story = db.Key(story)
    logging.debug(story)
    c.text = content
    c.author = '%s[%s]'%(me.name,me.key().name())
    c.postime = datetime.utcnow()
    c.put()
    mckey = str(story)+'_cms'
    if mckey is not None:
        pages = from_cache(mckey)
        if pages is not None:
            page1 = pages[0][0]
            if len(page1) > 60:
                decache(mckey)
            else:
                page1.insert(0,c)
                to_cache(mckey,pages)
Exemple #15
0
def add_comment0(me, story, content):
    """ Add a comment to a story. """
    c = SuiComment()
    c.story = db.Key(story)
    logging.debug(story)
    c.text = content
    c.author = '%s[%s]' % (me.name, me.key().name())
    c.postime = datetime.utcnow()
    c.put()
    mckey = str(story) + '_cms'
    if mckey is not None:
        pages = from_cache(mckey)
        if pages is not None:
            page1 = pages[0][0]
            if len(page1) > 60:
                decache(mckey)
            else:
                page1.insert(0, c)
                to_cache(mckey, pages)
Exemple #16
0
def load_comments(story, page=0):
    """ Load all SuiContent entities for story and return text and comments of first entity.
        @param story - key string of SuiStory
        @param page - which entity of SuiContent for this story, 0 first by default, can be 10 pages maximum.
    """
    if isinstance(story, basestring):
        skey = db.Key(story)
    else:
        skey = story
    mckey = str(skey) + '_cms'
    content = from_cache(mckey)
    if content is None:
        content = SuiContent.all().ancestor(skey).fetch(10)
        if content:
            to_cache(mckey, content)
        else:
            return None
    if len(content) > page:
        return content[page]
    else:
        return content[-1]
Exemple #17
0
def load_comments(story,page=0):
    """ Load all SuiContent entities for story and return text and comments of first entity.
        @param story - key string of SuiStory
        @param page - which entity of SuiContent for this story, 0 first by default, can be 10 pages maximum.
    """
    if isinstance(story,basestring):
        skey = db.Key(story)
    else:
        skey = story
    mckey = str(skey)+'_cms'
    content = from_cache(mckey)
    if content is None:
        content = SuiContent.all().ancestor(skey).fetch(10)
        if content:
            to_cache(mckey, content)
        else:
            return None
    if len(content) > page:
        return content[page]
    else:
        return content[-1]
Exemple #18
0
def lock_process(lock_key):
    """ Emulate a lock to stop the code going on if the process is still going on.
        This can happen when a user repeatedly clicks on buy button that causes invalid transaction.
        If memcache is not available, this will definately raise an exception and causes the routine to fail.
        Algorithm: check whether a memcache is available, if not, add it for 30 seconds, and return, if yet, raises ServerBusy exception.
    """
    lock = from_cache(lock_key)
    if lock is None:
        if to_cache(lock_key, lock_key, 30) == False:
            raise Exception('Server Error, try later')
    else:
        raise Exception('Server Busy, try later')
Exemple #19
0
def lock_process(lock_key):
    """ Emulate a lock to stop the code going on if the process is still going on.
        This can happen when a user repeatedly clicks on buy button that causes invalid transaction.
        If memcache is not available, this will definately raise an exception and causes the routine to fail.
        Algorithm: check whether a memcache is available, if not, add it for 30 seconds, and return, if yet, raises ServerBusy exception.
    """
    lock = from_cache(lock_key)
    if lock is None:
        if to_cache(lock_key,lock_key,30) == False:
            raise Exception('Server Error, try later')
    else:
        raise Exception('Server Busy, try later')
Exemple #20
0
def get_user_by_key(uid,usecache=True):
    """ Get SuiUser entity from datastore by key_name, return None if not existent. 
    @param uid: fb_1234 like
    @param usecache: if True, Get from memcache first, and Put in memcache or not, default is True.
    """
    if usecache:
        u = from_cache(uid)
    else:
        u = None
    if not u:
        logging.debug('UID %s not in memcache'%uid)
        try:
            u = SuiUser.get_by_key_name(uid)
            if u is None:
                logging.debug('User not in SuiUser')
                return u
            if usecache:
                u._cache_time = datetime.utcnow()
                to_cache(uid, u, PLAYER_CACHE_SECS)
        except Exception,e:
            logging.error('helper.get_user_by_key(%s) error:%s' % (uid,e))
            raise
Exemple #21
0
def get_user_by_key(uid, usecache=True):
    """ Get SuiUser entity from datastore by key_name, return None if not existent. 
    @param uid: fb_1234 like
    @param usecache: if True, Get from memcache first, and Put in memcache or not, default is True.
    """
    if usecache:
        u = from_cache(uid)
    else:
        u = None
    if not u:
        logging.debug('UID %s not in memcache' % uid)
        try:
            u = SuiUser.get_by_key_name(uid)
            if u is None:
                logging.debug('User not in SuiUser')
                return u
            if usecache:
                u._cache_time = datetime.utcnow()
                to_cache(uid, u, PLAYER_CACHE_SECS)
        except Exception, e:
            logging.error('helper.get_user_by_key(%s) error:%s' % (uid, e))
            raise
Exemple #22
0
def add_comment(me,story,comment):
    """ Add a comment """
    if isinstance(story,basestring):
        skey = db.Key(story)
    else:
        skey = story
    if not comment:
        return
    elif comment.find('\n'):
        comment = comment.replace('\r\n','<br>').replace('\n','<br>')
    mckey = str(skey)+'_cms'
    content = from_cache(mckey)
    if content is None:
        content = SuiContent.all().ancestor(skey).fetch(10)
        if not content:
            raise Exception('Story not found')
    c = content[-1]
    cp = 'c%d' % c.count
    c.count += 1
    pfx = '[%s:%s@%s]'%(me.key().name(),me.name,datetime.strftime(datetime.utcnow(),'%Y-%m-%d %H:%M:%S'))
    setattr(c, cp, '%s%s'%(pfx, XML_REPTN.sub(filter_tag, comment)))
    c.put()
    to_cache(mckey, content)