ex_chat
ex_chat copied to clipboard
A simple chat server written in Elixir as an example of Websocket usage
ExChat
This is a simple chat server built in Elixir with the goal to show a real life application of Websockets.

Features roadmap
- As a client I want to create a user so that I can use the chat system
- As a user I can send a private message to an existing user to that I can talk directly without using an existing room
Run tests
$ mix deps.get
$ mix test
Run application
$ mix deps.get
$ iex -S mix
How to use the chat
The web client will be available at http://localhost:4000/chat.html
At the moment there are two users in the system. You can use two different URLs in order to get associated to them:
http://localhost:4000/chat.html?access_token=foo_tokento enter as foo_userhttp://localhost:4000/chat.html?access_token=bar_tokento enter as bar_user
Scratchpad
DOING
TODO
- Rename
ChatRoom,ChatRoomsandChatroomtoRoom(basically remove theChatterm) - Rename
session_idoruser_session_idtouser_id - Introduce the ping/pong mechanism between client and server in order to unsubscribe and disconnect a client due inactivity
- Find a way to document the websocket API
- Try to split the API, the Server and the Application Logic in the
UserSessionsand in theChatRoomsmodule- It could be interesting to open a related thread to the ElixirForum, trying to get more feedback
- Think if it could be useful to use
Moxinstead ofMock(think about the use ofBehaviour) - find a way to distribute the Chat across different nodes, in order to use more than one nodes
- we have to think to introduce
gprocfor distribute the lookup processes across different nodes
- we have to think to introduce
- improve the way we make assertions on received messages (e.g. assert_receive wants pattern match and not functions or variables) in the
websocket_test.exs - try to write some acceptance test with Wallaby, for the frontend ?
- setup a continuous integration for the project (e.g. using TravisCI)
- Bonus: Let's try to use
Websockexfor the server too, instead of using the rawcowboy_websocket - try to expose the chat using the IRC protocol
- it seems that we have some flaky tests for "other clients" scenarios
DONE
- Try to decouple the
WebSocketControllerfrom the Application Domain by introducing the Use Cases: - Extract a use case for
SubscribeToUserSession - Extract a use case for
JoinChatRoom - Extract a use case for
CreateChatRoom - Extract a use case for
SendMessageToChatRoom - Extract a use case for
ValidateAccessToken - Should the
WebSocketClientbe renamed inWebSocketController? - As a client I want to be associated to a user so that other clients can see who send messages
- Prepare the system with some initial data:
foo_userassociated to the tokenfoo_tokenbar_userassociated to the tokenbar_token
- Maybe the
AuthenticationServiceis a "Repository" instead. Consider to rename it - Provide a real implementation of the
AuthenticationService - Extract a collaborator for the
WebSocketClientthat will be responsible to understand if there is an existing user_session for a given access_token - Update the UI in order to handle the user id
- It seems that we have a websocket idle timeout issue. Increase the idle timeout to 10 minutes
- Handle the connection when the provided access token is empty or not valid (no user session associated)
- what happen when we try to connect to the chat with an invalid access token
-
- the token not exist or is not valid [DONE]
-
- no token provided [DONE]
-
- Bump to version 2.4 to fix the issue of cowboy 1.0 about the
cowboy_clock badarg - When I join a chat room as an identified user I want to read my user name in the welcome message
- Extract the websocket chat URL in the
WebSocketAcceptanceTests - Rename
ws_clienttoclientin theWebSocketAcceptanceTests - Try to remove all the setup duplication in the
WebSocketAcceptanceTests - Review all the acceptance tests in order to align it with the User Feature
- Use the access_token to open websocket connection from the UI
- Try to associate a WebSocketClient to a UserSession
- Draw the actual application architecture sketch
- Think about to rename
ExChat.SupervisorinExChat.Application - Rename
ExChat.InittoExChat.Setup - Put the
user-session-idas a state ofWebSocketClient - Find a better name for the websocket tests
- Rename
ExChat.Web.WebSockettoExChat.Web.Router - Rename
ChatRoomsWebSocketHandlertoWebSocketClient ChatRooms.sendshould use theuser-session-id- The module
ChatRoomsshould be reorganized like theUserSessions - As a
ChatRoomI can notify of new messages to all the subscribedUserSessions - rename the
UserSessions.sendtoUserSessions.notify - think to rename
clientstosession_idsin theChatRoomprocess - Rename
ExChat.RegistryinExChat.ChatRoomRegistry - rename
user_session_idtosession_id - Maybe the
UserSessionsandUserSessionSupervisorcould be merged in a single module namedUserSessions - Fix the names used for the user sessions in the
UserSessionsTest - Try to find a way to remove the shared state (the
UserSessionRegistry) from theUserSessionsTests - do not start the application when run all the tests
- remove the
UserSession.exists?function in favor of theUserSession.findfunction - Refactor the
UserSessionsmodule in order to achieve the obvious implementation with Supervisors, UserSession Processes, etc, ... - Start writing test from the point of view of the
Clientwho tries to subscribe toUserSessions ExChat.ChatRoomscould be a "simple" module and not a process- remove the empty file
ex_chat_test.exs - Issue during run the tests: It seems that
Elixir.ExChat.Supervisoris already started - handle invalid command
- handle invalid client messages
- rename
subscriberstoclientsinChatRoom - bug: avoid that a client can join twice to a room
- add a
Supervisorto supervise all theChatRoomprocesses - use a registry to name all the
ChatRoomprocesses - think to rename the websocket endpoint (
ws://localhost:4000/room), maybe/chator others - handle the welcome message in the
ChatRoomitself and not in thechatroom_websocket_handler - handle the case when we try to send a message to an unexisting chat room
- update the roadmap features in the readme
- maybe
ExChat.Web.Routeris not a good name for the web sockets delivery mechanism (maybeWeb.WebSocket) - rename
chatroom_websocket_handler.extochat_rooms_websocket_handler.ex - think to separate the two actions
create chatroomandjoin chatroom(at the moment the chatroom creation happens when a client try to join an unexisting chatroom, look at theChatRooms.create_and_join_chatroom/3function) - update the UI so that it can support the create command
- Handle multiple chat rooms
- adapt the UI to handle the room name
- handle the chat room creation when client wants to join to an unexisting chat room
- rename
subscribertoclientinChatRooms - change the format of the response for other tests (add the room name)
- Rename
web.httptoweb.router - Remove the
/echoendpoint just because it is no longer needed - Allow web clients to receive messages
- Allow web clients to write and send messages
- We have to create a better web UI to allows user to write and send messages
- Replace the
plug-web-socketwith the defaultcowboy_websocket_handler - Allow web clients to join a chatroom
- How to test the websocket endpoint in Elixir
- Put
how to run testsandhow to start applicationin theREADME.md - Start the application
- Rename the test folder
exchattoex_chat - As a client I can subscribe to a chat room so that I can receive all the messages sent