UI Integration
Congratz on making it this far! You know the most valuable pieces of serverless and how to use them.
It's okay if you feel a little shakey about everything you've learned so far. This is where you put it to the test and bring it all together.
You're going to build a shared click counter.
Sounds silly, I know, but it's a great way to test your skills. This is how likes work on twitter, how medium's +1 works, reddit upvotes, etc. At the core, it's all just counting clicks.
Distributed click counter
DynamoDB stores data in tables. Each works as its own database and you can have as many as you want.
Exercise
Take your code from exercise-6 and add 2 new methods:
upvote
which adds a new vote to the databasecountVotes
which returns the current number
Make sure they're at <base url>/upvote/<identifier>
and <base url>/countvotes/<identifier>
. POST request for upvoting, GET for counting.
You can model the data as a single counting integer. That makes it easier, but you might run into votes overwriting each other. You also won't know when they happened.
Another approach is to model your data as a table of votes with a timestamp each.
In both cases you'll need some identifier
for what's being voted upon.
Here's a CodeSandbox you can use for the UI:
It uses React Query and lets you specify your API's domain. You get that from deploying your cloud functions.
You can build your own using your favorite way to run API requests.
Tips
- You'll have to return CORS headers that allow CodeSandbox to make these requests.
const response = {statusCode: 200,headers: {"Access-Control-Allow-Headers": "Content-Type","Access-Control-Allow-Origin": "https://www.example.com","Access-Control-Allow-Methods": "OPTIONS,POST,GET",},body: JSON.stringify("Hello from Lambda!"),}
Make sure you add a secondary ID to your votes, primary for the item, secondary for the vote itself
The uuid library is a great way to generate unique IDs
Use this sort of code to get a vote count
const result = await db.scanItems({TableName: process.env.UPVOTES_TABLE!,FilterExpression: "#itemId = :itemId",ExpressionAttributeNames: {"#itemId": "itemId",},ExpressionAttributeValues: {":itemId": itemId,},})
Solution
https://github.com/Swizec/serverless-workshop-exercises/tree/exercise-7-solution