Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nodejs20.x - migrate sample from aws-sdk v2 to v3 #10

Merged
merged 6 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ jobs:
python-version: '3.9'

- name: Setup Nodejs
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 16
node-version: 20.x

- name: Install dependencies
run: |
Expand Down
18 changes: 11 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
{
"dependencies": {
"aws-sdk": "^2.1386.0",
"serverless": "^3.31.0",
"serverless-lift": "^1.26.1",
"serverless-localstack": "^1.1.1"
}
"type":"module",
"dependencies": {
"aws-sdk": "^2.1386.0",
"serverless": "^3.31.0",
"serverless-lift": "^1.26.1",
"serverless-localstack": "^1.1.1",
"@aws-sdk/client-s3": "^3.0.0",
"@aws-sdk/client-sqs": "^3.0.0",
"@aws-sdk/client-ses": "^3.0.0",
"@aws-sdk/client-transcribe": "^3.0.0"
}
}

6 changes: 3 additions & 3 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ plugins:
custom:
defaultStage: local
profile: default
runtime: nodejs14.x
runtime: nodejs20.x
localstack:
stages: [local]

provider:
name: aws
runtime: nodejs14.x
runtime: nodejs20.x
environment:
S3_AUDIO_BUCKET: ${self:service}-${opt:stage, self:provider.stage}-records
S3_TRANSCRIPTION_BUCKET: ${self:service}-${opt:stage, self:provider.stage}-transcriptions
Expand All @@ -45,7 +45,7 @@ provider:

functions:
transcribe:
handler: src/transcribe.process
handler: src/transcribe.transcribe_process
events:
- s3:
bucket: ${self:provider.environment.S3_AUDIO_BUCKET}
Expand Down
17 changes: 12 additions & 5 deletions src/jobs.js → src/jobs.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
'use strict';

const awsSdk = require('aws-sdk');
import { S3, ListObjectsCommand } from "@aws-sdk/client-s3";

const endpoint = process.env.AWS_ENDPOINT_URL
const s3 = new awsSdk.S3({endpoint: endpoint, s3ForcePathStyle: true});
const s3 = new S3({
endpoint: endpoint,
forcePathStyle: true,
credentials: {
accessKeyId:'test',
secretAccessKey:'test'
},
});

// This function is triggered by an HTTP request using the GET method.
// The function returns a list of all the transcription jobs stored in the S3 bucket.
exports.list = async (event, context, callback) => {
export const list = async (event, context, callback) => {
var htmlStr = `
<!DOCTYPE html>
<html>
Expand All @@ -33,8 +40,8 @@ exports.list = async (event, context, callback) => {
};

try {
const { Contents } = await s3.listObjects(params).promise();
const keys = Contents.map(({ Key }) => Key);
const data = await s3.send(new ListObjectsCommand(params));
const keys = data.Contents.map(({ Key }) => Key);
keys.forEach(object => {
htmlStr += `<li><a href="https://s3.localhost.localstack.cloud:4566/${bucketName}/${object}">${object}</a></li>`
});
Expand Down
30 changes: 15 additions & 15 deletions src/presign.js → src/presign.mjs
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
const AWS = require('aws-sdk');
const credentials = new AWS.Credentials({
accessKeyId: 'test',
secretAccessKey: 'test'
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { PutObjectCommand, S3 } from '@aws-sdk/client-s3';

const s3 = new S3({
endpoint: 'https://s3.localhost.localstack.cloud:4566',
forcePathStyle: true,
credentials: {
accessKeyId:'test',
secretAccessKey:'test'
},
});
AWS.config.credentials = credentials;

const s3 = new AWS.S3(
{
endpoint: 'https://s3.localhost.localstack.cloud:4566',
s3ForcePathStyle: true,
}
);

// This function is triggered by an HTTP request using the POST method.
// The function returns a presigned URL to upload a file to S3.
exports.post = async (event) => {
export const post = async (event) => {
const bucketName = 'aws-node-sample-transcribe-s3-local-records';
const key = event.queryStringParameters.filename;
const expiration = 3600;

try {
const url = await s3.getSignedUrlPromise('putObject', {
const url = await getSignedUrl(s3, new PutObjectCommand({
Bucket: bucketName,
Key: key,
Expires: expiration,
}), {
expiresIn: expiration,
});
console.log('Presigned URL: ', url);
return {
statusCode: 200,
body: {"url": url},
Expand Down
101 changes: 0 additions & 101 deletions src/queue.js

This file was deleted.

122 changes: 122 additions & 0 deletions src/queue.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { S3, GetObjectCommand } from "@aws-sdk/client-s3";
import { SES, SendEmailCommand } from "@aws-sdk/client-ses";
import { SQS, SendMessageCommand } from "@aws-sdk/client-sqs";

const endpoint = process.env.AWS_ENDPOINT_URL;
const sqs = new SQS({
endpoint: endpoint,
credentials: {
accessKeyId:'test',
secretAccessKey:'test'
},
});
const ses = new SES({
endpoint: endpoint,
credentials: {
accessKeyId:'test',
secretAccessKey:'test'
},
});
const s3Client = new S3({
endpoint: endpoint,
forcePathStyle: true,
credentials: {
accessKeyId:'test',
secretAccessKey:'test'
},
});
const queueUrl = `${endpoint}/000000000000/aws-node-sample-transcribe-s3-local-jobs`;
const transcriptionBucket = process.env.S3_TRANSCRIPTION_BUCKET

// This function consumes the event from s3 PutObject and pushes a new message to SQS.
const producer = async (event, context, callback) => {
let statusCode = 200;
let message;

try {
// Get the record from the s3 event
const records = event.Records;
const sqsSendMessagePromises = records.map(async (record) => {
const params = {
Bucket: transcriptionBucket,
Key: record.s3.object.key,
};

try {
const data = await s3Client.send(new GetObjectCommand(params));
const str = await data.Body.transformToString();
console.log("str: ", str);

const jsonContent = await JSON.parse(str);
console.log("jsonContent: ", jsonContent);

// Send message to SQS queue
const sendMessageParams = {
QueueUrl: queueUrl,
MessageBody: jsonContent.results.transcripts[0].transcript,
MessageAttributes: {
AttributeName: {
StringValue: "Attribute Value",
DataType: "String",
},
},
};
await sqs.send(new SendMessageCommand(sendMessageParams));
} catch (err) {
console.error("Error getting object from S3 bucket: ", transcriptionBucket, err);
throw err;
}
});

await Promise.all(sqsSendMessagePromises);
callback(null, { message: 'Message sent successfully' });
message = "Message accepted!";
} catch (error) {
console.log(error);
message = error.message;
statusCode = 500;
}

return {
statusCode,
body: JSON.stringify({
message,
}),
};
};

// The function is triggered by the SQS queue.
// A function is triggered whenever there is a new message in the queue.
// When the function is triggered, it sends an email to '[email protected]'
const consumer = async (event) => {
for (const record of event.Records) {
const params = {
Destination: {
ToAddresses: ["[email protected]"] // Email address/addresses that you want to send your email
},
Message: {
Body: {
Text: {
Charset: "UTF-8",
Data: `Hey there! Here is your generated transcribed file:\n${record.body}`
}
},
Subject: {
Charset: "UTF-8",
Data: "Test Email - JOB COMPLETED SUCCESSFULLY"
}
},
Source: "[email protected]" // Sender email address
};

try {
// Send email to recipient
const result = await ses.send(new SendEmailCommand(params));
console.log("Email sent successfully: ", result);
} catch (error) {
console.error("Error sending email: ", error);
}
}
};

export { producer, consumer };
Loading
Loading