Skip to content

Commit a86e070

Browse files
committed
feat: make long-polling client-aware and harden message/like handling
- Replace callBacksForNewMessages array with object keyed by clientId - Store GET /messages callbacks under clientId and return [] if clientId missing - Broadcast new messages and likes to all waiting clients via Object.values(...) - Clear waiting-room after notifying clients to avoid double-sends - Add try/catch removal behavior when sending callback responses - Ensure 404 check before incrementing likes in POST /messages/:id/like - Add API_BASE_URL and per-client myClientId (with localhost fallback commented)
1 parent a513439 commit a86e070

2 files changed

Lines changed: 32 additions & 15 deletions

File tree

chat-app/backend/server.js

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const app = express();
55
const port = process.env.PORT || 3000;
66

77
const messages = [];
8-
const callBacksForNewMessages = [];
8+
let callBacksForNewMessages = {};
99

1010
// Enable CORS for all routes
1111
app.use(cors());
@@ -43,12 +43,12 @@ app.post("/messages", (req, res) => {
4343
messages.push(newMessage);
4444

4545
// long polling logic
46-
while (callBacksForNewMessages.length > 0) {
47-
// take the last function out the array
48-
const callback = callBacksForNewMessages.pop();
46+
const waitingCallbacks = Object.values(callBacksForNewMessages);
47+
if (waitingCallbacks.length > 0) {
48+
waitingCallbacks.forEach((eachClient) => eachClient([newMessage]));
4949

50-
// run that function using the newMessage as argument
51-
callback([newMessage]);
50+
// SInce the waiting room still has all the clients I just sent responses to, I need to manually delete them
51+
callBacksForNewMessages = {};
5252
}
5353

5454
// Finally, respond to the person who actually sent the POST request
@@ -69,7 +69,18 @@ app.get("/messages", (req, res) => {
6969
const messagesSinceId = messages.filter((message) => message.id > sinceId);
7070

7171
if (messagesSinceId.length === 0) {
72-
callBacksForNewMessages.push((value) => res.send(value));
72+
const clientId = req.query.clientId;
73+
74+
if (!clientId) {
75+
return res.send([]);
76+
}
77+
callBacksForNewMessages[clientId] = (value) => {
78+
try {
79+
res.send(value);
80+
} catch (e) {
81+
delete callBacksForNewMessages[clientId];
82+
}
83+
};
7384
} else {
7485
res.send(messagesSinceId);
7586
}
@@ -86,18 +97,23 @@ app.post("/messages/:id/like", (req, res) => {
8697
(message) => message.id === idAsNumber,
8798
);
8899

100+
if (!messageWithIdAsNumber) {
101+
return res.status(404).send("Message not found");
102+
}
89103
messageWithIdAsNumber.likes += 1;
90104

91-
if (messageWithIdAsNumber) {
92-
while (callBacksForNewMessages.length > 0) {
93-
const callback = callBacksForNewMessages.pop();
105+
// Get a snapshot list of all the clients' callback in the waiting room (Array)
106+
const waitingCallbacks = Object.values(callBacksForNewMessages);
94107

95-
callback([messageWithIdAsNumber]);
96-
}
97-
res.status(200).send(messageWithIdAsNumber);
98-
} else {
99-
res.status(404).send("Message not found");
108+
if (waitingCallbacks.length > 0) {
109+
waitingCallbacks.forEach((eachClient) => {
110+
eachClient([messageWithIdAsNumber]);
111+
});
112+
113+
// clear the waiting room
114+
callBacksForNewMessages = {};
100115
}
116+
res.status(200).send(messageWithIdAsNumber);
101117
});
102118

103119
// Start the server

chat-app/frontend/script.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const API_BASE_URL = "https://iswanna-chat-app-backend.hosting.codeyourfuture.io";
2+
//const API_BASE_URL = "http://localhost:3000";
23
const myClientId = crypto.randomUUID();
34

45
let lastIdSeen = -1;

0 commit comments

Comments
 (0)