feat: http user join/leave
This commit is contained in:
parent
7780efa239
commit
a2a485fbee
|
@ -1,47 +1,40 @@
|
||||||
import {joinChannel} from '~/common/channel';
|
import {joinChannel} from '~/common/channel';
|
||||||
|
|
||||||
import createRedisClient from './redis';
|
import createRedisClient, {keys} from './redis';
|
||||||
|
|
||||||
const redisClient = createRedisClient();
|
const redisClient = createRedisClient();
|
||||||
|
|
||||||
const enterChannel = async (req, channel) => {
|
const channelState = async (req, channel) => {
|
||||||
const messages = await new Promise((resolve, reject) => {
|
const messageKeys = await keys(redisClient, `${channel}:messages:*`);
|
||||||
redisClient.scan(
|
const messages = 0 === messageKeys.length
|
||||||
0,
|
? []
|
||||||
'COUNT', 50,
|
: await new Promise((resolve, reject) => {
|
||||||
'MATCH', `${channel}:*`,
|
redisClient.mget(messageKeys, (error, replies) => (
|
||||||
(error, [, keys]) => (
|
|
||||||
error
|
error
|
||||||
? reject(error)
|
? reject(error)
|
||||||
: resolve(
|
: resolve(replies
|
||||||
0 === keys.length
|
.map((reply, i) => ({
|
||||||
? []
|
...JSON.parse(reply),
|
||||||
: new Promise((resolve, reject) => {
|
uuid: messageKeys[i].split(':')[2],
|
||||||
redisClient.mget(keys, (error, replies) => (
|
}))
|
||||||
error
|
.sort((l, r) => l.timestamp - r.timestamp))
|
||||||
? reject(error)
|
));
|
||||||
: resolve(replies
|
});
|
||||||
.map((reply, i) => ({
|
const socketKeys = await keys(redisClient, `${channel}:users:*`);
|
||||||
...JSON.parse(reply),
|
const users = 0 === socketKeys.length
|
||||||
uuid: keys[i].split(':')[1],
|
? []
|
||||||
}))
|
: await new Promise((resolve, reject) => {
|
||||||
.sort((l, r) => l.timestamp - r.timestamp))
|
redisClient.mget(socketKeys, (error, replies) => (
|
||||||
));
|
error ? reject(error) : resolve(
|
||||||
}),
|
Object
|
||||||
)
|
.keys(replies.reduce((r, k) => ({[k]: true, ...r}), {}))
|
||||||
),
|
.map((idStrings) => parseInt(idStrings, 10)),
|
||||||
);
|
)
|
||||||
});
|
));
|
||||||
// const users = await new Promise((resolve, reject) => {
|
});
|
||||||
// req.adapter.remoteJoin(req.socketId, channel, (error) => {
|
|
||||||
// if (error) {
|
|
||||||
// reject(error);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
return {
|
return {
|
||||||
messages,
|
messages,
|
||||||
|
users,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -72,14 +65,14 @@ export const chatState = async (req) => {
|
||||||
recent: [],
|
recent: [],
|
||||||
};
|
};
|
||||||
const entries = await Promise.all(
|
const entries = await Promise.all(
|
||||||
toHydrate.map((favorite) => enterChannel(req, joinChannel(favorite))),
|
toHydrate.map((favorite) => channelState(req, joinChannel(favorite))),
|
||||||
);
|
);
|
||||||
for (let i = 0; i < toHydrate.length; i++) {
|
for (let i = 0; i < toHydrate.length; i++) {
|
||||||
const channel = joinChannel(toHydrate[i]);
|
const channel = joinChannel(toHydrate[i]);
|
||||||
const {messages} = entries[i];
|
const {messages, users} = entries[i];
|
||||||
chat.channels[channel] = {
|
chat.channels[channel] = {
|
||||||
messages: messages.map((message) => message.uuid),
|
messages: messages.map((message) => message.uuid),
|
||||||
users: [],
|
users,
|
||||||
};
|
};
|
||||||
messages.forEach((message) => {
|
messages.forEach((message) => {
|
||||||
chat.messages[message.uuid] = message;
|
chat.messages[message.uuid] = message;
|
||||||
|
|
|
@ -11,7 +11,7 @@ import Message from '~/common/packets/message.packet';
|
||||||
import {channelsToHydrate} from '~/server/entry';
|
import {channelsToHydrate} from '~/server/entry';
|
||||||
|
|
||||||
import passport from './passport';
|
import passport from './passport';
|
||||||
import createRedisClient from './redis';
|
import createRedisClient, {keys} from './redis';
|
||||||
import session from './session';
|
import session from './session';
|
||||||
|
|
||||||
const pubClient = createRedisClient();
|
const pubClient = createRedisClient();
|
||||||
|
@ -46,6 +46,17 @@ export function createSocketServer(httpServer) {
|
||||||
);
|
);
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
socketServer.io.use(async (socket, next) => {
|
||||||
|
await Promise.all(
|
||||||
|
channelsToHydrate(socket.handshake)
|
||||||
|
.map((channel) => new Promise((resolve, reject) => {
|
||||||
|
const key = `${joinChannel(channel)}:users:${socket.id}`;
|
||||||
|
const {user} = socket.handshake;
|
||||||
|
pubClient.set(key, user ? user.id : 0, (error) => (error ? reject(error) : resolve()));
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
next();
|
||||||
|
});
|
||||||
socketServer.on('connect', (socket) => {
|
socketServer.on('connect', (socket) => {
|
||||||
const {req} = socket;
|
const {req} = socket;
|
||||||
socket.on('packet', (packet, fn) => {
|
socket.on('packet', (packet, fn) => {
|
||||||
|
@ -54,7 +65,7 @@ export function createSocketServer(httpServer) {
|
||||||
const owner = req.user ? req.user.id : 0;
|
const owner = req.user ? req.user.id : 0;
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
const uuid = uuidv4();
|
const uuid = uuidv4();
|
||||||
const key = `${channel}:${uuid}`;
|
const key = `${channel}:messages:${uuid}`;
|
||||||
pubClient
|
pubClient
|
||||||
.multi()
|
.multi()
|
||||||
.set(key, JSON.stringify({
|
.set(key, JSON.stringify({
|
||||||
|
@ -66,6 +77,12 @@ export function createSocketServer(httpServer) {
|
||||||
.exec(() => fn([timestamp, uuid]));
|
.exec(() => fn([timestamp, uuid]));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
socket.on('disconnect', async () => {
|
||||||
|
const socketKeys = await keys(pubClient, `*:users:${socket.id}`);
|
||||||
|
if (socketKeys.length > 0) {
|
||||||
|
pubClient.del(socketKeys);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return socketServer;
|
return socketServer;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user