Merge branch 'hotfix/21.56.9' into master
[gitter.git] / docs / send-receive-messages.md
blob4578cd8f28e2c9f121ed0d1c943e812e81d406cc
1 # Sending and receiving messages explained
2 This document will walk you through the implementation of sending and receiving messages end to end.
4 ```mermaid
5 graph TD
6 A[User submits a message] --> B[API endpoint receives the message]
7 B --> C[message gets stored to MongoDB]
8 C --> D[bayeux is used to notify all users active in the room]
9 D --> E[users receive the message through active websocket connection]
10 E --> F[message gets rendered into the main message flow]
11 ```
13 ## User typed in a message and pressed `Enter`
14 1. [ChatInputBoxView.send](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/views/chat/chat-input-box-view.js#L248) adds the new message to `LiveCollection`.
15     - This collection is available from [`router-chat.js`](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/router-chat.js#L260) through [`ChatToolbarInput`](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/views/layouts/chat-toolbar-input.js#L109)
16 1. We use `backbone-proxy-collection` [wrapped by `chats-cached` collection](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/collections/instances/chats-cached.js#L30). This proxy collection uses [`ChatCollection`](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/collections/chat.js#L89) to define how the `LiveCollection` fetches data.
17 1. Thanks to this [`urlTemplate` set to `/v1/rooms/:troupeId/chatMessages`](https://gitlab.com/gitterHQ/webapp/blob/49cc5b37f6691e500dcb23b9dc57fd338ef1a02d/public/js/collections/chat.js#L96) we send a POST request to API when [something is created in the chat collection](https://gitlab.com/gitterHQ/webapp/blob/fc20892381b2c23a0937d19329ea35a11282541e/public/js/views/chat/chat-input-box-view.js#L248).
18 ![Screenshot_2019-05-29_at_13.15.10](/uploads/b36cf0428a8970d2bf80b578352d6ecd/Screenshot_2019-05-29_at_13.15.10.png)
20 ## API listens for POST requests on `/v1/rooms/:troupeId/chatMessages`
21 ```mermaid
22 graph TD
23 A[POST /api/v1/rooms/id] --> B[api/v1/rooms/chat-messages.js.create]
24 B --> C[chat-service.js.newChatMessageToTroupe]
25 C --> D[new message to MongoDB chatMessage.save]
26 C --> E[unreadItemService.createChatUnreadItems]
27 ```
28 1. [`server/api/v1/rooms/chat-messages.js`](https://gitlab.com/gitterHQ/webapp/blob/7984c4966f8322a319172400561f064372ff013c/server/api/v1/rooms/chat-messages.js) handles creation of the new message. The API folder structure copies the URL.
29 1. POST request invokes `create` method which [calls `chatService.newChatMessageToTroupe()`](https://gitlab.com/gitterHQ/webapp/blob/7984c4966f8322a319172400561f064372ff013c/server/api/v1/rooms/chat-messages.js#L85).
30 1. `chatService` [saves the newly created message](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/modules/chats/lib/chat-service.js#L191) to MongoDB.
31     <details>
32     <summary>Example of stored message</summary>
34     ```json
35     {
36         "_id": ObjectID("5d147ea84dad9dfbc522317a"),
37         "fromUserId": ObjectID("5cdc09f6572f607a5bc8a41d"),
38         "toTroupeId": ObjectID("5d07443a17d82eff1cc8265e"),
39         "text": "Example message using a bit of  `code` and **bold** to show how *markdown* is stored.",
40         "pub": true,
41         "html": "Example message using a bit of  <code>code</code> and <strong>bold</strong> to show how <em>markdown</em> is stored.",
42         "lang": "en",
43         "_md": 14,
44         "_tv": 1,
45         "readBy": [],
46         "editedAt": null,
47         "sent": ISODate("2019-06-27T08:30:32.165Z"),
48         "issues": [],
49         "mentions": [],
50         "urls": [],
51         "__v": 0
52     }
53     ```
54   </details>
56 1. `chatService` [uses `unreadItemService` to `createChatUnreadItems`](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/modules/chats/lib/chat-service.js#L209).
58 ## Distribute a message to active users
59 ```mermaid
60 graph TD
61 C[chat-service.js.newChatMessageToTroupe] --> D[new message to MongoDB chatMessage.save]
62 D --> I[persistence-service-events.js ChatMessageSchema.onCreate]
63 I --> J[liveCollections.chats.emit 'create]
64 J --> K[serializeObject - appEvents.dataChange2]
65 K -.-> L[bayeux-events-bridge.js publish]
66 L --> M[bayeux/cluster.js publish]
67 ```
68 1. `persistence-service-events` [adds a new listener on created chat message](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/server/services/persistence-service-events.js#L27) during application startup.
69 1. `live-collection-chat` [emits `dataChange2` with the new message](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/server/services/live-collection-handlers/live-collection-chats.js#L18).
70 1. `bayeux-events-bridge` listens on `dataChange2` and [publishes the message to a bayeux cluster](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/server/event-listeners/bayeux-events-bridge.js#L52).
71 1. `bayeux/cluster` [publishes the message](https://gitlab.com/gitterHQ/webapp/blob/c4387f141ced8272cb6eb5731d19adb84d74d7bf/server/web/bayeux/cluster.js#L265) (internally it's using `redis-faye` to store the message to redis).
73 ## Users subscribing to `chatMessages` channel.
74 There are multiple ways of listening to new messages in a room.
75 - Bayeux protocol over websockets - main mean of the message transport, the only option discussed here
76 - long-polling used as a fallback
78 1. The [realtime-client uses](https://gitlab.com/gitlab-org/gitter/realtime-client/blob/9c11abd8a1206b712272a99aed49c95f1cb10471/lib/realtime-client.js#L308) [`gitter/halley`](https://gitlab.com/gitlab-org/gitter/halley) client to subscribe to [`/bayeux` endpoint](https://gitlab.com/gitlab-org/gitter/realtime-client/blob/9c11abd8a1206b712272a99aed49c95f1cb10471/lib/realtime-client.js#L21).
79 1. webapp [initializes a `chats` `LiveCollections`](https://gitlab.com/gitterHQ/webapp/blob/0a4c1c39acf1efdcaa8f8bd452f15cfe939ff5dc/public/js/collections/chat.js#L96).
80 1. `ChatCollection` [listens on new messages](https://gitlab.com/gitterHQ/webapp/blob/c30893e683bef21634f5a084d8b372f88be9165a/public/js/collections/chat.js#L112).
81 1. `ChatCollection` (wrapped in cache) is [used as the main model for the chat window in `router-chat`](https://gitlab.com/gitterHQ/webapp/blob/c30893e683bef21634f5a084d8b372f88be9165a/public/js/router-chat.js#L72).
83 ## UI displaying a new message
84 - The `ChatCollection` extends `realtime-client.LiveCollection` which in turn [extends `Backbone.Collection`](https://gitlab.com/gitlab-org/gitter/realtime-client/blob/9c11abd8a1206b712272a99aed49c95f1cb10471/lib/live-collection.js#L17).
85 - `ChatCollectionView` is responsible for rendering the chat messages feed. [It extends Marionette.CollectionView](https://gitlab.com/gitterHQ/webapp/blob/f20b8a678938c3d0f306c74293eac3621ef513b4/public/js/views/chat/chatCollectionView.js#L115) which [connects to the `Backbone.Collection` life cycle](https://marionettejs.com/docs/marionette.collectionview.html#marionettecollectionview).
86 - [`ChatCollectionView` specifies `ChatItemView` as a view for one message](https://gitlab.com/gitterHQ/webapp/blob/f20b8a678938c3d0f306c74293eac3621ef513b4/public/js/views/chat/chatCollectionView.js#L135).
87 - [`ChatItemView`](https://gitlab.com/gitterHQ/webapp/blob/f20b8a678938c3d0f306c74293eac3621ef513b4/public/js/views/chat/chatItemView.js) is a juicy view that supports all use cases of one displayed message.
88 - You can find the template for `ChatItemView` in [`chatItemView.hbs`](https://gitlab.com/gitterHQ/webapp/blob/f20b8a678938c3d0f306c74293eac3621ef513b4/public/js/views/chat/tmpl/chatItemView.hbs).