Example #1
0
def get_locked_task(project_id,
                    user_id=None,
                    user_ip=None,
                    external_uid=None,
                    offset=0,
                    limit=1,
                    orderby='priority_0',
                    desc=True):
    if offset > 2:
        raise BadRequest()
    if offset == 2:
        return []

    user_count = get_active_user_count(project_id, sentinel.master)
    limit = 2 * user_count

    user_param = 'user_id'
    uid = user_id
    if not user_id:
        if not user_ip:
            user_ip = '127.0.0.1'
        if not external_uid:
            user_param = 'user_ip'
            uid = user_ip
        else:
            user_param = 'external_uid'
            uid = external_uid

    sql = text('''
           SELECT task.id, COUNT(task_run.task_id) AS taskcount, n_answers
           FROM task
           LEFT JOIN task_run ON (task.id = task_run.task_id)
           WHERE NOT EXISTS
           (SELECT 1 FROM task_run WHERE project_id=:project_id AND
           {}=:uid AND task_id=task.id)
           AND task.project_id=:project_id AND task.state !='completed'
           group by task.id HAVING COUNT(task_run.task_id) < n_answers
           ORDER BY priority_0 DESC, id ASC LIMIT :limit;
           '''.format(user_param))

    rows = session.execute(
        sql, dict(project_id=project_id, uid=uid, limit=user_count + 5))

    for task_id, taskcount, n_answers in rows:
        remaining = n_answers - taskcount
        if acquire_lock(task_id, uid, remaining, TIMEOUT):
            if offset == 1:
                offset = 0
                continue
            rows.close()
            register_active_user(project_id, uid, sentinel.master, ttl=TIMEOUT)
            return [session.query(Task).get(task_id)]

    return []
Example #2
0
    def test_get_active_users_lock(self):
        """ Test number of locked tasks"""
        user = UserFactory.create(id=500)
        project = ProjectFactory.create(owner=user, info={'sched': 'default'})
        TaskFactory.create_batch(2, project=project, n_answers=2)

        # Register the active user as a locked task.
        register_active_user(project.id, user.id, sentinel.master)
        # Verify the count of locked tasks for this project equals 1.
        count = get_active_user_count(project.id, sentinel.master)
        assert count == 1

        # Unregister the active user as a locked task.
        unregister_active_user(project.id, user.id, sentinel.master)
        # Verify the count of locked tasks for this project equals 1.
        # There is a delay before the lock is released.
        count = get_active_user_count(project.id, sentinel.master)
        assert count == 1

        # Confirm lock released after a delay.
        time.sleep(EXPIRE_LOCK_DELAY + 1)
        count = get_active_user_count(project.id, sentinel.master)
        assert not count
Example #3
0
def get_locked_task(project_id, user_id=None, user_ip=None,
                    external_uid=None, offset=0, limit=1,
                    orderby='priority_0', desc=True):
    if offset > 2:
        raise BadRequest()
    if offset == 2:
        return []

    user_count = get_active_user_count(project_id, sentinel.master)
    limit = 2*user_count

    user_param = 'user_id'
    uid = user_id
    if not user_id:
        if not user_ip:
            user_ip = '127.0.0.1'
        if not external_uid:
            user_param = 'user_ip'
            uid = user_ip
        else:
            user_param = 'external_uid'
            uid = external_uid

    sql = text('''
           SELECT task.id, COUNT(task_run.task_id) AS taskcount, n_answers
           FROM task
           LEFT JOIN task_run ON (task.id = task_run.task_id)
           WHERE NOT EXISTS
           (SELECT 1 FROM task_run WHERE project_id=:project_id AND
           {}=:uid AND task_id=task.id)
           AND task.project_id=:project_id AND task.state !='completed'
           group by task.id HAVING COUNT(task_run.task_id) < n_answers
           ORDER BY priority_0 DESC, id ASC LIMIT :limit;
           '''.format(user_param))

    rows = session.execute(sql, dict(project_id=project_id,
                                     uid=uid, limit=user_count + 5))

    for task_id, taskcount, n_answers in rows:
        remaining = n_answers - taskcount
        if acquire_lock(task_id, uid, remaining, TIMEOUT):
            if offset == 1:
                offset = 0
                continue
            rows.close()
            register_active_user(project_id, uid, sentinel.master, ttl=TIMEOUT)
            return [session.query(Task).get(task_id)]

    return []
Example #4
0
def n_locked_tasks(project_id):
    """Return the number of locked tasks in the project."""
    from pybossa.core import sentinel
    from pybossa.redis_lock import get_active_user_count

    return get_active_user_count(project_id, sentinel.master)