Your task is to create a simple microservice for processing customer feedback data. The microservice will be responsible for managing customer feedback, storing it in a PostgreSQL database, and publishing it to a Kafka topic. Additionally, the microservice implements caching using Memcached to improve performance.
-
Create a Go microservice with the following endpoints:
- ✅ POST /feedback: allows the user to submit a new feedback item. The endpoint should accept JSON in the following format:
{ "customer_name": "Andrii Derkach", "email": "[email protected]", "feedback_text": "It's a really good test task.", "source": "https://t.me/andrsj" }
✅ The microservice should validate the input data, create a unique identifier for the feedback item, save the item in the PostgreSQL database, and publish it to the Kafka topic.
- ✅ GET /feedback/{id}: allows the user to retrieve a specific feedback item by its identifier. The microservice should first check the Memcached cache for the item. If the item is not in the cache, it should retrieve it from the PostgreSQL database and store it in the cache for future requests.
-
Use the following technology stack: (if needed for the task):
- ✅ Go
- ✅ PostgreSQL for data storage
- ✅ Kafka for message publishing
- ✅ Memcached for caching
- ❌ JavaScript and React for the interface
- ✅ Microservice communication via HTTP
- ✅ JWT for authentication
-
✅ The microservice should return appropriate error messages if the endpoint is used incorrectly or if there are issues with the data.
-
✅ You should use any relevant libraries or frameworks that are convenient for you.
- ✅ Implement pagination for the /feedback endpoint to limit the number of results returned.
- ❌ Add unit tests for the microservice endpoints.
- ✅ Implement authentication and authorization using JWT.
- ✅ Use Docker to containerize the microservice.
✅ Please provide the source code for your solution, including instructions for configuration and running the program.
Good luck!
GET /
- Status code 200 for verify the viability of server
GET /token?minutes=10&role=all
- Generator of JSON Web Tokens- minutes:
- int
- default = 10
- role:
- string
- available:
get
,post
,all
- minutes:
JWT Errors:
Errors | Messages |
---|---|
Invalid JWT | {"error": "wrong token authorization: parsing error: token is malformed: could not JSON decode header: invalid character 'ÿ' looking for beginning of value"} |
Wrong access role | {"error": "validating token error: validating 'role' error: wrong role for 'POST': token has wrong role"} |
Token Expired | {"error": "validating token error: validating 'expiredAt' error: expired (122): token is expired"} |
GET /feedbacks
- GET all feedbacks from DB [No cache, no paginated values]
Text | Image |
---|---|
Response for GET |
GET /feedback/{id}
- GET one specific feedback by ID- id - UUID string (that parsed into
uuid.UUID
)
- id - UUID string (that parsed into
GET /p-feedbacks?limit=10&next=""
- Paginated version of/feedbacks
- limit:
- int
- EXPECTED > 0
- next:
- string
- NEED TO BE IN UUID format
- limit:
Text | Image |
---|---|
Output | |
Headers | |
Next request/response |
Error | Message |
---|---|
Wrong type of limit | {"error":"error while check limit: wrong limit param 'a': invalid limit parameter"} |
Wrong limit value | {"error":"error while check limit: wrong limit param '-1 < 0': invalid limit parameter"} |
Wrong format of next | {"error":"error while check next: wrong format of next ID: invalid next parameter"} |
No values after next | {"error": "next 'b7970cbb-0a70-41bb-99d7-52ec3884d3d5': no values after 'next'"} |
POST /feedback
- CREATE one feedback
/l?time=0
- Just a handler that sleep, used to test "graceful shutdown" (actually a timeout signal interrupt)
In the Makefile I include a lot of different commands:
make build
- build app on local machinemake brun
- build and run on local machinemake db-up | kafka-up | cache-up
- app separate servicemake consumer
- CLI consumer for TOPIC that used for producing in Appmake up
- Start whole dockerize projectmake down
- Stop itmake go
- rerun Go app container without rebuildmake bgo
- rebuild and run Docker image for Go app- e.t.c.
- Unit tests! Integration tests! E2E tests! No manual testing!
- More effective error handling [no wrapped messages]
- Communicating between running requests for graceful shutdown
- Make writing to DB and Kafka in goro [not 100% sure]
- Move generating UUID for models inside DB and return this value back to APP [Currently the ID is generated in Repository]
- Move some validation to model methods: something like
isValidEmail
func (f *Feedback) IsValidEmail() bool {
if f.Email == "" && isValidEmail(f.Email) {
return true
}
return false
}
If we are running the Docker Compose, we can see that the Go Web Server try to connect to not-ready DB. I tried to fix it with this shell/bash script but not successful.
We can use the mechanism is commonly known as "database connection retry"
Small code example (haven't included into project until I'll got review from employer):
db, err := sql.Open("mysql", "user:password@tcp(dbhost:3306)/dbname")
// Retry connecting to the database up to 5 times with a delay of 5 seconds between each attempt
for i := 0; i < 5; i++ {
if err != nil {
fmt.Printf("Error connecting to database: %v\n", err)
time.Sleep(5 * time.Second)
db, err = sql.Open("mysql", "user:password@tcp(dbhost:3306)/dbname")
} else {
break
}
}
if err != nil {
panic("Failed to connect to database after multiple attempts")
}
// DO next business logic
I'll write until I'll got review from employer
I'll write until I'll got review from employer