@infect/rda
Version:
RDA public API
147 lines (102 loc) • 4.59 kB
JavaScript
import { Controller } from '@infect/rda-service';
import logd from 'logd';
import Cache from '../Cache.js';
import HTTP2Client from '@distributed-systems/http2-client';
const log = logd.module('rda');
export default class DataController extends Controller {
constructor({
registryClient,
tenantConfig,
}) {
super('data');
// urls to remote services
this.registryClient = registryClient;
this.tenantConfig = tenantConfig;
// cache most used request for up to an hour
this.cache = new Cache();
this.client = new HTTP2Client();
this.enableAction('list');
}
/**
* returns a computed data set
*/
async list(request) {
const tenantConfig = await this.tenantConfig.get(request);
const query = request.query();
const dataSetIdentifier = tenantConfig.dataSet;
const dataSource = 'infect-rda-sample-storage';
const functionName = query && query.functionName ? query.functionName : 'Infect';
const subRoutines = query && query.subRoutines ? query.subRoutines : '[]';
if (this.cache.has(request)) {
return this.cache.get(request);
} else {
// load cluster info
const cluster = await this.getCluster({
dataSetIdentifier,
dataSource,
});
// the cluster is live!
// lets take the first shard as the reducer
const shardHost = cluster.shards[0].url;
let parameters = {};
let rountines = [];
// extract filters, set defaults
if (query.filter && query.filter.length) {
try {
parameters = JSON.parse(query.filter);
} catch (err) {
return request.response().status(400).send(`Failed to parse filters: ${err.message}`);
}
}
if (!parameters.dataVersionStatusIdentifier) {
parameters.dataVersionStatusIdentifier = ['active'];
}
// fix me! hard coded date since data is not delivered anymore!
if (!parameters.fromDate) {
const date = new Date(2022, 5, 1);
parameters.fromDate = date.toISOString();
}
// make sure the subroutines are not DDosing our system
try {
rountines = JSON.parse(subRoutines);
} catch (err) {
return request.response().status(400).send(`Failed to parse subRoutines: ${err.message}`);
}
if (rountines.includes('DiscDiffusionPercentile') || rountines.includes('MICPercentileSubRoutine')) {
if (!parameters.microorganismIds || parameters.microorganismIds.length > 10) {
return request.response().status(400).send(`Cannot apply the DiscDiffusionPercentile or MICPercentile SubRoutine to a dataset that was NOT filtered for a maximum of 10 microorganismIds!`);
}
if (!parameters.compoundSubstanceIds || parameters.compoundSubstanceIds.length > 10) {
return request.response().status(400).send(`Cannot apply the DiscDiffusionPercentile or MICPercentile SubRoutine to a dataset that was NOT filtered for a maximum of 10 compoundSubstanceIds!`);
}
}
// call the reducer
const res = await this.client.post(`${shardHost}/rda-compute.reduction`).expect(201).send({
dataSetIdentifier,
functionName,
parameters: JSON.stringify(parameters),
subRoutines,
shards: cluster.shards,
options: tenantConfig,
});
const responseData = await res.getData();
this.cache.set(request, responseData);
return responseData;
}
}
async getCluster({
dataSetIdentifier,
dataSource,
}) {
if (!this.cluster) {
if (!this.clusterHost) this.clusterHost = await this.registryClient.resolve('rda-cluster');
// get an active infect cluster
const clusterResponse = await this.client.get(`${this.clusterHost}/rda-cluster.cluster-info`).query({
dataSet: dataSetIdentifier,
dataSource,
}).expect(200).send();
this.cluster = await clusterResponse.getData();
}
return this.cluster;
}
}