강동현

Message Handler 재작성

1 import { Socket } from "socket.io"; 1 import { Socket } from "socket.io";
2 -import { MessageHandlerRegistry } from "../message/MessageHandlerRegistry"; 2 +import { ServerOutboundMessageMap } from "../../common";
3 -import { Message } from "../message/types"; 3 +import { loginHandler } from "../message/handler/loginHandler";
4 +import { MessageHandlerChain } from "../message/MessageHandlerChain";
4 import { Room } from "../room/Room"; 5 import { Room } from "../room/Room";
5 import { User } from "../user/User"; 6 import { User } from "../user/User";
6 7
...@@ -9,17 +10,21 @@ export class Connection { ...@@ -9,17 +10,21 @@ export class Connection {
9 10
10 public user?: User; 11 public user?: User;
11 12
13 + private messageHandlerChain: MessageHandlerChain;
14 +
12 constructor(socket: Socket) { 15 constructor(socket: Socket) {
13 this.socket = socket; 16 this.socket = socket;
14 - 17 + this.messageHandlerChain = new MessageHandlerChain(this);
15 - MessageHandlerRegistry.registerHandlers(this);
16 } 18 }
17 19
18 public get authenticated(): boolean { 20 public get authenticated(): boolean {
19 return this.user !== undefined; 21 return this.user !== undefined;
20 } 22 }
21 23
22 - public send(message: Message) { 24 + public send<T extends keyof ServerOutboundMessageMap>(
23 - this.socket.emit(message.type, message); 25 + type: T,
26 + message: ServerOutboundMessageMap[T]
27 + ) {
28 + this.socket.emit(type as string, message);
24 } 29 }
25 } 30 }
......
...@@ -15,6 +15,7 @@ export class ConnectionMapper { ...@@ -15,6 +15,7 @@ export class ConnectionMapper {
15 } 15 }
16 16
17 value = new Connection(socket); 17 value = new Connection(socket);
18 + // FIXME: Register connection to the map
18 return value; 19 return value;
19 } 20 }
20 21
......
1 +import { Connection } from "../connection/Connection";
2 +import { ServerInboundMessageMap, ServerResponse } from "../../common/index";
3 +
4 +type ServerHandlerMap<T> = {
5 + [Key in keyof ServerInboundMessageMap]?: (
6 + connection: Connection,
7 + message: Omit<ServerInboundMessageMap[Key], "result">,
8 + scope: T
9 + ) => ServerResponse<
10 + "result" extends keyof ServerInboundMessageMap[Key]
11 + ? ServerInboundMessageMap[Key]["result"]
12 + : undefined
13 + >;
14 +};
15 +
16 +export class HandlerMap<T> {
17 + private scope: T;
18 + private handlers: ServerHandlerMap<T>;
19 +
20 + constructor(scope: T, handlers: ServerHandlerMap<T>) {
21 + this.scope = scope;
22 + this.handlers = handlers;
23 + }
24 +
25 + public handle(
26 + type: keyof ServerInboundMessageMap,
27 + connection: Connection,
28 + message: any,
29 + callback: Function
30 + ): boolean {
31 + const handler = this.handlers[type];
32 + if (!handler) return false;
33 + const response = handler(connection, message, this.scope);
34 + callback(response);
35 + return true;
36 + }
37 +}
1 +import { Connection } from "../connection/Connection";
2 +import { ServerInboundMessageMap, ServerResponse } from "../../common/index";
3 +import { keys } from "ts-transformer-keys";
4 +
5 +export class MessageHandlerChain {
6 + connection: Connection;
7 +
8 + constructor(connection: Connection) {
9 + this.connection = connection;
10 +
11 + for (const key in keys<ServerInboundMessageMap>()) {
12 + const type = key as keyof ServerInboundMessageMap;
13 + this.connection.socket.on(key, (message: any, callback: Function) => {
14 + if (
15 + connection?.user &&
16 + connection.user.handler.handle(
17 + type,
18 + connection,
19 + message.data,
20 + callback
21 + )
22 + )
23 + return;
24 +
25 + // TODO: Add more handlers
26 + });
27 + }
28 + }
29 +}
1 -import { Connection } from "../connection/Connection";
2 -import { User } from "../user/User";
3 -import { loginHandler } from "./handler/loginHandler";
4 -import { roomChatHandler } from "./handler/roomChatHandler";
5 -import { roomJoinHandler } from "./handler/roomJoinHandler";
6 -import { roomLeaveHandler } from "./handler/roomLeaveHandler";
7 -import { roomListRequestHandler } from "./handler/roomListRequestHandler";
8 -import { Message, MessageResponse, MessageType } from "./types";
9 -
10 -export class MessageHandlerRegistry {
11 - static registerHandlers(connection: Connection) {
12 - this.registerHandler(connection, MessageType.LOGIN, loginHandler);
13 - this.registerHandlerAuthed(
14 - connection,
15 - MessageType.ROOM_LIST_REQUEST,
16 - roomListRequestHandler
17 - );
18 - this.registerHandlerAuthed(
19 - connection,
20 - MessageType.ROOM_JOIN,
21 - roomJoinHandler
22 - );
23 - this.registerHandlerAuthed(
24 - connection,
25 - MessageType.ROOM_LEAVE,
26 - roomLeaveHandler
27 - );
28 - this.registerHandlerAuthed(
29 - connection,
30 - MessageType.ROOM_CHAT,
31 - roomChatHandler
32 - );
33 - }
34 -
35 - private static registerHandler<T extends Message, S>(
36 - connection: Connection,
37 - typeName: string,
38 - handler: (connection: Connection, message: T) => MessageResponse<S>
39 - ) {
40 - connection.socket.on(typeName, (message: T, callback: Function) => {
41 - const response = handler(connection, message);
42 - callback(response);
43 - });
44 - }
45 -
46 - private static registerHandlerAuthed<T extends Message, S>(
47 - connection: Connection,
48 - typeName: string,
49 - handler: (user: User, message: T) => MessageResponse<S>
50 - ) {
51 - connection.socket.on(typeName, (message: T, callback: Function) => {
52 - if (connection.user !== undefined) {
53 - const response = handler(connection.user, message);
54 - callback(response);
55 - } else {
56 - callback({ ok: false });
57 - }
58 - });
59 - }
60 -}
1 import { Connection } from "../connection/Connection"; 1 import { Connection } from "../connection/Connection";
2 +import { HandlerMap } from "../message/MessageHandler";
2 import { Room } from "../room/Room"; 3 import { Room } from "../room/Room";
3 import { UserData } from "./types"; 4 import { UserData } from "./types";
4 5
...@@ -9,9 +10,12 @@ export class User { ...@@ -9,9 +10,12 @@ export class User {
9 10
10 public room?: Room; 11 public room?: Room;
11 12
13 + public handler: HandlerMap<User>;
14 +
12 constructor(username: string, connection: Connection) { 15 constructor(username: string, connection: Connection) {
13 this.username = username; 16 this.username = username;
14 this.connection = connection; 17 this.connection = connection;
18 + this.handler = new HandlerMap<User>(this, {});
15 } 19 }
16 20
17 public getData(): UserData { 21 public getData(): UserData {
......