Skip to content

Commit 929ffcc

Browse files
HarshCasperwhummer
andauthored
configure the sample application to work with LocalStack (#1)
* setup the application for localstack usage * add a makefile and setup a github action * add a learn more and github action section to docs * remove code of conduct and contributing docs * Update README.md Co-authored-by: Waldemar Hummer <waldemar.hummer@gmail.com> * Update README.md Co-authored-by: Waldemar Hummer <waldemar.hummer@gmail.com> * Update README.md Co-authored-by: Waldemar Hummer <waldemar.hummer@gmail.com> * run tests on ci and some makefile changes * finish work on README --------- Co-authored-by: Waldemar Hummer <waldemar.hummer@gmail.com>
1 parent 7c7c930 commit 929ffcc

File tree

9 files changed

+174
-145
lines changed

9 files changed

+174
-145
lines changed

.github/workflows/main.yml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Deploy on LocalStack
2+
3+
on:
4+
push:
5+
paths-ignore:
6+
- 'README.md'
7+
branches:
8+
- main
9+
pull_request:
10+
branches:
11+
- main
12+
13+
jobs:
14+
terraform:
15+
name: Setup infrastructure using CDK
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v3
20+
21+
- name: Setup Node.js
22+
uses: actions/setup-node@v3
23+
with:
24+
node-version: 18
25+
26+
- name: Install CDK
27+
run: |
28+
npm install -g aws-cdk-local aws-cdk
29+
cdklocal --version
30+
31+
- name: Install dependencies
32+
run: |
33+
yarn
34+
35+
- name: Start LocalStack
36+
env:
37+
LOCALSTACK_API_KEY: ${{ secrets.LOCALSTACK_API_KEY }}
38+
DNS_ADDRESS: 0
39+
run: |
40+
pip install localstack awscli-local[ver1]
41+
pip install terraform-local
42+
docker pull localstack/localstack-pro:latest
43+
# Start LocalStack in the background
44+
localstack start -d
45+
# Wait 30 seconds for the LocalStack container to become ready before timing out
46+
echo "Waiting for LocalStack startup..."
47+
localstack wait -t 15
48+
echo "Startup complete"
49+
50+
- name: Deploy using CDK
51+
run: |
52+
cdklocal bootstrap aws://000000000000/us-east-1
53+
cdklocal deploy --require-approval never
54+
55+
- name: List the resources
56+
run: |
57+
awslocal lambda list-functions
58+
awslocal sqs list-queues
59+
awslocal dynamodb list-tables
60+
61+
- name: Run tests
62+
run: |
63+
yarn test

CODE_OF_CONDUCT.md

Lines changed: 0 additions & 4 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 0 additions & 59 deletions
This file was deleted.

Makefile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
export AWS_ACCESS_KEY_ID ?= test
2+
export AWS_SECRET_ACCESS_KEY ?= test
3+
export AWS_DEFAULT_REGION=us-east-1
4+
SHELL := /bin/bash
5+
6+
## Show this help
7+
usage:
8+
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'
9+
10+
## Install dependencies
11+
install:
12+
@which localstack || pip install localstack
13+
@which awslocal || pip install awscli-local
14+
@which cdklocal || npm install -g aws-cdk-local aws-cdk
15+
16+
deploy:
17+
test -e node_modules || yarn; \
18+
cdklocal bootstrap aws://000000000000/us-east-1; \
19+
cdklocal deploy
20+
21+
## Start LocalStack in detached mode
22+
start:
23+
localstack start -d
24+
25+
## Stop the Running LocalStack container
26+
stop:
27+
@echo
28+
localstack stop
29+
30+
## Make sure the LocalStack container is up
31+
ready:
32+
@echo Waiting on the LocalStack container...
33+
@localstack wait -t 30 && echo LocalStack is ready to use! || (echo Gave up waiting on LocalStack, exiting. && exit 1)
34+
35+
## Save the logs in a separate file, since the LS container will only contain the logs of the last sample run.
36+
logs:
37+
@localstack logs > logs.txt
38+
39+
.PHONY: usage install run start stop ready logs

README.md

Lines changed: 69 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,107 @@
1-
# Friend Microservices Sample
1+
# Serverless Microservices with Amazon API Gateway, DynamoDB, SQS, and Lambda
22

3-
This CDK project is a sample solution for friend microservices in games.\
4-
The sample solution contains AWS Lambda Functions, Amazon DynamoDB Tables, Amazon SQS Queues and Amazon API Gateway.
3+
| Key | Value |
4+
| ------------ | ---------------------------------------------------------------------------------------------------- |
5+
| Environment | <img src="https://img.shields.io/badge/LocalStack-deploys-4D29B4.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAKgAAACoABZrFArwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAALbSURBVHic7ZpNaxNRFIafczNTGIq0G2M7pXWRlRv3Lusf8AMFEQT3guDWhX9BcC/uFAr1B4igLgSF4EYDtsuQ3M5GYrTaj3Tmui2SpMnM3PlK3m1uzjnPw8xw50MoaNrttl+r1e4CNRv1jTG/+v3+c8dG8TSilHoAPLZVX0RYWlraUbYaJI2IuLZ7KKUWCisgq8wF5D1A3rF+EQyCYPHo6Ghh3BrP8wb1en3f9izDYlVAp9O5EkXRB8dxxl7QBoNBpLW+7fv+a5vzDIvVU0BELhpjJrmaK2NMw+YsIxunUaTZbLrdbveZ1vpmGvWyTOJToNlsuqurq1vAdWPMeSDzwzhJEh0Bp+FTmifzxBZQBXiIKaAq8BBDQJXgYUoBVYOHKQRUER4mFFBVeJhAQJXh4QwBVYeHMQJmAR5GCJgVeBgiYJbg4T8BswYPp+4GW63WwvLy8hZwLcd5TudvBj3+OFBIeA4PD596nvc1iiIrD21qtdr+ysrKR8cY42itCwUP0Gg0+sC27T5qb2/vMunB/0ipTmZxfN//orW+BCwmrGV6vd63BP9P2j9WxGbxbrd7B3g14fLfwFsROUlzBmNM33XdR6Meuxfp5eg54IYxJvXCx8fHL4F3w36blTdDI4/0WREwMnMBeQ+Qd+YC8h4g78wF5D1A3rEqwBiT6q4ubpRSI+ewuhP0PO/NwcHBExHJZZ8PICI/e73ep7z6zzNPwWP1djhuOp3OfRG5kLROFEXv19fXP49bU6TbYQDa7XZDRF6kUUtEtoFb49YUbh/gOM7YbwqnyG4URQ/PWlQ4ASllNwzDzY2NDX3WwioKmBgeqidgKnioloCp4aE6AmLBQzUExIaH8gtIBA/lFrCTFB7KK2AnDMOrSeGhnAJSg4fyCUgVHsolIHV4KI8AK/BQDgHW4KH4AqzCQwEfiIRheKKUAvjuuu7m2tpakPdMmcYYI1rre0EQ1LPo9w82qyNziMdZ3AAAAABJRU5ErkJggg=="> <img src="https://img.shields.io/badge/AWS-deploys-F29100.svg?logo=amazon"> |
6+
| Services | API Gateway, DynamoDB, SQS, Lambda |
7+
| Integrations | CDK |
8+
| Categories | Serverless; Microservices |
9+
| Level | Beginner |
10+
| GitHub | [Repository link](https://github.com/localstack/microservices-apigateway-lambda-dynamodb-sqs-sample) |
511

6-
## Key features
12+
## Introduction
713

8-
- the solution is constructed with only serverless services
9-
- the solution handles friend state management asynchronously
10-
- the solution utilizes DynamoDB Streams with Event Source Mapping Filters to reduce number of transactional writes
11-
- the solution has an SQS queue in front, so multiple backend services can send friend actions
12-
- the solution is decoupled from player management, it simply serves friend state management
13-
- the solution handles duplicated messages from SQS using Event Source Mapping Filters
14+
The Serverless microservices application sample demonstrates how you can build and deploy a solution for friend microservices in gaming applications using API Gateway, Lambda, DynamoDB, and SQS. This application sample allows you to handle friend state management asynchronously and utilizes DynamoDB Streams with Event Source Mapping Filters to reduce the number of transactional writes. With an SQS queue, multiple backend services can send friend actions and handle duplicated messages using Event Source Mapping Filters. An API Gateway and a Lambda Function have been implemented to read the data and DynamoDB for data persistence. The sample is decoupled from player management and only serves friend state management. Users can deploy the infrastructure with AWS Cloud Development Kit, and we will demonstrate how you use LocalStack to deploy the infrastructure on your developer machine and your CI environment.
1415

15-
## Assumptions
16+
## Architecture diagram
1617

17-
- another service, such as a notification service, has bidirectional connection with clients
18-
- player metadata is stored separately with all player IDs matched
18+
![Architecture diagram for Serverless microservices with Amazon API Gateway, Amazon DynamoDB, Amazon SQS, and AWS Lambda](images/microservices-apigateway-lambda-dynamodb-sqs-sample-architecture.png)
1919

20-
## Architecture
20+
We are using the following AWS services and their features to build our infrastructure:
2121

22-
As Shown in the diagram below, there are three Lambda functions (though State Handlers are made of four lambda functions), a single SQS queues in front and a DynamoDB table.\
23-
`Front Queue` intakes all friend actions from game backend services\
24-
Each `State Handler` handles different state, and triggered though different Event Source Mapping Filters\
25-
There also is an API Gateway and a Lambda Function for reading data\
26-
![alt text](./docs/FriendsMicroservices.png)
22+
- [Lambda](https://docs.localstack.cloud/user-guide/aws/lambda/) to create the serverless functions for the Create, State, and Read handlers.
23+
- [SQS](https://docs.localstack.cloud/user-guide/aws/sqs/) as a distributed message queuing service to intakes all friend actions from game backend services.
24+
- [DynamoDB](https://docs.localstack.cloud/user-guide/aws/dynamodb/) as a key-value and document database to persist data with Event Source Mapping Filters to reduce number of transactional writes.
25+
- [API Gateway](https://docs.localstack.cloud/user-guide/aws/apigatewayv2/) to expose and allow the Lambda functions to read data through HTTP APIs.
2726

28-
## DynamoDB Tables
27+
## Prerequisites
2928

30-
### Friend Table
29+
- LocalStack Pro
30+
- [AWS CLI](https://docs.localstack.cloud/user-guide/integrations/aws-cli/) with the [`awslocal`](https://github.com/localstack/awscli-local) wrapper.
31+
- [CDK](https://docs.localstack.cloud/user-guide/integrations/aws-cdk/) with the [`cdklocal`](https://github.com/localstack/aws-cdk-local) wrapper.
32+
- [NodeJS v18.0.0](https://nodejs.org/en/download/) with `npm` package manager.
3133

32-
Each entry represents friend state from the perspective of a player with the player ID against a friend with the friend ID.
34+
Start LocalStack Pro by setting your `LOCALSTACK_API_KEY` to activate the Pro features.
3335

34-
| PK: player_id | SK: friend_id | state | last_updated |
35-
| ----------------- | ----------------- | -------------------- | ------------ |
36-
| string: player ID | string: friend ID | string: friend state | time stamp |
37-
38-
## Friend States
36+
```shell
37+
export LOCALSTACK_API_KEY=<your-api-key>
38+
EXTRA_CORS_ALLOWED_ORIGINS=* localstack start -d
39+
```
3940

40-
- Requested
41-
- State that the requester sees on his/her entry after sending a friend request
42-
- Pending
43-
- State that the receiver sees on his/her entry after receiving a friend request
44-
- Friends
45-
- State that both players see on their entries once they become friends
41+
## Instructions
4642

47-
## Friend Actions
43+
You can build and deploy the sample application on LocalStack by running our `Makefile` commands. To deploy the infrastructure, you can run `make deploy` after installing the application dependencies. Here are instructions to deploy and test it manually step-by-step.
4844

49-
- Request
50-
- initial action to send a friend request to another player
51-
- Accept
52-
- an action to accept a pending friend request from another player
53-
- this can only be triggered by the receiver
54-
- Reject
55-
- an action to reject a pending friend request from another player
56-
- this can only be triggered by the receiver
57-
- Unfriend
58-
- an action to break off a completed friend relationship between two players
59-
- this can be triggered by both players
45+
### Creating the infrastructure
6046

61-
## Friend Action Message
47+
To create the AWS infrastructure locally, you can use CDK and our `cdklocal` wrapper. Before you can deploy the infrastructure, you need to install the application dependencies:
6248

63-
```
64-
{
65-
"player_id": string,
66-
"friend_id": string,
67-
"friend_action": Friend Action,
68-
}
49+
```shell
50+
yarn
6951
```
7052

71-
### Prerequisites
53+
To deploy the infrastructure, you can run the following command:
7254

73-
- An AWS account
74-
- Nodejs LTS installed, such as 14.x
75-
- Install Docker Engine
55+
```shell
56+
cdklocal bootstrap aws://000000000000/us-east-1
57+
cdklocal deploy
58+
```
7659

77-
## Usage
60+
As an output of the last command, you will see the API Gateway endpoint URL. You can use this URL to test the API.
7861

79-
### Deployment
62+
### Testing the microservice
8063

81-
To deploy the example stack to your default AWS account/region, under project root folder, run:
64+
To test the microservice, we will send Friend Action Events to the front SQS queue. We will use the AWS CLI to send the events to the queue. To get the Queue URL, you can run the following command:
8265

83-
1. `yarn install` to install all the dependencies
84-
2. `cdk deploy` to deploy this stack to your default AWS account/region
66+
```shell
67+
awslocal sqs list-queues
68+
```
8569

86-
## Test
70+
Get the URL of the Front Queue and use the following commands to send a friend request event:
8771

88-
### Send Test Friend Action Events
72+
```shell
73+
awslocal sqs send-message-batch --queue-url <QUEUE_URL> --entries file://test/testMessagesFirst.json
74+
awslocal sqs send-message-batch --queue-url <QUEUE_URL> --entries file://test/testMessagesSecond.json
75+
awslocal sqs send-message-batch --queue-url <QUEUE_URL> --entries file://test/testMessagesThird.json
76+
```
8977

90-
Since front SQS is Standard queue, you need to send test messages three times separately, to get to the final state.
91-
With AWS CLI:
78+
To test corner cases, you can send the following messages to the queue:
9279

93-
```
94-
aws sqs send-message-batch --queue-url <QUEUE URL> \
95-
--entries file://test/testMessages<First|Second|Third>.json
80+
```shell
81+
awslocal sqs send-message-batch --queue-url <QUEUE_URL> --entries file://test/cornerCase1.json
82+
awslocal sqs send-message-batch --queue-url <QUEUE_URL> --entries file://test/cornerCase2.json
9683
```
9784

98-
If you want to test corner cases, try this:
85+
To test the microservice now, send the following command using `cURL`:
9986

87+
```shell
88+
curl -X GET 'https://<LOCAL_APIGATEWAY_ENDPOINT>/friends/player1'
89+
curl -X GET 'https://<LOCAL_APIGATEWAY_ENDPOINT>/friends/player2'
90+
curl -X GET 'https://<LOCAL_APIGATEWAY_ENDPOINT>/friends/player3'
10091
```
101-
aws sqs send-message-batch --queue-url <QUEUE URL> \
102-
--entries file://test/cornerCase<1|2>.json
103-
```
104-
105-
### Get Test Friend Data
10692

107-
With `curl`:
93+
To run the unit tests, you can run the following command:
10894

95+
```shell
96+
yarn test
10997
```
110-
$ curl -X GET 'https://<YOUR ENDPOINT>/friends/player1'
111-
```
11298

113-
## License
99+
## GitHub Action
100+
101+
This application sample hosts an example GitHub Action workflow that starts up LocalStack, deploys the infrastructure, and checks the created resources using `awslocal`. You can find the workflow in the `.github/workflows/main.yml` file. To run the workflow, you can fork this repository and push a commit to the `main` branch.
114102

115-
This solution is licensed under the MIT-0 License. See the LICENSE file.
103+
Users can adapt this example workflow to run in their own CI environment. LocalStack supports various CI environments, including GitHub Actions, CircleCI, Jenkins, Travis CI, and more. You can find more information about the CI integration in the [LocalStack documentation](https://docs.localstack.cloud/user-guide/ci/).
116104

117-
Also, this application uses below open source project,
105+
## Learn more
118106

119-
- [aigle](https://www.npmjs.com/package/aigle)
107+
The sample application is based on a [public AWS sample app](https://github.com/aws-samples/friend-microservices) that deploys a friend microservice for gaming applications.

docs/FriendsMicroservices.png

-71.6 KB
Binary file not shown.
354 KB
Loading

lib/friend-microservices-stack.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Runtime,
1212
StartingPosition,
1313
} from "aws-cdk-lib/aws-lambda";
14+
import * as cdk from "aws-cdk-lib";
1415
import { Friend, State } from "../models/friend";
1516
import { keyMap, Keys, tableMap } from "../models/tableDecorator";
1617
import {
@@ -37,6 +38,7 @@ export class FriendMicroservicesStack extends Stack {
3738

3839
const functionProp: NodejsFunctionProps = {
3940
runtime: Runtime.NODEJS_14_X,
41+
timeout: cdk.Duration.seconds(10000),
4042
memorySize: 1024,
4143
};
4244

test/friend-microservices.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ test("resource count test", () => {
77
const stack = new FriendMicroservicesStack(app, "TestStack");
88
const template = Template.fromStack(stack);
99

10-
template.resourceCountIs("AWS::Lambda::Function", 5);
10+
template.resourceCountIs("AWS::Lambda::Function", 6);
1111
template.resourceCountIs("AWS::DynamoDB::Table", 1);
1212
template.resourceCountIs("AWS::SQS::Queue", 2);
1313
});

0 commit comments

Comments
 (0)