From 3ee03ab9a39ed2544e7f4c04d78396430b965427 Mon Sep 17 00:00:00 2001 From: cosa65 Date: Thu, 5 Oct 2023 15:04:45 -0300 Subject: [PATCH] Add begin sample file upload endpoint, decouple it from create sample file Signed-off-by: cosa65 --- .../controllers/sampleFileController.js | 26 +++++-- src/api.v2/routes/sampleFile.js | 6 +- src/specs/api.v2.yaml | 73 ++++++++++++++++++- .../BeginSampleFileUpload.v2.yaml | 21 ++++++ .../samples-bodies/CreateSampleFile.v2.yaml | 9 --- 5 files changed, 117 insertions(+), 18 deletions(-) create mode 100644 src/specs/models/samples-bodies/BeginSampleFileUpload.v2.yaml diff --git a/src/api.v2/controllers/sampleFileController.js b/src/api.v2/controllers/sampleFileController.js index 0d372e751..ca3fd588c 100644 --- a/src/api.v2/controllers/sampleFileController.js +++ b/src/api.v2/controllers/sampleFileController.js @@ -13,7 +13,7 @@ const logger = getLogger('[SampleFileController] - '); const createFile = async (req, res) => { const { params: { experimentId, sampleId, sampleFileType }, - body: { sampleFileId, size, metadata = {} }, + body: { sampleFileId, size }, } = req; logger.log(`Creating file ${sampleFileType} for sample ${sampleId} in experiment ${experimentId}`); @@ -25,19 +25,31 @@ const createFile = async (req, res) => { upload_status: 'uploading', }; - let uploadUrlParams; + await sqlClient.get().transaction(async (trx) => { await new SampleFile(trx).create(newSampleFile); await new Sample(trx).setNewFile(sampleId, sampleFileId, sampleFileType); - - logger.log(`Getting multipart upload urls for ${experimentId}, sample ${sampleId}, sampleFileType ${sampleFileType}`); - uploadUrlParams = await getFileUploadUrls(sampleFileId, metadata, size, bucketNames.SAMPLE_FILES); }); logger.log(`Finished creating sample file for experiment ${experimentId}, sample ${sampleId}, sampleFileType ${sampleFileType}`); - res.json(uploadUrlParams); + + res.json(OK()); +}; + +const beginUpload = async (req, res) => { + const { + params: { experimentId, sampleFileId }, + body: { metadata, size }, + } = req; + + logger.log(`Generating multipart upload urls for ${experimentId}, sample file ${sampleFileId}`); + const uploadParams = await getFileUploadUrls( + sampleFileId, metadata, size, bucketNames.SAMPLE_FILES, + ); + + res.json(uploadParams); }; const patchFile = async (req, res) => { @@ -66,5 +78,5 @@ const getS3DownloadUrl = async (req, res) => { }; module.exports = { - createFile, patchFile, getS3DownloadUrl, + createFile, beginUpload, patchFile, getS3DownloadUrl, }; diff --git a/src/api.v2/routes/sampleFile.js b/src/api.v2/routes/sampleFile.js index 552b67141..7c00cff2b 100644 --- a/src/api.v2/routes/sampleFile.js +++ b/src/api.v2/routes/sampleFile.js @@ -1,5 +1,5 @@ const { - createFile, patchFile, getS3DownloadUrl, + createFile, patchFile, getS3DownloadUrl, beginUpload, } = require('../controllers/sampleFileController'); const { expressAuthorizationMiddleware } = require('../middlewares/authMiddlewares'); @@ -13,6 +13,10 @@ module.exports = { expressAuthorizationMiddleware, (req, res, next) => patchFile(req, res).catch(next), ], + 'sampleFile#beginUpload': [ + expressAuthorizationMiddleware, + (req, res, next) => beginUpload(req, res).catch(next), + ], 'sampleFile#downloadUrl': [ expressAuthorizationMiddleware, (req, res, next) => getS3DownloadUrl(req, res).catch(next), diff --git a/src/specs/api.v2.yaml b/src/specs/api.v2.yaml index ba38ea4d0..4afbc623e 100644 --- a/src/specs/api.v2.yaml +++ b/src/specs/api.v2.yaml @@ -1439,7 +1439,7 @@ paths: content: application/json: schema: - type: object + $ref: "#/components/schemas/HTTPSuccess" "400": description: Bad Request content: @@ -1537,6 +1537,75 @@ paths: application/json: schema: $ref: "#/components/schemas/HTTPError" + "/experiments/{experimentId}/sampleFiles/{sampleFileId}/beginUpload": + post: + summary: Begins the multipart upload of a sample file + description: Begins the multipart upload of a sample file + operationId: beginUpload + x-eov-operation-id: sampleFile#beginUpload + x-eov-operation-handler: routes/sampleFile + parameters: + - name: experimentId + required: true + in: path + description: ID of the experiment. + schema: + type: string + - name: sampleFileId + in: path + description: Type of the file. + required: true + schema: + type: string + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/BeginSampleFileUpload" + responses: + "200": + description: Success + content: + application/json: + schema: + type: object + properties: + signedUrls: + type: array + items: + type: string + uploadId: + type: string + "400": + description: Bad Request + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + "401": + description: The request lacks authentication credentials. + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + "403": + description: Forbidden request for this user. + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + "404": + description: Not found error. + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" + "424": + description: Terms not accepted error. + content: + application/json: + schema: + $ref: "#/components/schemas/HTTPError" /completeMultipartUpload: post: summary: Complete a multipart upload @@ -2481,6 +2550,8 @@ components: $ref: ./models/samples-bodies/CreateSampleFile.v2.yaml PatchSampleFile: $ref: ./models/samples-bodies/PatchSampleFile.v2.yaml + BeginSampleFileUpload: + $ref: ./models/samples-bodies/BeginSampleFileUpload.v2.yaml UpdateSamplesOptions: $ref: ./models/samples-bodies/UpdateSamplesOptions.v2.yaml CellSets: diff --git a/src/specs/models/samples-bodies/BeginSampleFileUpload.v2.yaml b/src/specs/models/samples-bodies/BeginSampleFileUpload.v2.yaml new file mode 100644 index 000000000..427212573 --- /dev/null +++ b/src/specs/models/samples-bodies/BeginSampleFileUpload.v2.yaml @@ -0,0 +1,21 @@ +title: Begin sample file multipart upload +description: 'Data to begin an s3 multipart upload' +type: object +properties: + size: + type: number + metadata: + description: Metadata to append to the s3 object on upload + type: object + properties: + cellrangerVersion: + type: string + oneOf: + - pattern: v2 + - pattern: v3 + +required: + - size + - metadata + +additionalProperties: false \ No newline at end of file diff --git a/src/specs/models/samples-bodies/CreateSampleFile.v2.yaml b/src/specs/models/samples-bodies/CreateSampleFile.v2.yaml index dfec7cc76..908bd3629 100644 --- a/src/specs/models/samples-bodies/CreateSampleFile.v2.yaml +++ b/src/specs/models/samples-bodies/CreateSampleFile.v2.yaml @@ -6,15 +6,6 @@ properties: type: string size: type: number - metadata: - description: Metadata to append to the s3 object on upload - type: object - properties: - cellrangerVersion: - type: string - oneOf: - - pattern: v2 - - pattern: v3 required: - sampleFileId