-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.js
109 lines (97 loc) · 2.72 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
const PROTO_PATH = __dirname + "/simplechat.proto";
const grpc = require("grpc");
const protoLoader = require("@grpc/proto-loader");
const packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
const protoDescriptor = grpc.loadPackageDefinition(packageDefinition);
const simplechat = protoDescriptor.simplechat;
/**
* チャットデータ
*
* @typedef {Object} chatData
*
* @property {number} userId
* @property {string} text
* @property {Date} postDate
*/
/**
* @type {chatData[]} chatDataList
*/
let chatDataList = [];
/**
* 新しく追加されたチャットデータ
*
* @type {chatData[]} latestChatDataList
*/
let latestChatDataList = [];
/**
* 入力中のユーザーのID
*
* @type {Set<number>} typingUserIds
*/
let typingUserIds = new Set;
(async function repeat() {
while (true) {
let lastGetDate = new Date;
await new Promise(resolve => setTimeout(resolve, 2000));
// 最新のチャットのみを保存しておく
latestChatDataList = [];
for (const { userId, text, postDate } of chatDataList) {
if (lastGetDate.getTime() <= postDate.getTime()) {
latestChatDataList.push({ user_id: userId, text });
continue;
}
break;
}
// 入力中のユーザー初期化
typingUserIds = new Set;
}
})();
// チャット追加
function doAddChat(call, callback) {
const { chat_data: { user_id: userId, text } } = call.request;
chatDataList = [
{ userId, text, postDate: new Date },
...chatDataList,
];
callback(null, { result: true });
}
// チャット取得
async function doRepeatChat(call) {
// 接続開始時に全てのチャットの内容を取得
call.write({
chat_data: [...chatDataList].reverse()
.map(({ channel, userId: user_id, text }) => ({ channel, user_id, text })),
});
// 接続している間はループ、接続が切れたらループを抜ける
while (!call.cancelled) {
await new Promise(resolve => setTimeout(resolve, 2000));
call.write({ chat_data: [...latestChatDataList].reverse(), typing_user_id: [...typingUserIds] });
}
}
// 入力しているユーザー追加
function doTypingChat(call, callback) {
typingUserIds.add(call.request.user_id);
callback(null, { result: true });
}
function getServer() {
const server = new grpc.Server();
server.addService(simplechat.ChatCaller.service, {
addChat: doAddChat,
repeatChat: doRepeatChat,
typingChat: doTypingChat,
});
return server;
}
if (require.main === module) {
const server = getServer();
server.bind("0.0.0.0:9090", grpc.ServerCredentials.createInsecure());
server.start();
}
exports.getServer = getServer;