def update_tasks_redundancy(self, project, n_answers, filters=None): """ Update the n_answer of every task from a project and their state. Use raw SQL for performance. Mark tasks as exported = False for tasks with curr redundancy < new redundancy, with state as completed and were marked as exported = True """ from pybossa.jobs import check_and_send_task_notifications if n_answers < self.MIN_REDUNDANCY or n_answers > self.MAX_REDUNDANCY: raise ValueError("Invalid redundancy value: {}".format(n_answers)) filters = filters or {} task_expiration = '{} day'.format(self.rdancy_upd_exp) conditions, params = get_task_filters(filters) tasks_not_updated = self._get_redundancy_update_msg( project, n_answers, conditions, params, task_expiration) self.update_task_exported_status(project.id, n_answers, conditions, params, task_expiration) sql = text(''' WITH all_tasks_with_orig_filter AS ( SELECT task.id as id, coalesce(ct, 0) as n_task_runs, task.n_answers, ft, priority_0, task.created FROM task LEFT OUTER JOIN (SELECT task_id, CAST(COUNT(id) AS FLOAT) AS ct, MAX(finish_time) as ft FROM task_run WHERE project_id=:project_id GROUP BY task_id) AS log_counts ON task.id=log_counts.task_id WHERE task.project_id=:project_id {} ), tasks_with_file_urls AS ( SELECT t.id as id FROM task t WHERE t.id IN (SELECT id from all_tasks_with_orig_filter) AND jsonb_typeof(t.info) = 'object' AND EXISTS(SELECT TRUE FROM jsonb_object_keys(t.info) AS key WHERE key ILIKE '%\_\_upload\_url%') ), tasks_excl_file_urls AS ( SELECT id FROM all_tasks_with_orig_filter WHERE id NOT IN (SELECT id FROM tasks_with_file_urls) ) UPDATE task SET n_answers=:n_answers, state='ongoing' WHERE project_id=:project_id AND ((id IN (SELECT id from tasks_excl_file_urls)) OR (id IN (SELECT id from tasks_with_file_urls) AND state='ongoing' AND TO_DATE(created, 'YYYY-MM-DD\THH24:MI:SS.US') >= NOW() - :task_expiration ::INTERVAL));''' .format(conditions)) self.db.session.execute(sql, dict(n_answers=n_answers, project_id=project.id, task_expiration=task_expiration, **params)) self.update_task_state(project.id) self.db.session.commit() cached_projects.clean_project(project.id) check_and_send_task_notifications(project.id) return tasks_not_updated
def test_remaining_tasks_drop_below_configuration_2(self, notify, n_tasks): """Do not sent multiple email""" n_tasks.return_value = 0 reminder = dict(target_remaining=0, sent=True) project_id = '1' project = ProjectFactory.create(id=project_id, owners_ids=[], published=True, featured=True, info={'progress_reminder': reminder}) check_and_send_task_notifications(project_id) assert not notify.called assert project.info['progress_reminder']['sent']
def test_remaining_tasks_drop_below_configuration_0(self, notify, n_tasks): """Send email if remaining tasks drops below, test with connection""" n_tasks.return_value = 0 reminder = dict(target_remaining=0, sent=False) conn = MagicMock() conn.execute.return_value = None project_id = '1' project = ProjectFactory.create(id=project_id, owners_ids=[], published=True, featured=True, info={'progress_reminder': reminder}) check_and_send_task_notifications(project_id, conn) assert notify.called assert project.info['progress_reminder']['sent']
def delete_task_by_id(self, project_id, task_id): from pybossa.jobs import check_and_send_task_notifications args = dict(project_id=project_id, task_id=task_id) self.db.session.execute(text(''' DELETE FROM result WHERE project_id=:project_id AND task_id=:task_id;'''), args) self.db.session.execute(text(''' DELETE FROM task_run WHERE project_id=:project_id AND task_id=:task_id;'''), args) self.db.session.execute(text(''' DELETE FROM task WHERE project_id=:project_id AND id=:task_id;'''), args) self.db.session.commit() cached_projects.clean_project(project_id) check_and_send_task_notifications(project_id)
def on_taskrun_submit(mapper, conn, target): """Update the task.state when n_answers condition is met.""" # Get project details sql_query = ( 'select name, short_name, published, webhook, info, category_id \ from project where id=%s') % target.project_id results = conn.execute(sql_query) tmp = dict() for r in results: tmp['name'] = r.name tmp['short_name'] = r.short_name _published = r.published tmp['info'] = r.info _webhook = r.webhook tmp['category_id'] = r.category_id tmp['id'] = target.project_id project_public = dict() project_public.update(Project().to_public_json(tmp)) project_public['action_updated'] = 'TaskCompleted' sched.after_save(target, conn) add_user_contributed_to_feed(conn, target.user_id, project_public) # golden tasks never complete; bypass update to task.state # mark task as exported false for each task run submissions task = task_repo.get_task(id=target.task_id) if task.calibration: if task.exported and _published: sql_query = ("""UPDATE task SET exported=False \ WHERE id=%s;""") % (task.id) conn.execute(sql_query) return is_completed = is_task_completed(conn, target.task_id, target.project_id) if is_completed: update_task_state(conn, target.task_id) check_and_send_task_notifications(target.project_id, conn) if is_completed and _published: update_feed(project_public) result_id = create_result(conn, target.project_id, target.task_id) project_private = dict() project_private.update(project_public) project_private['webhook'] = _webhook push_webhook(project_private, target.task_id, result_id)
def test_remaining_tasks_drop_below_configuration_hitting_webhook_failed( self, notify, n_tasks, req): """Send email if remaining tasks drops below, test with connection""" n_tasks.return_value = 0 req.post.side_effect = Exception('not found') reminder = dict(target_remaining=0, webhook="fake_url", sent=False) conn = MagicMock() conn.execute.return_value = None project_id = '1' project = ProjectFactory.create(id=project_id, owners_ids=[], published=True, featured=True, info={'progress_reminder': reminder}) check_and_send_task_notifications(project_id, conn) assert req.post.called assert project.info['progress_reminder']['sent']
def calculate_and_send_progress_after_update_task(mapper, conn, target): check_and_send_task_notifications(target.project_id, conn)