diff options
| author | Melonai <einebeere@gmail.com> | 2021-06-03 02:10:52 +0200 |
|---|---|---|
| committer | Melonai <einebeere@gmail.com> | 2021-06-03 02:10:52 +0200 |
| commit | 1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8 (patch) | |
| tree | 991147a82958413ed7a5c4a30ce6861bbdabb918 | |
| parent | 6f7ce856f784dce0952db2272a85ee70e6e1b159 (diff) | |
| download | rook-1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8.tar.zst rook-1348f3402c9c15c37501c7cf48f6c63ae7f8c1d8.zip | |
Dynamic event handling architecture
| -rw-r--r-- | assets/src/network/channel/connection.ts | 32 | ||||
| -rw-r--r-- | assets/src/network/channel/messages/handler.ts | 93 | ||||
| -rw-r--r-- | assets/src/network/channel/request.ts | 2 | ||||
| -rw-r--r-- | assets/src/network/channel/share.ts | 8 |
4 files changed, 126 insertions, 9 deletions
diff --git a/assets/src/network/channel/connection.ts b/assets/src/network/channel/connection.ts index 52d85d1..6d6f3de 100644 --- a/assets/src/network/channel/connection.ts +++ b/assets/src/network/channel/connection.ts @@ -1,4 +1,11 @@ import { Channel, Push, Socket } from "phoenix"; +import { + Handler, + Handlers, + registerTokenHandler, + UnregisterHandler, +} from "./messages/handler"; +import type { AnyMessage } from "./messages/messages"; import { startRequest } from "./request"; import { startShare } from "./share"; import { connectSocket, fetchToken } from "./socket"; @@ -22,6 +29,7 @@ export type Connection = { channel: Channel | null; token: string | null; state: ConnectionState; + handlers: Handlers; type: Type; }; @@ -30,6 +38,7 @@ const connection: Connection = { channel: null, token: null, state: ConnectionState.CONNECTING_SOCKET, + handlers: {}, type: Type.NONE, }; @@ -55,6 +64,21 @@ export function send(event: string, data: any): Push { return connection.channel.push(event, data); } +export function onWithToken<Message extends AnyMessage>( + event: string, + token: string | null, + handler: Handler<Message> +): UnregisterHandler { + return registerTokenHandler(connection.handlers, event, token, handler); +} + +export function on<Message extends AnyMessage>( + event: string, + handler: Handler<Message> +): UnregisterHandler { + return onWithToken(event, null, handler); +} + export function getOwnToken(): string { if (connection.state <= ConnectionState.FETCHING_TOKEN) { throw new Error("There is no token yet."); @@ -63,6 +87,14 @@ export function getOwnToken(): string { return connection.token; } +export function getChannel(): Channel { + if (connection.state <= ConnectionState.FETCHING_TOKEN) { + throw new Error("There is no channel yet."); + } + + return connection.channel; +} + function updateState(state: ConnectionState) { // TODO: Notify state listeners connection.state = state; diff --git a/assets/src/network/channel/messages/handler.ts b/assets/src/network/channel/messages/handler.ts new file mode 100644 index 0000000..5cfe327 --- /dev/null +++ b/assets/src/network/channel/messages/handler.ts @@ -0,0 +1,93 @@ +import { getChannel } from "../connection"; +import type { AnyMessage } from "./messages"; + +export type Handlers = { + [event: string]: EventHandler<unknown>; +}; + +type EventHandler<Message extends AnyMessage> = { + tokenHandler: TokenHandler<Message>; + directHandlers: Handler<Message>[]; +}; + +export type TokenHandler<Message extends AnyMessage> = { + [token: string]: Handler<Message>; +}; + +export type Handler<Message extends AnyMessage> = (message?: Message) => void; + +export type UnregisterHandler = () => void; + +export function registerTokenHandler<Message extends AnyMessage>( + handlers: Handlers, + event: string, + token: string | null, + handler: Handler<Message> +): UnregisterHandler { + let eventHandler = handlers[event]; + + // If this event did not yet have any handlers registered we have to register it + if (eventHandler === undefined) { + eventHandler = { + tokenHandler: {}, + directHandlers: [], + }; + + handlers[event] = eventHandler; + + registerNewEvent<Message>(eventHandler, event); + } + + let unregister: UnregisterHandler; + + if (token === null) { + const directHandlers = eventHandler.directHandlers; + directHandlers.push(handler); + + unregister = () => { + const index = directHandlers.findIndex(h => h === handler); + directHandlers.splice(index, 1); + }; + } else { + const tokenHandler = eventHandler.tokenHandler; + tokenHandler[token] = handler; + + unregister = () => { + delete tokenHandler[token]; + }; + } + + return unregister; +} + +function registerNewEvent<Message extends AnyMessage>( + eventHandler: EventHandler<Message>, + event: string +) { + const callback = (data: Message) => { + handleEvent<Message>(eventHandler, data); + }; + + getChannel().on(event, callback); +} + +function handleEvent<Message extends AnyMessage>( + eventHandler: EventHandler<Message>, + message: Message +) { + if (message["token"] !== undefined) { + const token = message["token"]; + + const handler: Handler<Message> = eventHandler.tokenHandler[token]; + + if (handler === undefined) { + throw new Error("Received message for an unknown token."); + } + + handler(message); + } + + for (const handler of eventHandler.directHandlers) { + handler(message); + } +} diff --git a/assets/src/network/channel/request.ts b/assets/src/network/channel/request.ts index 801eee1..dd18aab 100644 --- a/assets/src/network/channel/request.ts +++ b/assets/src/network/channel/request.ts @@ -9,6 +9,4 @@ export async function startRequest(connection: Connection) { getShareToken() ); connection.channel = requestChannel; - - // TODO: Handle incoming messages from the request channel } diff --git a/assets/src/network/channel/share.ts b/assets/src/network/channel/share.ts index 10a34fa..f93e8cb 100644 --- a/assets/src/network/channel/share.ts +++ b/assets/src/network/channel/share.ts @@ -8,10 +8,4 @@ export async function startShare(connection: Connection) { connection.token ); connection.channel = shareChannel; - - shareChannel.on("new_request", onNewRequest); -} - -function onNewRequest(data) { - requests.addRequest(data); -} +} \ No newline at end of file |
