https://github.com/jcserv/vu-mi
A very over-engineered serverless application enabling users to add visitor count badges to their Github profile.
https://github.com/jcserv/vu-mi
aws dynamodb dynamodb-streams serverless sqs
Last synced: about 2 months ago
JSON representation
A very over-engineered serverless application enabling users to add visitor count badges to their Github profile.
- Host: GitHub
- URL: https://github.com/jcserv/vu-mi
- Owner: jcserv
- License: gpl-3.0
- Created: 2024-08-05T22:48:03.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2024-08-11T22:30:03.000Z (9 months ago)
- Last Synced: 2025-02-09T12:28:31.428Z (3 months ago)
- Topics: aws, dynamodb, dynamodb-streams, serverless, sqs
- Language: Python
- Homepage:
- Size: 14.5 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# vu-mi
vu-mi is a public API to enable view count badges in Markdown.
The API returns up-to-date counts, up to {prevComputedCount} + 7999. Any more than that, and it will show a stale count.It is tremendously over-engineered, using the following technologies:
- AWS Lambda
- DynamoDB
- DynamoDB Streams
- SQSI did it to implement concepts I've learned about, but never worked with such as:
- Modelling one-to-many relationships in a DynamoDB single table design (from [The DynamoDB Book](https://dynamodbbook.com/), by Alex Debrie)
- Change Data Capture## Usage
To use this in a Markdown document, simply paste the following, and insert your unique ID:
```md

```
The ID could be your Github username, Github repo, anything you want really.
## API
### GET /v1/api/views?id=YOUR-ID-HERE
Response:
```
200 OK
{
"schemaVersion": 1,
"label": "views",
"message": "12",
"color": "blue"
}
```## Design
### End-to-End Flow

``
1. `GET /v1/api/views?id=jcserv` request comes into `get-views-lambda`
2. `get-views-lambda` queries Dynamo for all items with matching PK, limit of 8000
3. a. Send SQS message with user id & countb. Return response with count - 1 (minus one to account for the USER item)
``
4. If the provided count is 0, PUT the USER item
> Q: Is there a risk of race conditions here when multiple requests come in for a new user?A: There is, if the message to the `put-views-lambda` comes after a `batch-update-count-lambda` invocation, it can override the count to 0.
To circumvent this, we only PUT the user item IFF the user object does not already exist ("attribute_not_exists(PK) AND attribute_not_exists(SK)")5. Put VIEW item, with TTL rounded to the next 5 min interval
6. Items expire; DynamoDB streams sends records with each item
> This is essentially the same as having a 5-min cron job to collate View items, but without having to SCAN the entire table.
> Streams is also nice here since, rather than one invocation per item expiring, we can do a bulk update. Savings++
``
7. Get the user object using the PK provided from the DynamoDB Streams record
8. Put the new count onto the user item
### Dynamo Model

## Discussion
> Q: Was this really necessary?
Not really, it could've been achieved with a simpler design, like so:

But that wouldn't be fun!
## Author's Note
This project is named after my cat Yumi, since I implemented the majority of this during an early morning
after she woke me up TT
![]()