OneOffice Logo

Introduction

Custom Client

Introduction

This section is important, please read it carefully as everything that follows is based on it.

Inspiration

Our approach to server-client communication is based on the MeteorJS DDP model which uses Websockets for real-time communication - More information here.

However, do note that substantial changes have been made for performance improvement (namely that our client is low-level, so we abstract a lot of the high-level features Meteor had added which we feel cater towards junior developers)

Example

Websockets

The example above should come a long way in illustrating how the protocol works. You will notice that all messaging is JSON-based.

In order, here is what is happening

  1. Connection is established -- frames 1 - 2
  2. Client logs in -- frames 3 - 4
  3. Client subscribes to "users" collection to get logged in user information -- frames 5 - 7
  4. Client subscribes to "files" collection to get user files (Note: a resub is occuring due to the reactive native of our application)

Security

At the beginning of an authenticated session, the client logs in. This establishes an authenticated session. The server knows who you are and all requests are validated based on that (e.g. you can only ask for your data).

All communication is over secured connected (protocol is wss:// i.e. secure websocket)

Message Types

The basis of the DDP protocol is two types of communications (all visible in the example above)

  1. Method call (e.g. "loginWithToken" in frame #3)
  2. Subscription (e.g. subscribing to "users" or "files" in example above)

Client-side Data

We will go in more detail later, but our client heavily leans on the client-side reactive database. Along with ReactJS as front-end framework, we are able to render large amounts of data quickly.

The basis of the client-side storage is an implementation of "collections".

A collection is the MongoDB equivalent of an SQL table. The reason we use MongoDB as a reference point is that it is well-suited for functions-based queries. For example, to find all files having parent id 10 you would call:

files.find({parent:10})

There are many examples of MongoDB style of queries in almost all popular development frameworks. You could use any of those, or roll-out your own