Changeset 34:fa0836060deb

website/juviewer

← 33:3c29ce29c6b1 34:fa0836060deb 35:47097a90779b
Author:
Kang Seonghoon <public+hg@mearie.org>
Committed on

library-ifying juupdater; more emphasis on new_result warning

Files

juupdater.py
tmpl/new_result.en.html
tmpl/new_result.ko.html

Diff

     1.1 --- a/juupdater.py	Fri Jul 24 02:37:53 2009 +0900
     1.2 +++ b/juupdater.py	Sat Jul 25 00:59:05 2009 +0900
     1.3 @@ -7,105 +7,111 @@
     1.4  
     1.5  from lib.jubeatdb import *
     1.6  
     1.7 +THRESHOLD = 86400
     1.8 +RETRYCOUNT = 3
     1.9 +forcebefore = int(time.time()) - THRESHOLD
    1.10 +
    1.11  def log(s):
    1.12      sys.stdout.write('%s | %s\n' % (time.strftime('%Y-%m-%d %H:%M:%S'), s))
    1.13      sys.stdout.flush()
    1.14  
    1.15 -THRESHOLD = 86400
    1.16 -RETRYCOUNT = 3
    1.17 -forcebefore = int(time.time()) - THRESHOLD
    1.18 +def update_user(db, user):
    1.19 +    with db:
    1.20 +        # cannot rely on existing (possibly unsynchronized) stat.
    1.21 +        prevnplays = sum(sum(result.nplays) for _, result in
    1.22 +                db.query(sqlfunc.max(MusicResult.time), MusicResult)
    1.23 +                  .filter(and_(MusicResult.sid == user.sid,
    1.24 +                               MusicResult.mid == Music.mid))
    1.25 +                  .group_by(MusicResult.mid).order_by(Music.order))
    1.26 +        _, newstat, _ = db.update_user(user.sid)
    1.27 +        nplays = newstat.nplays
    1.28 +        assert nplays >= prevnplays
    1.29  
    1.30 -log('--- start of process (pid=%d) ---' % os.getpid())
    1.31 -db = Database()
    1.32 -userlist = db.query(User).all()
    1.33 -for retrycount in xrange(1, RETRYCOUNT+1):
    1.34 -    retrylist = []
    1.35 +        prevmusiclist = [i for i, in db.query(MusicResult.mid)
    1.36 +                                       .filter(MusicResult.sid == user.sid)
    1.37 +                                       .order_by(MusicResult.time.desc())
    1.38 +                                       .group_by(MusicResult.mid)]
    1.39  
    1.40 -    for user in userlist:
    1.41 -        time.sleep(1)
    1.42 -        sid = user.sid
    1.43 -        log('updating user %d' % sid)
    1.44 -        try:
    1.45 -            with db:
    1.46 -                # cannot rely on existing (possibly unsynchronized) stat.
    1.47 -                prevnplays = sum(sum(result.nplays) for _, result in
    1.48 -                        db.query(sqlfunc.max(MusicResult.time), MusicResult)
    1.49 -                          .filter(and_(MusicResult.sid == sid,
    1.50 -                                       MusicResult.mid == Music.mid))
    1.51 -                          .group_by(MusicResult.mid).order_by(Music.order))
    1.52 -                _, newstat, _ = db.update_user(sid)
    1.53 -                nplays = newstat.nplays
    1.54 -                assert nplays >= prevnplays
    1.55 +        rescount = db.query(MusicResult).filter(MusicResult.sid == user.sid).count()
    1.56 +        if rescount == 0 or nplays > prevnplays:
    1.57 +            if rescount == 0:
    1.58 +                log('.. first update scheduled')
    1.59 +                prevnplays = 0 # treat as initial state!
    1.60 +            else:
    1.61 +                log('.. nplays changed (%d->%d)' % (prevnplays, nplays))
    1.62 +            musiclist = set(db.list_avail_music(user.sid).keys())
    1.63 +            assert musiclist.issuperset(prevmusiclist)
    1.64 +            musicdiff = musiclist.difference(prevmusiclist)
    1.65 +            for mid in musicdiff:
    1.66 +                result, _ = db.update_musicresult(user.sid, mid)
    1.67 +                prevnplays += sum(result.nplays)
    1.68 +                log('.. updating new music %d (0->%d; %d plays remaining)' %
    1.69 +                        (mid, sum(result.nplays), nplays - prevnplays))
    1.70  
    1.71 -                prevmusiclist = [i for i, in db.query(MusicResult.mid)
    1.72 -                                               .filter(MusicResult.sid == sid)
    1.73 -                                               .order_by(MusicResult.time.desc())
    1.74 -                                               .group_by(MusicResult.mid)]
    1.75 +        for mid in prevmusiclist: # in the order of most recent plays
    1.76 +            if prevnplays >= nplays:
    1.77 +                withinthreshold = (db.query(MusicResultRank)
    1.78 +                                     .filter(and_(MusicResultRank.sid == user.sid,
    1.79 +                                                  MusicResultRank.mid == mid,
    1.80 +                                                  MusicResultRank.time >= forcebefore))
    1.81 +                                     .count())
    1.82 +                if withinthreshold > 0: continue
    1.83 +                flag = True
    1.84 +            else:
    1.85 +                flag = False
    1.86 +            prevresult = (db.query(MusicResult)
    1.87 +                            .filter(and_(MusicResult.sid == user.sid,
    1.88 +                                         MusicResult.mid == mid))
    1.89 +                            .order_by(MusicResult.time.desc()).first())
    1.90 +            prevresnplays = 0 if prevresult is None else sum(prevresult.nplays)
    1.91 +            time.sleep(0.5)
    1.92 +            result, _ = db.update_musicresult(user.sid, mid)
    1.93 +            resnplays = sum(result.nplays)
    1.94 +            assert resnplays >= prevresnplays
    1.95 +            prevnplays += resnplays - prevresnplays
    1.96 +            log('.. updating %s %d (%d->%d; %d plays remaining)' %
    1.97 +                    (('music', 'rank-expired music')[flag], mid, prevresnplays,
    1.98 +                     resnplays, nplays - prevnplays))
    1.99  
   1.100 -                rescount = db.query(MusicResult).filter(MusicResult.sid == sid).count()
   1.101 -                if rescount == 0 or nplays > prevnplays:
   1.102 -                    if rescount == 0:
   1.103 -                        log('.. first update scheduled')
   1.104 -                        prevnplays = 0 # treat as initial state!
   1.105 -                    else:
   1.106 -                        log('.. nplays changed (%d->%d)' % (prevnplays, nplays))
   1.107 -                    musiclist = set(db.list_avail_music(sid).keys())
   1.108 -                    assert musiclist.issuperset(prevmusiclist)
   1.109 -                    musicdiff = musiclist.difference(prevmusiclist)
   1.110 -                    for mid in musicdiff:
   1.111 -                        result, _ = db.update_musicresult(sid, mid)
   1.112 -                        prevnplays += sum(result.nplays)
   1.113 -                        log('.. updating new music %d (0->%d; %d plays remaining)' %
   1.114 -                                (mid, sum(result.nplays), nplays - prevnplays))
   1.115 +        if nplays != prevnplays:
   1.116 +            # theoretically this is an error. but in the reality, there are cases
   1.117 +            # that other music is played while crawling process, thus rendering
   1.118 +            # assertion invalid. so we just log this incident. if the situation
   1.119 +            # is over, nplays and prevnplays should be synchronized and this
   1.120 +            # warning won't be repeated.
   1.121 +            log('.. warning: nplays=%d and prevnplays=%d doesn\'t match.' %
   1.122 +                    (nplays, prevnplays))
   1.123  
   1.124 -                for mid in prevmusiclist: # in the order of most recent plays
   1.125 -                    if prevnplays >= nplays:
   1.126 -                        withinthreshold = (db.query(MusicResultRank)
   1.127 -                                             .filter(and_(MusicResultRank.sid == sid,
   1.128 -                                                          MusicResultRank.mid == mid,
   1.129 -                                                          MusicResultRank.time >= forcebefore))
   1.130 -                                             .count())
   1.131 -                        if withinthreshold > 0: continue
   1.132 -                        flag = True
   1.133 -                    else:
   1.134 -                        flag = False
   1.135 -                    prevresult = (db.query(MusicResult)
   1.136 -                                    .filter(and_(MusicResult.sid == sid,
   1.137 -                                                 MusicResult.mid == mid))
   1.138 -                                    .order_by(MusicResult.time.desc()).first())
   1.139 -                    prevresnplays = 0 if prevresult is None else sum(prevresult.nplays)
   1.140 -                    time.sleep(0.5)
   1.141 -                    result, _ = db.update_musicresult(sid, mid)
   1.142 -                    resnplays = sum(result.nplays)
   1.143 -                    assert resnplays >= prevresnplays
   1.144 -                    prevnplays += resnplays - prevresnplays
   1.145 -                    log('.. updating %s %d (%d->%d; %d plays remaining)' %
   1.146 -                            (('music', 'rank-expired music')[flag], mid, prevresnplays,
   1.147 -                             resnplays, nplays - prevnplays))
   1.148 +def process():
   1.149 +    log('--- start of process (pid=%d) ---' % os.getpid())
   1.150  
   1.151 -                if nplays != prevnplays:
   1.152 -                    # theoretically this is an error. but in the reality, there are cases
   1.153 -                    # that other music is played while crawling process, thus rendering
   1.154 -                    # assertion invalid. so we just log this incident. if the situation
   1.155 -                    # is over, nplays and prevnplays should be synchronized and this
   1.156 -                    # warning won't be repeated.
   1.157 -                    log('.. warning: nplays=%d and prevnplays=%d doesn\'t match.' %
   1.158 -                            (nplays, prevnplays))
   1.159 +    db = Database()
   1.160 +    userlist = db.query(User).all()
   1.161 +    for retrycount in xrange(1, RETRYCOUNT+1):
   1.162 +        retrylist = []
   1.163  
   1.164 -        except Exception:
   1.165 -            traceback.print_exc()
   1.166 -            log('.. crawling terminated due to exception!')
   1.167 -            retrylist.append(user)
   1.168 +        for user in userlist:
   1.169 +            time.sleep(1)
   1.170 +            log('updating user %d' % user.sid)
   1.171 +            try:
   1.172 +                update_user(db, user)
   1.173 +            except Exception:
   1.174 +                traceback.print_exc()
   1.175 +                log('.. crawling terminated due to exception!')
   1.176 +                retrylist.append(user)
   1.177  
   1.178 -    if not retrylist: break
   1.179 -    log('some crawler process failed due to exception: %s' %
   1.180 -            ', '.join(str(u.sid) for u in retrylist))
   1.181 -    if retrycount == RETRYCOUNT:
   1.182 -        log('retry limit exceeded: blockage or protocol change?')
   1.183 -    else:
   1.184 -        log('restarting crawler process soon...')
   1.185 -        time.sleep(10)
   1.186 -        userlist = retrylist
   1.187 +        if not retrylist: break
   1.188 +        log('some crawler process failed due to exception: %s' %
   1.189 +                ', '.join(str(u.sid) for u in retrylist))
   1.190 +        if retrycount == RETRYCOUNT:
   1.191 +            log('retry limit exceeded: blockage or protocol change?')
   1.192 +        else:
   1.193 +            log('restarting crawler process soon...')
   1.194 +            time.sleep(10)
   1.195 +            userlist = retrylist
   1.196  
   1.197 -log('--- end of process ---')
   1.198 +    log('--- end of process ---')
   1.199  
   1.200 +if __name__ == '__main__':
   1.201 +    process()
   1.202 +
     2.1 --- a/tmpl/new_result.en.html	Fri Jul 24 02:37:53 2009 +0900
     2.2 +++ b/tmpl/new_result.en.html	Sat Jul 25 00:59:05 2009 +0900
     2.3 @@ -1,6 +1,6 @@
     2.4  <%inherit file="layout.en.html" />
     2.5  <%def name="title()">Register</%def>
     2.6  <h2>Registration success</h2>
     2.7 -<p>From now on you can access <a href="${root}/u/${sid|encode_sid}">your play data</a>. (Warning: You cannot register the same friend ID again, so please bookmark the play data page in your favorites!)</p>
     2.8 +<p>From now on you can access <a href="${root}/u/${sid|encode_sid}">your play data</a>. (Warning: <big>You cannot register the same friend ID again, so please make sure that the page is in your favorites!</big>)</p>
     2.9  
    2.10  ## vim: syn=mako
     3.1 --- a/tmpl/new_result.ko.html	Fri Jul 24 02:37:53 2009 +0900
     3.2 +++ b/tmpl/new_result.ko.html	Sat Jul 25 00:59:05 2009 +0900
     3.3 @@ -1,6 +1,6 @@
     3.4  <%inherit file="layout.ko.html" />
     3.5  <%def name="title()">등록</%def>
     3.6  <h2>등록 성공</h2>
     3.7 -<p>이제부터 <a href="${root}/u/${sid|encode_sid}">여러분의 플레이 기록</a>을 확인할 수 있습니다. (주의: 한 번 등록하면 같은 프렌드 아이디를 다시 등록할 수 없으므로 기록 페이지는 필히 즐겨찾기에 추가해 주세요!)</p>
     3.8 +<p>이제부터 <a href="${root}/u/${sid|encode_sid}">여러분의 플레이 기록</a>을 확인할 수 있습니다. (주의: <big>한 번 등록하면 같은 프렌드 아이디를 다시 등록할 수 없으므로 기록 페이지는 필히 즐겨찾기에 추가해 주세요!</big>)</p>
     3.9  
    3.10  ## vim: syn=mako

Powered by Mercurial