s3Helper.ts
unknown
typescript
2 years ago
5.3 kB
7
Indexable
import {API, graphqlOperation} from 'aws-amplify';
import {
endSimpleTrainConsistTrip,
getPresignedPostUrl,
} from '@graphql/queriesFn';
// Utils
import {
deleteGzipFile,
readAndDecompressGzipFile,
readGzipDirectory,
} from '@Utils/fileHelper';
// Types
import {File, S3PathKey} from '@Types';
// Apollo
import apolloClient from '@ApolloClient/apolloClient';
/**
* Requests an S3 pre-signed URL that can be used to upload files.
* @param {string} s3PathKey - An enum value specifying the data type (e.g GPS, MODELS, etc.).
* @returns {Promise<string>} - An S3 pre-signed URL.
*/
const getS3PreSignedUrl = async ({s3PathKey}: {s3PathKey: string}) => {
try {
const client = await apolloClient();
const response = await client.query({
query: getPresignedPostUrl({
s3_path_key: s3PathKey,
}),
});
console.log('response', response, s3PathKey);
return response;
} catch (error) {
console.log('error', error);
return error;
}
};
/**
* This is an asynchronous function that ends a simple train consist trip by calling an API with the
* necessary parameters.
* @param - The function `endTrip` takes in an object with three properties as its parameter:
*/
const endTrip = async (
createdBy: string,
endDateUtc: string,
simpleTrainConsistId: string,
) => {
try {
const client = await apolloClient();
await client.mutate({
mutation: endSimpleTrainConsistTrip({
createdBy,
endDateUtc,
simpleTrainConsistId,
}),
});
} catch (error) {
console.log(error);
}
};
/**
* Uploads a single file to S3 using a pre-signed URL.
* @param {string} url - The pre-signed URL used to upload the file.
* @param {any} postRequestFields - Request headers
* @param {File} file - An object containing information about the file to upload. It should have the following properties:
* - file_name: The name of the file, including the extension.
* - file_type: The MIME type of the file.
* - file_uri: The URI of the file to upload.
* @returns {Promise<void>} - A promise that resolves when the file has been successfully uploaded to S3.
*/
const uploadSingleFileToS3 = async (
url: string,
postRequestFields: any,
file: File,
s3PathKey: S3PathKey,
) => {
console.log(`Uploading ${file.name}...`);
const fileContent = await readAndDecompressGzipFile(s3PathKey, file.name);
const fileContentObject = JSON.parse(fileContent);
endTrip(
fileContentObject.created_at_utc,
fileContentObject.end_trip_timestamp_utc,
fileContentObject.simple_train_consist_id,
);
const formData = new FormData();
// Add post request fields to body requests
for (const [key, value] of Object.entries(postRequestFields)) {
formData.append(key, value);
}
formData.append('file', {
...file,
});
const response = await fetch(url, {
method: 'POST',
body: formData,
headers: {
'Content-Type': `multipart/form-data`,
},
});
return response;
};
/**
* Uploads an array of .gzip files read from native file system to S3 using pre-signed URLs.
* @param {S3PathKey} s3PathKey - An enum value specifying the data type (e.g GPS, MODEL, etc.).
*/
export const uploadAllFilesToS3 = async (s3PathKey: S3PathKey) => {
const files: File[] = await readGzipDirectory(s3PathKey);
for (const file of files) {
// 1. Request for a pre-signed url given railroad_id, timestamp and file format
let preSignedUrl, postRequestFields;
try {
const fileMetaData = file.name.split(':');
// File name on S3 is just the Simple Train Consist
const fileNameOnS3 = fileMetaData[5];
const preSignedUrlResponse: any = await getS3PreSignedUrl({
s3PathKey: `${s3PathKey}/railroad=${fileMetaData[0]}/year=${fileMetaData[1]}/month=${fileMetaData[2]}/day=${fileMetaData[3]}/${fileNameOnS3}`,
});
const presignedPostUrl = preSignedUrlResponse?.data?.presigned_post_url;
const {response_code, presigned_url, post_request_fields} =
presignedPostUrl;
const parsed_post_request_fields = JSON.parse(post_request_fields);
if (response_code === 409) {
console.error(`${file.name} already exists`);
deleteGzipFile(s3PathKey, file.name);
continue;
}
preSignedUrl = presigned_url;
postRequestFields = parsed_post_request_fields;
} catch (error) {
console.error(`Error getting pre-signed URL for ${file.name}: ${error}`);
continue;
}
// 2. Upload the file to S3 using the pre-signed URL
try {
const response = await uploadSingleFileToS3(
preSignedUrl,
postRequestFields,
file,
s3PathKey,
);
if (response.status === 409) {
console.log(`${file.name} already exists`);
deleteGzipFile(s3PathKey, file.name);
return;
}
if (response.status !== 200 && response.status !== 204) {
console.log(`${file.name} uploaded failed!`);
return;
}
console.log(`${file.name} uploaded successfully!`);
// Delete gzip file after uploading successfully
deleteGzipFile(s3PathKey, file.name);
} catch (error) {
console.error(`Error uploading ${file.name}: ${error}`);
}
}
};
Editor is loading...