def project_get(project_id): """ This endpoint describes a Project. """ log = logger.bind(pid=project_id) log.info("Getting detail for a project") abort_if_project_doesnt_exist(project_id) authorise_get_request(project_id) with DBConn() as db_conn: project_object = db.get_project(db_conn, project_id) # Expose the number of data providers who have uploaded clks parties_contributed = db.get_number_parties_uploaded( db_conn, project_id) num_parties_with_error = db.get_encoding_error_count( db_conn, project_id) log.info(f"{parties_contributed} parties have contributed hashes") project_object['parties_contributed'] = parties_contributed if num_parties_with_error > 0: log.warning( f"There are {num_parties_with_error} parties in error state") project_object['error'] = num_parties_with_error > 0 return ProjectDescription().dump(project_object)
def abort_if_project_in_error_state(project_id): conn = get_db() num_parties_with_error = db.get_encoding_error_count(conn, project_id) if num_parties_with_error > 0: safe_fail_request(500, message="Can't post run as project has errors")
def get(project_id, run_id): log = logger.bind(pid=project_id, rid=run_id) parent_span = g.flask_tracer.get_span() log.debug("request run status") with opentracing.tracer.start_span('check-auth', child_of=parent_span) as span: # Check the project and run resources exist abort_if_run_doesnt_exist(project_id, run_id) # Check the caller has a valid results token. Yes it should be renamed. auth_token_type = get_authorization_token_type_or_abort( project_id, request.headers.get('Authorization')) log.debug( "Run status authorized using {} token".format(auth_token_type)) with opentracing.tracer.start_span('get-status-from-db', child_of=parent_span) as span: dbinstance = get_db() run_status = db.get_run_status(dbinstance, run_id) project_in_error = db.get_encoding_error_count(dbinstance, project_id) > 0 span.set_tag('stage', run_status['stage']) run_type = RUN_TYPES[run_status['type']] state = 'error' if project_in_error else run_status['state'] stage = run_status['stage'] status = { "state": state, "time_added": run_status['time_added'], "stages": run_type['stages'], "current_stage": { "number": stage, "description": run_type['stage_descriptions'].get( stage, "there is no description for this stage") } } # trying to get progress if available if stage == 1: # waiting for CLKs abs_val = db.get_number_parties_uploaded(dbinstance, project_id) max_val = db.get_project_column(dbinstance, project_id, 'parties') elif stage == 2: # Computing similarity abs_val = cache.get_progress(run_id) if abs_val is not None: max_val = db.get_total_comparisons_for_project( dbinstance, project_id) else: # Solving for mapping (no progress) abs_val = None if abs_val is not None: progress = { 'absolute': abs_val, 'relative': (abs_val / max_val) if max_val != 0 else 0, } if progress['relative'] > 1.0: log.warning('oh no. more than 100% ??? abs: {}, max: {}'.format( abs_val, max_val)) if run_status['stage'] in run_type['stage_progress_descriptions']: progress['description'] = run_type['stage_progress_descriptions'][ run_status['stage']] status["current_stage"]["progress"] = progress if state == 'completed': status["time_started"] = run_status['time_started'] status["time_completed"] = run_status['time_completed'] return completed().dump(status) elif state == 'running' or state == 'queued' or state == 'created': status["time_started"] = run_status['time_started'] return running().dump(status) elif state == 'error': log.warning( 'handling the run status for state "error" is not implemented') return error().dump(status)