Trong bài này, chúng ta dùng React Native, Serverless framework và Upstash phát triển ứng dụng mobile xem và cập nhật bảng xếp hạng (leaderboard).
Sử dụng React Native phát triển mobile app backed by Serverless framework, bao gồm Python functions chạy trên AWS Lambda.
1 - Sử dụng Upstash Redis
Trong leaderboard app điển hình, thông tin user và điểm số cần lưu trữ. Vì tất cả data cần sắp xếp theo điểm, dùng Redis là một trong những giải pháp tốt nhất.
"Sorted Set", được Redis hỗ trợ, là kiểu dữ liệu đã sắp xếp cho phép lưu trữ, thêm, xóa và query by range rất nhanh.
Sorted set chính xác là thứ cần cho lưu trữ, cập nhật và hiển thị leaderboard đã sắp xếp.
1.1 - Bắt đầu với Upstash
Upstash cung cấp serverless database cho Redis. Xem chi tiết Redis documentation.
Một số ưu điểm dẫn đến dùng Upstash Redis:
- Hệ thống giá pay-as-you-go, Pricing
- Free tier cho lưu trữ và operations
- Triển khai rất dễ dàng
- Không cần cấu hình chi tiết
Trong trường hợp này, bước đầu là tạo tài khoản Upstash Console. Thứ hai, tạo Upstash database như ý. Sau đó sẵn sàng!

Để quen, làm vài operations trong CLI cung cấp trong Upstash console.
Thêm user mới với score vào sorted set tên Leaderboard:
ZADD Leaderboard <Score> <User>
Hiển thị tất cả user info với score:
ZRANGE Leaderboard 0 -1 WITHSCORES
Có thể làm các operations này trên AWS Lambda functions với Serverless Framework kết nối Redis với backend app.
2 - Tạo Functions với Serverless Framework
Serverless framework cho phép làm việc với serverless functions của cloud providers (AWS, Azure, Google Cloud...). Công cụ mạnh triển khai và quản lý serverless functions từ user side.
Bắt đầu cài đặt và cấu hình Serverless Framework cho AWS. Xem và làm theo Serverless quick start.
Sau cài đặt, có handler.py và serverless.yml.
- serverless.yml: Định nghĩa functions sẽ implement. Cần "addScore" và "getLeaderboard".
functions:
addScore:
handler: handler.addScore
events:
- httpApi: 'POST /add'
getLeaderboard:
handler: handler.getLeaderboard
events:
- httpApi: 'GET /getLeaderboard'
- handler.py: Implement functions, code chạy ở backend khi HTTP request từ mobile app theo định nghĩa serverless.yml.
Import và cấu hình redis, dependency duy nhất. Thêm redis dependency vào serverless framework, cần plugin "Serverless Python Requirements". Chạy:
serverless plugin install -n serverless-python-requirements
Đảm bảo plugin thêm vào serverless.yml:
plugins:
- serverless-python-requirements
Xem chi tiết serverless-python-requirements.
Bước cuối, tạo requirements.txt cùng thư mục serverless.yml. Thêm redis dependency:
redis==4.0.2
Cấu hình Upstash Redis trong handler.py:
import json
import redis
r = redis.Redis(
host='YOUR_REDIS_ENDPOINT',
port='YOUR_REDIS_PORT',
password='YOUR_REDIS_PASSWORD',
charset="utf-8",
decode_responses=True)
Sau cấu hình Redis, chuẩn bị functions được user gọi.
Hai chức năng:
Thứ nhất: thêm user và score mới vào leaderboard. POST request. User gửi info trong body HTTP request.
{"score": 15,"firstname": "Jack","lastname": "Thang"}
Function implement:
def addScore(event, context):
info = json.loads(event["body"])
leaderboard = "Leaderboard"
score = info["score"]
player_name = info["firstname"] + "_" + info["lastname"]
r.zadd(leaderboard, {player_name: score})
body = { "message": "Score added successfully!" }
response = {"statusCode": 200, "body": json.dumps(body)}
return response
Parse score và user info từ event parameter do AWS Lambda cung cấp. Dùng zadd function của redis thêm user và score vào sorted set "Leaderboard". Ví dụ:
Request body: {"score": 15,"firstname": "Jack","lastname": "Thang"}
Response body: {"message": "Score added successfully!"}
Function thứ hai: getLeaderboard. Chấp nhận GET requests, trả về leaderboard descending order, đọc từ Redis.
def getLeaderboard(event, context):
leaderboard = "Leaderboard"
score_list = r.zrange(leaderboard, 0, -1, withscores=True, desc=True)
body = {
"message": "Leaderboard returned successfully!",
"leaderboard": score_list
}
response = {"statusCode": 200, "body": json.dumps(body)}
return response
Ví dụ:
Response body: {"message": "Leaderboard returned successfully!", "leaderboard": [["Jack_Thang", 15.0], ["Omer_Aytac", 12.0]]}
Deploy functions:
serverless deploy -v
Sẽ thấy Service Information khi deploy. Lưu endpoints để dùng sau.
endpoints:
POST - https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/add
GET - https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/getLeaderboard
Backend serverless sẵn sàng.
3 - Phát triển Mobile App với React Native
React Native là framework phát triển mobile app multi-platform viết code Javascript.
Để develop mobile app với React Native, setup environment và tạo project. Làm theo environment-setup.
Trong mobile app, có 2 màn hình. Màn hình đầu: user thêm score mới với info.
Để đơn giản, chỉ yêu cầu first name, last name và score.
Màn hình submit score:

Khi user nhập score, app gửi HTTP request đến serverless endpoint:
https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/add
Function trong ví dụ:
async addScore(){
if(isNaN(this.state.score)){
Alert.alert("Error", "Please enter a valid score.");
return;
}
if(this.state.firstname == "" || this.state.lastname == "" || this.state.score == null){
Alert.alert("Error", "Please fill in the blanks.");
return;
}
await fetch('https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/add', {
method: 'POST',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({
firstname: this.state.firstname,
lastname: this.state.lastname,
score: parseInt(this.state.score)
}),
})
.then(response => response.json())
.then(data => {
if(data.message == "Score added successfully!"){
Alert.alert("Done!", "Score added successfully!");
} else{
Alert.alert("Error", "Please try again later.");
}
})
.catch(err => {
console.error(err)
Alert.alert("Error", "Please try again later.");
});
}
POST request body chứa "firstname", "lastname", "score" keys và values từ user.
Nếu response từ backend chứa "Score added successfully!", request đã nhận và score added thành công.

Thiết kế màn hình leaderboard đơn giản. User navigate đến leaderboard screen bằng nút "Go to Leaderboard".
Leaderboard screen:

Gửi HTTP GET request đến endpoint quan trọng nhất màn hình này:
https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/getLeaderboard
Khi màn hình mở lần đầu. Gửi request trong componentDidMount invoked ngay sau component mounted:
async componentDidMount() {
await fetch('https://f571j8y8s1.execute-api.us-east-1.amazonaws.com/getLeaderboard',{
method: 'GET',
headers: { Accept: 'application/json', 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
console.log(data);
userlist = data.leaderboard;
this.setState({reRender: !this.state.reRender});
})
.catch(err => console.error(err));
}
Mã nguồn hoàn chỉnh tại upstash-react-native-project
Kết luận
Trong bài này, chúng ta phát triển mobile app leaderboard backed by Python functions trên AWS Lambda qua Serverless Framework. Leaderboard lưu trong Upstash Redis.
Rất nhiều thứ có thể làm với Upstash. Xây leaderboard app dùng Redis chỉ là một trong số đó.
Hy vọng bài viết giúp ích cho mọi người!