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 []
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
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 []
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)