building real time app

65
BUILDING REAL-TIME APP By Steven Yap Futureworkz Pte. Ltd.

Upload: futureworkz

Post on 16-Apr-2017

144 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Building Real Time App

BUILDING REAL-TIME APP

By Steven Yap Futureworkz Pte. Ltd.

Page 2: Building Real Time App

Steven [email protected]://github.com/stevenyap

Page 3: Building Real Time App
Page 4: Building Real Time App

• Host Saigon.rb Ruby Meetup• Co-Founder of Futureworkz• Ruby on Rails coder• Agile startup consultant

Page 5: Building Real Time App

Awesome Ruby on Rails Developmenthttp://www.futureworkz.com

http://playbook.futureworkz.com/

Page 6: Building Real Time App

WHAT IS A REAL-TIME APP?

Page 7: Building Real Time App

“the real-time web consists in making the client interface (or the web side; or the web layer) of a web application, to communicate continuously with the corresponding real-time server, during every user connection.

wikipedia.org/wiki/Real-time_web

Page 8: Building Real Time App

USERS DON'T NEED TO REFRESH THE APP TO

GET NEW DATA

Page 9: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind

A husband and wife shares the same to-do list

Wife creates a to-do item "Buy fruits"

Husband sees the new item (without refreshing!)

Husband sees the total number of items of the list is now 1Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 10: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list

Wife creates a to-do item "Buy fruits"

Husband sees the new item (without refreshing!)

Husband sees the total number of items of the list is now 1Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 11: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits"

Husband sees the new item (without refreshing!)

Husband sees the total number of items of the list is now 1Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 12: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!)

Husband sees the total number of items of the list is now 1Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 13: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 14: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1

Find husband, broadcast count data and update view

Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 15: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1

Find husband, broadcast count data and update view

Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"

API update item and create item

Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 16: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1

Find husband, broadcast count data and update view

Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"

API update item and create item

Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Find wife, broadcast changes and update the view

Wife sees the total number of items is now 2

Wife deletes "Buy oranges"

Page 17: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1

Find husband, broadcast count data and update view

Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"

API update item and create item

Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Find wife, broadcast changes and update the view

Wife sees the total number of items is now 2 Broadcast to wife and update the count

Wife deletes "Buy oranges"

Page 18: Building Real Time App

HOW DO YOU?

Use Cases Development Effort

Build a real time To-do list app in your mind Setup Rails

A husband and wife shares the same to-do list Setup WebSocket

Wife creates a to-do item "Buy fruits" API create item

Husband sees the new item (without refreshing!) Find husband, broadcast item data and update view

Husband sees the total number of items of the list is now 1

Find husband, broadcast count data and update view

Husband refactor the item from "Buy fruits"to "Buy apples" and "Buy oranges"

API update item and create item

Wife sees the "Buy fruits" is changed to "Buy apples" and sees a new item "Buy oranges"

Find wife, broadcast changes and update the view

Wife sees the total number of items is now 2 Broadcast to wife and update the count

Wife deletes "Buy oranges" API delete item, find husband, broadcast item data, broadcast count data and update the view

Page 19: Building Real Time App

DIFFICULTIES IN BUILDING REAL TIME APP

➤ Managing a constant connection between client and server (Long polling or WebSocket)

➤ Messy code to update view via DOM manipulation (prepend, append, change HTML content, remove element)

➤ Messy code to push new changes to the correct clients

➤ Finding the correct clients and WebSocket channels

➤ Detect changes in item count

➤ If a model can update another model, then a view can update a model, which updates another model, and this, in turn, might cause another view to update.

➤ Total number of items in a list

➤ Total number of items by husband

➤ Total number of items by wife

➤ New item created by mistress in a shared list with husband

Page 20: Building Real Time App

A PROPOSED SOLUTION - R4

➤ Rails 5 ActionCable

➤ RethinkDB

➤ ReactJS

➤ Redux

Page 21: Building Real Time App

RAILS 5 - ACTIONCABLE

Page 22: Building Real Time App

RAILS 5 - ACTIONCABLE

➤ WebSocket is a bi-directional real-time communication between client and server

➤ It is a persistent connection between server and browser

➤ Server can send data to browser

➤ Browser can send data back to server

➤ Rails 5 ActionCable makes it "easy" to setup WebSocket

Page 23: Building Real Time App

RAILS 5 - ACTIONCABLE

$ gem install rails --pre --no-ri --no-rdoc --api

Page 24: Building Real Time App

RAILS 5 - ACTIONCABLE

$ gem install rails --pre --no-ri --no-rdoc --api

#app/channels/todos_channel.rbclassTodosChannel<ApplicationCable::Channeldefsubscribedstream_from'todo'endend

Page 25: Building Real Time App

RAILS 5 - ACTIONCABLE

$ gem install rails --pre --no-ri --no-rdoc --api

#app/channels/todos_channel.rbclassTodosChannel<ApplicationCable::Channeldefsubscribedstream_from'todo'endend

#SendamessagetoclientActionCable.server.broadcast('todo',{task:'BuyApples'})

Page 26: Building Real Time App

RAILS 5 - ACTIONCABLE

//JavascriptApp.cable.subscriptions.create('TodosChannel',{received:(data)=>{console.log(data)}})

Page 27: Building Real Time App

RAILS 5 - ACTIONCABLE

# app/channels/todos_channel.rb classTodosChannel<ApplicationCable::Channeldefsubscribedstream_from'todo'end

defcreate(data)todo=Todo.new(data)

iftodo.saveActionCable.server.broadcast('todo',todo)elseActionCable.server.broadcast('todo','Savefailed')endendend

Page 28: Building Real Time App

RAILS 5 - ACTIONCABLE

//JavascriptApp.cable.subscriptions.create('TodosChannel',{received:(data)=>{console.log(data)},

onSubmit:(task)=>{//senddatabacktoserver//callsTodosChannel#create//withdata={task:task}this.perform('create',{task:task})}})

Page 29: Building Real Time App

RAILS 5 - ACTIONCABLE

➤ Two kinds of broadcast:

➤ Operation broadcast (CRUD)

➤ Notification broadcast

➤ Operation broadcast is easy - simply broadcast back the result

➤ Notification broadcast is messy

➤ A todo item created

➤ Broadcast to wife/husband - which channel? which stream?

➤ Broadcast the new count - which channel? which stream?

➤ Broadcast to others - which channel? which stream?

➤ Code found in Channel/Controller/Model/Job/etc

Page 30: Building Real Time App

RETHINKDB

Page 31: Building Real Time App

RETHINKDB

➤ Open Source NoSQL database

➤ Stream changes to server for any changes in data

➤ Instead of finding all the channels to broadcast to, we simply put all notification broadcasting in our channel#subscribed

Page 32: Building Real Time App

RETHINKDB SETUP

#Gemfilegem'nobrainer'

$railsgnobrainer:install

Page 33: Building Real Time App

RETHINKDB SETUP

#models/todo.rbclassTodoincludeNoBrainer::DocumentincludeNoBrainer::Document::Timestamps

field:task,type:String,required:truefield:completed,type:Boolean,required:trueend

Page 34: Building Real Time App

RETHINKDB SETUP

#models/todo.rbclassTodoincludeNoBrainer::DocumentincludeNoBrainer::Document::Timestamps

field:task,type:String,required:truefield:completed,type:Boolean,required:trueend

#UseitlikeActiveRecord!(mostly)todo=Todo.new({task:'Buyapples',completed:false})todo.savetodo.errors.full_messages

Page 35: Building Real Time App

SUBSCRIBE TO CHANGES

#app/channels/todos_channel.rbclassTodosChannel<ApplicationCable::Channeldefsubscribedstream_from'todo'

Todo.all.raw.changes.eachdo|changes|ActionCable.server.broadcast(@stream,changes)endend#...end

Page 36: Building Real Time App

CHANGES STREAM#createatodo{"new_val"=>{"id"=>"3SGzWZLEdC2D6P","task"=>"buyoranges","completed"=>false,"created_at"=>2016-06-0707:31:47+0000,"updated_at"=>2016-06-0707:31:47+0000},"old_val"=>nil}

Page 37: Building Real Time App

CHANGES STREAM#updateatodo{"new_val"=>{"id"=>"3SEIgBkmjHNuNy","task"=>"buyoranges","completed"=>false,"created_at"=>2016-06-0703:12:40+0000,"updated_at"=>2016-06-0707:32:40+0000},"old_val"=>{"id"=>"3SEIgBkmjHNuNy","task"=>"buyapples","completed"=>false,"created_at"=>2016-06-0703:12:40+0000,"updated_at"=>2016-06-0707:32:24+0000}}

Page 38: Building Real Time App

CHANGES STREAM#destroyatodo{"new_val"=>nil,"old_val"=>{"id"=>"3SEIgBkmjHNuNy","task"=>"buyoranges","completed"=>false,"created_at"=>2016-06-0703:12:40+0000,"updated_at"=>2016-06-0707:32:40+0000}}

Page 39: Building Real Time App

RETHINKDB

➤ Notification broadcasting only occurs in channel subscription from RethinkDB

➤ Not hidden in Active Record, Active Job, controllers, channel subscriptions, etc

➤ Single source of notification broadcast

Page 40: Building Real Time App

REACTJS

Page 41: Building Real Time App

REACTJS

➤ Given a set of data, it will render

➤ When the set of data changes, it will automatically re-render

➤ Declarative style, easy to see how the view will turn out

➤ Easy to reason how data is transformed into view

Page 42: Building Real Time App

REACTJS WALKTHROUGH

Page 43: Building Real Time App

REACTJS

➤ Given a fixed data, ReactJS will always render correctly

➤ We can make ReactJS deal with rendering only

➤ Can we extract all data/state management to another place?

Page 44: Building Real Time App

REDUX

Page 45: Building Real Time App

REDUX

➤ Gives the state of entire frontend in a JS Object

➤ When the data changes, it creates a new state and pass to all the React components to re-render (if necessary)

➤ Extracts away all data logic from React

➤ React renders purely based on the state from Redux

➤ Single source of truth for React

Page 46: Building Real Time App

REDUX

#InitialStatestate={todos:[]}

#ReactRendersnothing

Page 47: Building Real Time App

REDUX

#NewMessagetoreducers{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false}

Page 48: Building Real Time App

REDUX

#NewMessagetoreducers{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false}]}

Page 49: Building Real Time App

REDUX#NewMessagetoreducers{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false}]}

#ReactRenders<p>buyapple</p>

Page 50: Building Real Time App

REDUX

#NewMessagetoreducers{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false}

Page 51: Building Real Time App

REDUX#NewMessagetoreducers{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false},{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false}]}

Page 52: Building Real Time App

REDUX#NewMessagetoreducers{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false},{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false}]}

#ReactRenders<p>buyapple</p><p>buyoranges</p>

Page 53: Building Real Time App

REDUX

#NewMessagetoreducers{id:"3SxIYBkmjUnxms",task:"buypears",completed:false}

Page 54: Building Real Time App

REDUX#NewMessagetoreducers{id:"3SxIYBkmjUnxms",task:"buypears",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false},{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false},{id:"3SxIYBkmjUnxms",task:"buypears",completed:false}]}

Page 55: Building Real Time App

REDUX#NewMessagetoreducers{id:"3SxIYBkmjUnxms",task:"buypears",completed:false}

#NewStatestate={todos:[{id:"3SEIgBkmjHNuNy",task:"buyapple",completed:false},{id:"3SGzWZLEdC2D6P",task:"buyoranges",completed:false},{id:"3SxIYBkmjUnxms",task:"buypears",completed:false}]}

#ReactRenders<p>buyapple</p><p>buyoranges</p><p>buypears</p>

Page 56: Building Real Time App

CONNECTING REDUX & REACTJS

Page 57: Building Real Time App

WIRING THEM UP

➤ ReactJS is (almost) pure functions of view

➤ Redux is the single source of truth for frontend data

➤ Rails provides the business logic and WebSocket connection

➤ RethinkDB is the single source of broadcast

RethinkDB

Rails

Redux

ReactJS

dispatch

perform

broadcast

Page 58: Building Real Time App

BENEFITS

➤ Separation of concerns

➤ Easier to subscribe to multiple data changes

➤ Increased use of WebSocket

➤ Real-time app made easy!

Page 59: Building Real Time App

FOOD FOR THOUGHT

➤ Using Opal for frontend React/Redux

➤ Pure frontend vs monolithic app

➤ Redux + React Native mobile developmentwith Rails + Rethinkdb backend

➤ Storing Redux state in backend vs frontend

➤ Websocket vs HTTP

Page 60: Building Real Time App

USING OPAL FOR FRONTEND REACT/REDUX

➤ Ruby everywhere!

➤ Isomorphic app - share code between frontend and backend

Page 61: Building Real Time App

PURE FRONTEND (REDUX + REACTJS) VS MONOLITHIC APP

➤ Enjoy the goodness of frontend development

➤ Separation of concern between frontend and backend

Page 62: Building Real Time App

REDUX + REACT NATIVE MOBILE DEVELOPMENT WITH RAILS + RETHINKDB BACKEND

➤ React = "Learn once, write every where"

➤ ReactJS is very similar to React Native

➤ Easy to onboard web developers onto mobile developments

➤ Enjoy hot reloading, code push, etc

Page 63: Building Real Time App

STORING REDUX STATE IN BACKEND VS FRONTEND

➤ Persist frontend state in backend

➤ Write reducers in Ruby!

➤ Faster performance in calculating new state

➤ Stream state diff to frontend

Page 64: Building Real Time App

WEBSOCKET VS HTTP API

➤ WebSocket is bi-directional

➤ Why do we need to call HTTP API?

➤ Less overhead, faster response

➤ HTTP - fetch and wait and response

➤ WebSocket - push to server and react on response

Page 65: Building Real Time App

RESOURCES

➤ https://github.com/rails/rails/tree/master/actioncable

➤ https://www.rethinkdb.com/docs/guide/ruby/

➤ https://facebook.github.io/react/docs/thinking-in-react.html

➤ http://redux.js.org/index.html

➤ https://egghead.io/courses/getting-started-with-redux