Skip to content

Commit

Permalink
Merge pull request #343 from hms-dbmi-cellenics/1836-metadata-tracks-…
Browse files Browse the repository at this point in the history
…endpoints

[BIOMAGE-1836] Implement metadata tracks-specific endpoints
  • Loading branch information
cosa65 authored May 3, 2022
2 parents 4acc269 + a585166 commit 5b3d04e
Show file tree
Hide file tree
Showing 15 changed files with 948 additions and 19 deletions.
80 changes: 80 additions & 0 deletions src/api.v2/controllers/metadataTrackController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
const MetadataTrack = require('../model/MetadataTrack');

const getLogger = require('../../utils/getLogger');
const { OK, NotFoundError } = require('../../utils/responses');

const logger = getLogger('[MetadataTrackController] - ');

const createMetadataTrack = async (req, res) => {
const {
params: { experimentId, metadataTrackKey },
} = req;

logger.log(`Creating metadata track ${metadataTrackKey} in experiment ${experimentId}`);

await new MetadataTrack().createNewMetadataTrack(experimentId, metadataTrackKey);

logger.log(`Finished creating metadata track ${metadataTrackKey} in experiment ${experimentId}`);

res.json(OK());
};

const patchMetadataTrack = async (req, res) => {
const {
params: { experimentId, metadataTrackKey: oldKey },
body: { key },
} = req;

logger.log(`Patching metadata track ${oldKey} in experiment ${experimentId}`);

const result = await new MetadataTrack()
.update({ experiment_id: experimentId, key: oldKey }, { key });

if (result.length === 0) {
throw new NotFoundError(`Metadata track ${oldKey} not found`);
}

logger.log(`Finished patching metadata track ${oldKey} in experiment ${experimentId}, changed to ${key}`);
res.json(OK());
};

const deleteMetadataTrack = async (req, res) => {
const {
params: { experimentId, metadataTrackKey },
} = req;

logger.log(`Creating metadata track ${metadataTrackKey} in experiment ${experimentId}`);

const result = await new MetadataTrack().delete(
{ experiment_id: experimentId, key: metadataTrackKey },
);

if (result.length === 0) {
throw new NotFoundError(`Metadata track ${metadataTrackKey} not found`);
}

logger.log(`Finished creating metadata track ${metadataTrackKey} in experiment ${experimentId}`);

res.json(OK());
};

const patchValueForSample = async (req, res) => {
const {
params: { experimentId, sampleId, metadataTrackKey },
body: { value },
} = req;

logger.log(`Patching value of metadata track ${metadataTrackKey} in sample ${sampleId} in experiment ${experimentId}`);

await new MetadataTrack().patchValueForSample(experimentId, sampleId, metadataTrackKey, value);

logger.log(`Finished patching value of metadata track ${metadataTrackKey} in sample ${sampleId} in experiment ${experimentId}, changed to ${value}`);
res.json(OK());
};

module.exports = {
createMetadataTrack,
patchMetadataTrack,
deleteMetadataTrack,
patchValueForSample,
};
2 changes: 1 addition & 1 deletion src/api.v2/controllers/sampleController.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const deleteSample = async (req, res) => {
logger.log(`Deleting sample ${sampleId} from experiment ${experimentId}`);

await sqlClient.get().transaction(async (trx) => {
await new Sample(trx).destroy(sampleId);
await new Sample(trx).deleteById(sampleId);
await new Experiment(trx).deleteSample(experimentId, sampleId);
});

Expand Down
11 changes: 10 additions & 1 deletion src/api.v2/model/BasicModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,19 @@ class BasicModel {
.timeout(this.timeout);
}

destroy(id) {
deleteById(id) {
return this.sql.del()
.from(this.tableName)
.where({ id })
.returning(this.selectableProps)
.timeout(this.timeout);
}

delete(filters) {
return this.sql.del()
.from(this.tableName)
.where(filters)
.returning(this.selectableProps)
.timeout(this.timeout);
}
}
Expand Down
52 changes: 45 additions & 7 deletions src/api.v2/model/MetadataTrack.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,48 @@ const BasicModel = require('./BasicModel');
const sqlClient = require('../../sql/sqlClient');

const tableNames = require('./tableNames');
const { NotFoundError } = require('../../utils/responses');

const sampleFields = [
'id',
'experiment_id',
'name',
'sample_technology',
'created_at',
'updated_at',
'key',
];

class MetadataTrack extends BasicModel {
constructor(sql = sqlClient.get()) {
super(sql, tableNames.METADATA_TRACK, sampleFields);
}

async createNewMetadataTrack(experimentId, key) {
const sampleIds = await this.sql.select(['id'])
.from(tableNames.SAMPLE)
.where({ experiment_id: experimentId });

await this.sql.transaction(async (trx) => {
const response = await trx
.insert({
experiment_id: experimentId,
key,
})
.returning(['id'])
.into(this.tableName);

if (sampleIds.length === 0) {
return;
}

const [{ id: metadataTrackId }] = response;

const valuesToInsert = sampleIds.map(({ id: sampleId }) => ({
metadata_track_id: metadataTrackId,
sample_id: sampleId,
}));

await trx(tableNames.SAMPLE_IN_METADATA_TRACK_MAP).insert(valuesToInsert);
});
}

async createNewSampleValues(experimentId, sampleId) {
const tracks = await this.sql.select(['id'])
.from(tableNames.METADATA_TRACK)
Expand All @@ -30,11 +57,22 @@ class MetadataTrack extends BasicModel {
const valuesToInsert = tracks.map(({ id }) => ({
metadata_track_id: id,
sample_id: sampleId,
value: 'N.A.',
}));

await this.sql(tableNames.SAMPLE_IN_METADATA_TRACK_MAP)
.insert(valuesToInsert);
await this.sql(tableNames.SAMPLE_IN_METADATA_TRACK_MAP).insert(valuesToInsert);
}

async patchValueForSample(experimentId, sampleId, key, value) {
const [{ id }] = await this.find({ experiment_id: experimentId, key });

const result = await this.sql(tableNames.SAMPLE_IN_METADATA_TRACK_MAP)
.update({ value })
.where({ metadata_track_id: id, sample_id: sampleId })
.returning(['metadata_track_id']);

if (result.length === 0) {
throw new NotFoundError(`Metadata track ${key} or sample ${sampleId} don't exist`);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/api.v2/model/__mocks__/BasicModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ const stub = {
findById: jest.fn(),
update: jest.fn(),
updateById: jest.fn(),
destroy: jest.fn(),
delete: jest.fn(),
deleteById: jest.fn(),
};

const BasicModel = jest.fn().mockImplementation(() => stub);
Expand Down
2 changes: 2 additions & 0 deletions src/api.v2/model/__mocks__/MetadataTrack.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
const BasicModel = require('./BasicModel')();

const stub = {
createNewMetadataTrack: jest.fn(),
createNewSampleValues: jest.fn(),
patchValueForSample: jest.fn(),
...BasicModel,
};

Expand Down
27 changes: 27 additions & 0 deletions src/api.v2/routes/metadataTrack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const {
createMetadataTrack,
patchMetadataTrack,
patchValueForSample,
deleteMetadataTrack,
} = require('../controllers/metadataTrackController');

const { expressAuthorizationMiddleware } = require('../middlewares/authMiddlewares');

module.exports = {
'metadataTrack#createMetadataTrack': [
expressAuthorizationMiddleware,
(req, res, next) => createMetadataTrack(req, res).catch(next),
],
'metadataTrack#patchMetadataTrack': [
expressAuthorizationMiddleware,
(req, res, next) => patchMetadataTrack(req, res).catch(next),
],
'metadataTrack#patchSampleInMetadataTrackValue': [
expressAuthorizationMiddleware,
(req, res, next) => patchValueForSample(req, res).catch(next),
],
'metadataTrack#deleteMetadataTrack': [
expressAuthorizationMiddleware,
(req, res, next) => deleteMetadataTrack(req, res).catch(next),
],
};
Loading

0 comments on commit 5b3d04e

Please sign in to comment.