Skip to content

Commit 027055c

Browse files
committed
developer annotations and readme
1 parent ab70b03 commit 027055c

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

README.md

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
11
# Developer Notes
22

3-
run with docker-compose
3+
## About the solution
44

5-
docker-compose up --build
5+
A few years ago I wrote a realtime chat scaling to infinite for a social TV startup which was based on Socket.io and used Layer 4 Load Balancing and Redis Pub/Sub to glue multiple Socket.io together. This worked very well in production and I would chose it again.
6+
7+
Since a Java backend was required for this task I decided to try something new:
8+
I know Spring Boot and I heard about server side events (SSE) as a new way to push data via http to a web client. For persistence I chose MongoDB because it scales well and I needed a simple NO-SQL DB running in docker (I would tend to DynamoDB or similar in a cloud native environment). Looking into MongoDB I came across tailable cursors and a nice tutorial who to use them in Spring - https://www.baeldung.com/spring-data-mongodb-tailable-cursors - At this point the solution was clear and fired up my IDE. I struggled setting up a capped collection in mongodb which is needed for the tailable cursors - A stackexchange thread suggested to run a setup.js but I was not satisfied and found a way to do this in Java/ Spring at application startup and not triggered by docker-compose. I lost a fair bit of time at this point.
9+
The solution works great and updates are almost instant. Any appended new message to the chat message collection is immediately sent to spring which is then doing the SSE magic and pushing it to the client. The client is already subscribed to the stream and appends the data to the list in the GUI. A normal POST endpoint is used to add a new chat row to the mongodb.
10+
11+
The frontend is coded in React which I love and use for a few years now. Having said this - I do React and Next.js but i don't do any CSS at all - I would be able to pick some tailwind components and add them to the Client to make it look nice but I ran out of time.
12+
13+
SSE seems to be supported through all current browsers https://caniuse.com/eventsource so one could also use this in production.
14+
15+
At the bottom of the this document I added a todo list of things I would have definitely realised if I had more time.
16+
17+
# Run the Demo
18+
19+
1. clone this repo from github
20+
21+
2. run with docker-compose in the root of the project
22+
23+
cd sse-chat/
24+
docker-compose up --build
625

726
access the react frontend at
827

928
http://localhost:3000/
1029

1130
## TODO's
1231

13-
- Proper Input Validation on the react client side
32+
- Proper input validation / sanitation on the react client side
1433
- A LOT of error handling on the react side (EventSource onError - fetch errors etc, check HTTP status codes )
34+
- check if SSE are supported in the browser (fallback to polling and add a none-reactive endpoint to retrieve Message list as json array)
1535
- Monitoring of the springboot app (actuator)
1636
- two stage build for spring docker image
17-
- CSS!!! - i seriosly did run out of time - i would have grabbed a few nice tailwind components
1837
- implement some proper test cases for the backendA API
1938
- run tests as part of the build stage
20-
- add send and recipient props on message
2139
- add SECURITY - this chat is wide open
2240
- add some nginx proxy in front of the react app and the backend app
2341
- add swagger for the backend api
42+
- CSS!!! - i seriosly did run out of time - i would have grabbed a few nice tailwind components
2443

2544
## API Usage
2645

@@ -39,10 +58,7 @@ add a new chat entry
3958
Content-Type application/json
4059

4160
{
42-
"message":"hello",
61+
"message":"hello world!",
4362
"channelId":1,
63+
"sender": "send name"
4464
}
45-
46-
## References
47-
48-
https://medium.com/hacktive-devs/building-the-backend-of-chat-applications-with-spring-webflux-and-reactive-mongodb-26347a1ddce4

backend/src/main/java/com/ssechat/Application.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
1212
import reactor.core.Disposable;
1313

14+
/**
15+
* launch spring boot app and create capped collection for chat message collection
16+
*/
1417
@SpringBootApplication
1518
public class Application {
1619

backend/src/main/java/com/ssechat/controller/ChatMessageController.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@
1313
@CrossOrigin(value = { "*" },
1414
maxAge = 900
1515
)
16+
/**
17+
* get chat message event stream and allow adding of new messages
18+
* crossdomain * open to allow react client -
19+
* i would remove this and run a nginx in the future serving both client and server
20+
*/
1621
@RestController
1722
public class ChatMessageController {
1823
@Autowired

backend/src/main/java/com/ssechat/model/ChatMessage.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
import java.time.Instant;
88

9+
/**
10+
* message entity - you can find the same contract in the typescript types.d.ts definition
11+
*/
912
@Document(collection = "chatmessages")
1013
public class ChatMessage {
1114
@Id

0 commit comments

Comments
 (0)