コード例 #1
0
ファイル: reaper.py プロジェクト: thecount92/newparp
from redis import StrictRedis
from sqlalchemy import and_, func
from sqlalchemy.orm import joinedload
from sqlalchemy.orm.exc import NoResultFound

from charat2.helpers.chat import disconnect, send_message, send_userlist
from charat2.model import sm, Message, ChatUser
from charat2.model.connections import redis_pool

if __name__ == "__main__":

    db = sm()

    print "Obtaining lock..."
    db.query(func.pg_advisory_lock(413, 1)).scalar()
    print "Lock obtained."

    redis = StrictRedis(connection_pool=redis_pool)

    while True:

        current_time = int(time.time())

        # Make sure a message is sent every 25 seconds so the long poll requests
        # don't time out.
        # XXX INCREASE THIS TO SEVERAL MINUTES
        for chat_id in redis.zrangebyscore("longpoll_timeout", 0, current_time):
            redis.publish("channel:%s" % chat_id, '{"messages":[]}')
            if redis.hlen("chat:%s:online" % chat_id) != 0:
                redis.zadd("longpoll_timeout", time.time() + 25, chat_id)
コード例 #2
0
ファイル: matchmaker.py プロジェクト: thecount92/newparp
def run_matchmaker(
    lock_id, searchers_key, searcher_prefix, get_searcher_info,
    check_compatibility, ChatClass, get_character_info,
):

    # XXX get log level from stdin
    root = logging.getLogger()
    root.setLevel(logging.DEBUG)

    db = sm()

    print "Obtaining lock..."
    db.query(func.pg_advisory_lock(413, lock_id)).scalar()
    print "Lock obtained."

    redis = StrictRedis(connection_pool=redis_pool)

    searcher_ids = redis.smembers(searchers_key)

    while True:

        # Reset the searcher list for the next iteration.
        redis.delete(searchers_key)
        for searcher in searcher_ids:
            logging.debug("Waking unmatched searcher %s." % searcher)
            redis.publish("%s:%s" % (searcher_prefix, searcher), "{ \"status\": \"unmatched\" }")

        time.sleep(10)

        logging.info("Starting match loop.")

        searcher_ids = redis.smembers(searchers_key)

        # We can't do anything with less than 2 people, so don't bother.
        if len(searcher_ids) < 2:
            logging.info("Not enough searchers, skipping.")
            continue

        searchers = get_searcher_info(redis, searcher_ids)
        logging.debug("Searcher list: %s" % searchers)
        shuffle(searchers)

        already_matched = set()
        # Range hack so we don't check opposite pairs or against itself.
        for n in range(len(searchers)):
            s1 = searchers[n]

            for m in range(n + 1, len(searchers)):
                s2 = searchers[m]

                if s1["id"] in already_matched or s2["id"] in already_matched:
                    continue

                logging.debug("Comparing %s and %s." % (s1["id"], s2["id"]))

                match, options = check_compatibility(redis, s1, s2)
                if not match:
                    logging.debug("No match.")
                    continue

                blocked = (
                    db.query(func.count("*")).select_from(Block).filter(and_(
                        Block.blocking_user_id == s1["user_id"],
                        Block.blocked_user_id == s2["user_id"]
                    )).scalar() != 0
                    or db.query(func.count("*")).select_from(Block).filter(and_(
                        Block.blocking_user_id == s2["user_id"],
                        Block.blocked_user_id == s1["user_id"]
                    )).scalar() != 0
                )
                if blocked:
                    logging.debug("Blocked.")
                    continue

                new_url = str(uuid4()).replace("-", "")
                logging.info(
                    "Matched %s and %s, sending to %s."
                    % (s1["id"], s2["id"], new_url)
                )
                new_chat = ChatClass(url=new_url)
                db.add(new_chat)
                db.flush()

                s1_user = db.query(User).filter(User.id == s1["user_id"]).one()
                s2_user = db.query(User).filter(User.id == s2["user_id"]).one()
                db.add(ChatUser.from_user(s1_user, chat_id=new_chat.id, number=1, **get_character_info(db, s1)))
                db.add(ChatUser.from_user(s2_user, chat_id=new_chat.id, number=2, **get_character_info(db, s2)))

                if options:
                    db.add(Message(
                        chat_id=new_chat.id,
                        type="search_info",
                        text=" ".join(option_messages[_] for _ in options),
                    ))

                db.commit()

                already_matched.add(s1["id"])
                already_matched.add(s2["id"])

                match_message = json.dumps({ "status": "matched", "url": new_url })
                redis.publish("%s:%s" % (searcher_prefix, s1["id"]), match_message)
                redis.publish("%s:%s" % (searcher_prefix, s2["id"]), match_message)
                searcher_ids.remove(s1["id"])
                searcher_ids.remove(s2["id"])