As a Node.js developer, you might have come across scenarios where you need to work with different AWS services, such as Amazon SQS. In this article, we will explore how to load credentials from the environment variables, retrieve a message from SQS, update its visibility, and delete the message when the work is completed using TypeScript and the client-sqs
library.
Prerequisites
Before proceeding with this article, you need to have the following installed on your system:
- Node.js and NPM installed.
- An AWS account with access to Amazon SQS.
- The AWS CLI configured with your credentials.
Setting up the Environment
To begin, let's create a new Node.js project and install the required dependencies. Open your terminal and follow these steps:
-
Create a new directory and navigate into it.
mkdir sqs-example cd sqs-example
-
Initialize a new Node.js project using NPM.
npm init -y
-
Install the
aws-sdk
andclient-sqs
packages as dependencies.
npm install aws-sdk client-sqs
Retrieving a Message from SQS
In this section, we will create a function to retrieve a message from SQS.
Create a new file named
sqs.ts
in the project's root directory.-
Import the necessary modules and initialize a new SQS client.
import { fromEnv } from "@aws-sdk/credential-provider-env"; import { SQSClient, ReceiveMessageCommand } from "@aws-sdk/client-sqs"; const credentials = fromEnv(); const sqsClient = new SQSClient({ credentials });
-
Define a new function named
getMessage
that accepts a queue URL and returns a message.
async function getMessage(queueUrl: string): Promise<string> { const command = new ReceiveMessageCommand({ QueueUrl: queueUrl, MaxNumberOfMessages: 1, }); const response = await sqsClient.send(command); if (response.Messages?.length) { const message = response.Messages[0]; return message.Body!; } throw new Error("No messages found in the queue"); }
-
Export the
getMessage
function.
export { getMessage };
Updating Message Visibility
In this section, we will create a function to update the visibility of a message.
Add a new function named updateMessageVisibility
to the sqs.ts
file.
```typescript
import { ChangeMessageVisibilityCommand } from "@aws-sdk/client-sqs";
async function updateMessageVisibility(
queueUrl: string,
receiptHandle: string,
visibilityTimeout: number
): Promise<void> {
const command = new ChangeMessageVisibilityCommand({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
VisibilityTimeout: visibilityTimeout,
});
await sqsClient.send(command);
}
```
Deleting a Message
In this section, we will create a function to delete a message from SQS.
Add a new function named deleteMessage
to the sqs.ts
file.
import { DeleteMessageCommand } from "@aws-sdk/client-sqs";
async function deleteMessage(queueUrl: string, receiptHandle
): Promise {
const command = new DeleteMessageCommand({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
});
await sqsClient.send(command);
}
Putting it all Together
In this section, we will put together all the functions we created and create a new file to run our code.
Create a new file named
index.ts
in the project's root directory.-
Import the
getMessage
,updateMessageVisibility
, anddeleteMessage
functions from thesqs.ts
file.
import { getMessage } from "./sqs"; import { updateMessageVisibility } from "./sqs"; import { deleteMessage } from "./sqs";
-
Define the queue URL and visibility timeout.
const queueUrl = "https://sqs.<region>.amazonaws.com/<account-id>/<queue-name>"; const visibilityTimeout = 60;
-
Call the
getMessage
function to retrieve a message from the queue.
const message = await getMessage(queueUrl);
-
Process the message and call the
updateMessageVisibility
function to extend its visibility timeout.
// TODO: DO THE WORK await updateMessageVisibility(queueUrl, receiptHandle, visibilityTimeout);
-
Delete the message when the work is completed.
await deleteMessage(queueUrl, receiptHandle);
Running the Code
To run the code, execute the following command in your terminal:
ts-node index.ts
This will execute the index.ts
file and retrieve a message from the queue. You can replace the TODO comment with your own code to process the message.
Conclusion
In this article, we explored how to load credentials from the environment variables, retrieve a message from SQS, update its visibility, and delete the message when the work is completed using TypeScript and the client-sqs
library. By following the steps outlined in this article, you should now be able to work with SQS in your Node.js applications with ease.
Remember to replace the placeholders in the queueUrl
variable with your own values. Additionally, you can customize the visibilityTimeout
variable to suit your needs.
We hope that this article has helped you learn how to work with SQS in your Node.js applications using TypeScript. Remember that this is just a starting point, and there is a lot more to learn about SQS and AWS services in general. If you want to learn more, we recommend checking out the official AWS documentation, as well as other resources available online. Happy coding!
BONUS TESTS
We will be using the Jest testing framework to write our tests. If you haven't installed Jest yet, you can install it using the following command:
npm install --save-dev jest
After installing Jest, create a new file named sqs.test.ts
in the same directory as the sqs.ts
file. This file will contain our unit tests.
Testing the getMessage Function
First, let's write a unit test for the getMessage
function. The purpose of this function is to retrieve a message from SQS.
Here's an example test:
import { getMessage } from "./sqs";
import { ReceiveMessageCommand } from "@aws-sdk/client-sqs";
jest.mock("@aws-sdk/client-sqs", () => ({
SQSClient: jest.fn(() => ({
send: jest.fn(),
})),
ReceiveMessageCommand: jest.fn(),
}));
describe("getMessage", () => {
it("should retrieve a message from SQS", async () => {
// Arrange
const queueUrl = "https://sqs.<region>.amazonaws.com/<account-id>/<queue-name>";
const messageBody = "test message";
const receiptHandle = "test-receipt-handle";
const command = new ReceiveMessageCommand({
QueueUrl: queueUrl,
MaxNumberOfMessages: 1,
VisibilityTimeout: 0,
});
const expectedMessage = {
Body: messageBody,
ReceiptHandle: receiptHandle,
};
// Mock the SQS client to return the expected message
const mockSend = jest.fn().mockResolvedValueOnce({
Messages: [expectedMessage],
});
const SQSClient = require("@aws-sdk/client-sqs").SQSClient;
SQSClient.prototype.send = mockSend;
const ReceiveMessageCommand = require("@aws-sdk/client-sqs").ReceiveMessageCommand;
ReceiveMessageCommand.mockReturnValueOnce(command);
// Act
const message = await getMessage(queueUrl);
// Assert
expect(mockSend).toHaveBeenCalledTimes(1);
expect(ReceiveMessageCommand).toHaveBeenCalledTimes(1);
expect(ReceiveMessageCommand).toHaveBeenCalledWith({
QueueUrl: queueUrl,
MaxNumberOfMessages: 1,
VisibilityTimeout: 0,
});
expect(message).toEqual(expectedMessage);
});
});
In this test, we are mocking the client-sqs
library to return a test message. We then call the getMessage
function and assert that it retrieves the expected message from SQS.
Testing the updateMessageVisibility Function
Next, let's write a unit test for the updateMessageVisibility
function. The purpose of this function is to update the visibility of a message in SQS.
Here's an example test:
import { updateMessageVisibility } from "./sqs";
import { ChangeMessageVisibilityCommand } from "@aws-sdk/client-sqs";
jest.mock("@aws-sdk/client-sqs", () => ({
SQSClient: jest.fn(() => ({
send: jest.fn(),
})),
ChangeMessageVisibilityCommand: jest.fn(),
}));
describe("updateMessageVisibility", () => {
it("should update the visibility of a message in SQS", async () => {
// Arrange
const queueUrl = "https://sqs.<region>.amazonaws.com/<account-id>/<queue-name>";
const receiptHandle = "test-receipt-handle";
const visibilityTimeout = 60;
const command = new ChangeMessageVisibilityCommand({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
VisibilityTimeout: visibilityTimeout,
});
// Mock the SQS client to return a successful response
const mockSend = jest.fn().mockResolvedValueOnce({});
const SQSClient = require("@aws-sdk/client-sqs").SQSClient;
SQSClient.prototype.send = mockSend;
const ChangeMessageVisibilityCommand = require("@aws-sdk/client-sqs").ChangeMessageVisibilityCommand;
ChangeMessageVisibilityCommand.mockReturnValueOnce(command);
// Act
await updateMessageVisibility(queueUrl, receiptHandle, visibilityTimeout);
// Assert
expect(mockSend).toHaveBeenCalledTimes(1);
expect(ChangeMessageVisibilityCommand).toHaveBeenCalledTimes(1);
expect(ChangeMessageVisibilityCommand).toHaveBeenCalledWith({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
VisibilityTimeout: visibilityTimeout,
});
});
});
In this test, we are mocking the client-sqs
library to return a successful response. We then call the updateMessageVisibility
function and assert that it updates the message visibility in SQS.
Testing the deleteMessage Function
Finally, let's write a unit test for the deleteMessage
function. The purpose of this function is to delete a message from SQS.
Here's an example test:
import { deleteMessage } from "./sqs";
import { DeleteMessageCommand } from "@aws-sdk/client-sqs";
jest.mock("@aws-sdk/client-sqs", () => ({
SQSClient: jest.fn(() => ({
send: jest.fn(),
})),
DeleteMessageCommand: jest.fn(),
}));
describe("deleteMessage", () => {
it("should delete a message from SQS", async () => {
// Arrange
const queueUrl = "https://sqs.<region>.amazonaws.com/<account-id>/<queue-name>";
const receiptHandle = "test-receipt-handle";
const command = new DeleteMessageCommand({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
});
// Mock the SQS client to return a successful response
const mockSend = jest.fn().mockResolvedValueOnce({});
const SQSClient = require("@aws-sdk/client-sqs").SQSClient;
SQSClient.prototype.send = mockSend;
const DeleteMessageCommand = require("@aws-sdk/client-sqs").DeleteMessageCommand;
DeleteMessageCommand.mockReturnValueOnce(command);
// Act
await deleteMessage(queueUrl, receiptHandle);
// Assert
expect(mockSend).toHaveBeenCalledTimes(1);
expect(DeleteMessageCommand).toHaveBeenCalledTimes(1);
expect(DeleteMessageCommand).toHaveBeenCalledWith({
QueueUrl: queueUrl,
ReceiptHandle: receiptHandle,
});
});
});
In this test, we are mocking the client-sqs
library to return a successful response. We then call the deleteMessage
function and assert that it deletes the message from SQS.
These unit tests will help you ensure that your code is working as expected and will help you catch bugs early on in the development process. You can run these tests using the following command:
npm test
This will run all the tests in the sqs.test.ts
file and output the results in your terminal.
We hope that this article has been helpful in guiding you on how to write unit tests for your Node.js TypeScript code using the Jest testing framework. Remember to write tests for all the functions in your code to ensure that it works as expected. Happy testing!
Top comments (0)