fix: make WS handler synchronous — async handler breaks socket.on('message') in @fastify/websocket v8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -52,7 +52,7 @@ async function sendPushToOfflineUsers(userIds: string[], payload: object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function setupWebSocket(app: FastifyInstance) {
|
export function setupWebSocket(app: FastifyInstance) {
|
||||||
(app as any).get('/ws', { websocket: true }, async (socket: any, req: any) => {
|
(app as any).get('/ws', { websocket: true }, (socket: any, req: any) => {
|
||||||
let userId: string | null = null;
|
let userId: string | null = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -64,21 +64,20 @@ export function setupWebSocket(app: FastifyInstance) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uid = userId;
|
||||||
|
|
||||||
// Register connection
|
// Register connection
|
||||||
if (!connections.has(userId)) connections.set(userId, new Set());
|
if (!connections.has(uid)) connections.set(uid, new Set());
|
||||||
connections.get(userId)!.add(socket);
|
connections.get(uid)!.add(socket);
|
||||||
|
|
||||||
// Update last_seen
|
// Update last_seen + notify online (fire-and-forget)
|
||||||
await pool.query('UPDATE users SET last_seen = NOW() WHERE id = $1', [userId]);
|
pool.query('UPDATE users SET last_seen = NOW() WHERE id = $1', [uid]).catch(() => {});
|
||||||
|
pool.query('SELECT DISTINCT chat_id FROM chat_members WHERE user_id = $1', [uid]).then(async ({ rows: memberChats }) => {
|
||||||
// Notify others that user is online
|
for (const row of memberChats) {
|
||||||
const { rows: memberChats } = await pool.query(
|
const ids = await getChatMemberIds(row.chat_id);
|
||||||
'SELECT DISTINCT chat_id FROM chat_members WHERE user_id = $1', [userId]
|
broadcast(ids.filter(id => id !== uid), { type: 'user_online', payload: { userId: uid, online: true } });
|
||||||
);
|
}
|
||||||
for (const row of memberChats) {
|
}).catch(() => {});
|
||||||
const ids = await getChatMemberIds(row.chat_id);
|
|
||||||
broadcast(ids.filter(id => id !== userId), { type: 'user_online', payload: { userId, online: true } });
|
|
||||||
}
|
|
||||||
|
|
||||||
socket.on('message', async (raw: any, isBinary: boolean) => {
|
socket.on('message', async (raw: any, isBinary: boolean) => {
|
||||||
try {
|
try {
|
||||||
@@ -199,20 +198,19 @@ export function setupWebSocket(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
socket.on('close', async () => {
|
socket.on('close', async () => {
|
||||||
if (!userId) return;
|
const set = connections.get(uid);
|
||||||
const set = connections.get(userId);
|
|
||||||
if (set) {
|
if (set) {
|
||||||
set.delete(socket);
|
set.delete(socket);
|
||||||
if (set.size === 0) {
|
if (set.size === 0) {
|
||||||
connections.delete(userId);
|
connections.delete(uid);
|
||||||
await pool.query('UPDATE users SET last_seen = NOW() WHERE id = $1', [userId]);
|
await pool.query('UPDATE users SET last_seen = NOW() WHERE id = $1', [uid]);
|
||||||
|
|
||||||
const { rows: memberChats } = await pool.query(
|
const { rows: memberChats } = await pool.query(
|
||||||
'SELECT DISTINCT chat_id FROM chat_members WHERE user_id = $1', [userId]
|
'SELECT DISTINCT chat_id FROM chat_members WHERE user_id = $1', [uid]
|
||||||
);
|
);
|
||||||
for (const row of memberChats) {
|
for (const row of memberChats) {
|
||||||
const ids = await getChatMemberIds(row.chat_id);
|
const ids = await getChatMemberIds(row.chat_id);
|
||||||
broadcast(ids, { type: 'user_online', payload: { userId, online: false } });
|
broadcast(ids, { type: 'user_online', payload: { userId: uid, online: false } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user