def get_all(events, context): """returns paged list with the latest status for the samples in the given experiment""" if 'pathParameters' in events: logger.info("events: {}".format(events)) tm = TableManager() table = tm.get_acquisition_table() if events['pathParameters'] is not None and 'sample' in events['pathParameters'] and 'experiment' in events[ 'pathParameters']: logger.info( f"Not the first page // {events['pathParameters']['sample']}// {events['pathParameters']['experiment']}") last = { "id": events['pathParameters']['sample'], "experiment": events['pathParameters']['experiment'] } else: logger.info("First page") last = None try: if last is None: result = table.scan(Limit=500) else: result = table.scan(ExclusiveStartKey=last, Limit=500) items = result['Items'] body = {"items": items} if 'LastEvaluatedKey' in result: body['last_item'] = result['LastEvaluatedKey'] data = { 'statusCode': 200, 'headers': __HTTP_HEADERS__, 'body': json.dumps(body) } return data except Exception as ex: logger.info("QUERY-ERROR: %s" % str(ex)) return { "statusCode": 418, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": ex.args}) } else: return { "statusCode": 404, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": "not supported, need's be called from a http event!"}) }
def test_get_with_reference(requireMocking): # store data tm = TableManager() table = tm.get_acquisition_table() item = { 'sample': '180415dZKsa20_1', 'experiment': '12345', 'acquisition': { 'instrument': 'Leco GC-Tof', 'name': 'GCTOF', 'ionisation': 'positive', 'method': 'gcms' }, 'metadata': { 'class': '382172', 'species': 'rat', 'organ': 'tissue' }, 'userdata': { 'label': 'GP_S_6_006', 'comment': '' }, 'processing': { 'method': 'gcms | test | test | positive' }, 'time': 1525121375499, 'id': '180415dZKsa20_1', 'references': [{ 'name': 'minix', 'value': '12345' }] } try: validate(item, __ACQUISITION_SCHEMA__) table.put_item(Item=tm.sanitize_json_for_dynamo(item)) except ValidationException as vex: result = None fail(str(vex.body)) except ClientError as cer: result = None fail(str(cer.response)) # process data result = get.get({"pathParameters": {"sample": "180415dZKsa20_1"}}, {}) assert result['statusCode'] == 200 assert json.loads(result['body'])["id"] == "180415dZKsa20_1" assert json.loads( result['body'])["acquisition"]["instrument"] == "Leco GC-Tof" assert json.loads(result['body'])["references"][0]["name"] == "minix" assert json.loads(result['body'])["references"][0]["value"] == "12345"
def test_get_experiment(requireMocking, sample_count): tm = TableManager() table = tm.get_acquisition_table() try: for x in range(0, sample_count): table.put_item(Item=tm.sanitize_json_for_dynamo({ "sample": f"test-{x:06d}", "experiment": "1", "id": f"test-{x:06d}", "acquisition": { "instrument": "random", "ionisation": "positive", "method": "test-method" }, "metadata": { "class": f"{x%100}", "species": "rat", "organ": "tissue" }, "userdata": { "label": "GP_S_6_006", "comment": "" }, "processing": { "method": "test-method | random | test | positive" } })) except ValidationException as vex: result = None fail(str(vex.body)) except ClientError as cer: result = None fail(str(cer.response)) page_size = 3 result = experiment.get( {'pathParameters': { 'experiment': '1', 'psize': page_size }}, {}) data = json.loads(result['body']) assert result['statusCode'] == 200 assert len(data['items']) == page_size assert data['last_item']['id'] == 'test-000002'
def get(events, context): """returns the specific element from the storage""" if 'pathParameters' in events: if 'sample' in events['pathParameters']: tm = TableManager() table = tm.get_acquisition_table() versions_table = tm.get_acquisition_table_version() sample = urllib.parse.unquote(events['pathParameters']['sample']) logger.info("looking for sample: {} ( raw its {} )".format(sample, events['pathParameters']['sample'])) result = table.query( KeyConditionExpression=Key('id').eq(sample) ) versions = versions_table.query( KeyConditionExpression=Key('id').eq(sample) ) if "Items" in result and len(result['Items']) > 0: record = result['Items'][0] if "Items" in versions and len(versions['Items']) > 0: record['versions'] = versions['Items'] return { "statusCode": 200, "headers": __HTTP_HEADERS__, "body": json.dumps(record) } else: return { "statusCode": 404, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": "no sample found with this identifier : {}".format( events['pathParameters']['sample'])}) } else: return { "statusCode": 404, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": "sample name is not provided!"}) } else: return { "statusCode": 404, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": "not supported, need's be called from a http event!"}) }
def get(events, context): """returns paged list with the latest status for the samples in the given experiment""" if 'pathParameters' in events: if 'experiment' in events['pathParameters']: expId = events['pathParameters']['experiment'] if 'psize' in events['pathParameters']: page_size = int(events['pathParameters']['psize']) else: page_size = 25 query_params = { 'IndexName': 'experiment-id-index', 'Select': 'ALL_ATTRIBUTES', 'KeyConditionExpression': Key('experiment').eq(expId), 'Limit': page_size } if 'lastSample' in events['pathParameters']: logger.info( f"Not the first page // {events['pathParameters']['lastSample']}" ) query_params['ExclusiveStartKey'] = { "experiment": expId, "id": events['pathParameters']['lastSample'] } tm = TableManager() table = tm.get_acquisition_table() try: result = table.query(**query_params) items = result['Items'] body = {"items": items} if 'LastEvaluatedKey' in result: body['last_item'] = result['LastEvaluatedKey'] data = { 'statusCode': 200, 'headers': __HTTP_HEADERS__, 'body': json.dumps(body) } return data except Exception as ex: logger.info("QUERY-ERROR: %s" % str(ex)) return { "statusCode": 418, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": ex.args}) } else: return { "statusCode": 422, "headers": __HTTP_HEADERS__, "body": json.dumps({"error": "sample name is not provided!"}) } else: return { "statusCode": 404, "headers": __HTTP_HEADERS__, "body": json.dumps({ "error": "not supported, need's be called from a http event!" }) }
def store_sample_for_job(event, context): """ stores an associated sample for an job :param event: :param context: :return: """ body = json.loads(event['body']) try: validate(body, __SAMPLE_JOB_SCHEMA__) except Exception as e: logger.info(f"received body was considered invalid: {body}") traceback.print_exc() return { 'body': json.dumps({ 'state': str(FAILED), 'reason': str(e) }), 'statusCode': 503, 'isBase64Encoded': False, 'headers': __HTTP_HEADERS__ } tracking = body.get('meta', {}).get('tracking', []) meta = body.get('meta', {}) meta.pop('tracking', None) sample = body.get('sample') job = body.get("job") try: # overwrite tracking states and extension if it's provided for track in tracking: if 'extension' in track: fileHandle = "{}.{}".format(sample, track['extension']) else: fileHandle = None save_sample_state(sample=sample, state=track['state'], fileHandle=fileHandle) if len(meta) > 0: # update the class here by updating the acquisition part # 1. get acquisition data # 2. set new metadata tm = TableManager() acqtable = tm.get_acquisition_table() result = acqtable.query( KeyConditionExpression=Key('id').eq(sample)) if "Items" in result and len(result['Items']) > 0: data = result['Items'][0] else: timestamp = int(time.time() * 1000) data = { 'time': timestamp, 'id': sample, 'sample': sample, 'experiment': _fetch_experiment(sample), 'acquisition': { 'instrument': 'unknown', 'ionisation': 'unknown', 'method': 'unknown' }, 'processing': { 'method': 'unknown' }, } try: data = Merge().data_merge(data, meta) store_acquisition_data(data, tm) except Exception as e: logger.info(f"generated data was considered invalid: {data}") traceback.print_exc() return { 'body': json.dumps({ 'state': str(FAILED), 'reason': str(traceback.format_exc()) }), 'statusCode': 503, 'isBase64Encoded': False, 'headers': __HTTP_HEADERS__ } set_sample_job_state(job=job, sample=sample, state=SCHEDULING) return { 'body': json.dumps({ 'state': str(SCHEDULING), 'job': job, 'sample': sample, 'reason': 'sample was submitted' }), 'statusCode': 200, 'isBase64Encoded': False, 'headers': __HTTP_HEADERS__ } except Exception as e: # update job state in the system to failed with the related reason error_diagnostics = traceback.format_exc() set_sample_job_state(job=job, sample=sample, state=FAILED, reason=f"{str(e)} = {error_diagnostics}") traceback.print_exc() return { 'body': json.dumps({ 'state': str(FAILED), 'job': job, 'sample': sample, 'reason': str(e) }), 'statusCode': 500, 'isBase64Encoded': False, 'headers': __HTTP_HEADERS__ }