Slide 1

Slide 1 text

RethinkDB Tornado & Event Machine

Slide 2

Slide 2 text

Ryan Paul RethinkDB Evangelist @segphault

Slide 3

Slide 3 text

Introduction What is RethinkDB?

Slide 4

Slide 4 text

What is RethinkDB? • Open source database for building realtime web applications • NoSQL database that stores schemaless JSON documents • Distributed database that is easy to scale

Slide 5

Slide 5 text

Built for Realtime Apps • Subscribe to change notifications from database queries • No more polling — the database pushes changes to your app • Reduce the amount of plumbing needed to stream live updates

Slide 6

Slide 6 text

Subscribe to change notifications on database queries Changefeeds

Slide 7

Slide 7 text

r.table("users").changes() Changefeeds Track changes on the users table

Slide 8

Slide 8 text

Changefeeds • The changes command returns a cursor that receives updates • Each update includes the new and old value of the modified record

Slide 9

Slide 9 text

Changefeeds r.table("users") .filter({name: "Bob"}).delete() Changefeed output: { new_val: null, old_val: { id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bob', ... } }

Slide 10

Slide 10 text

Changefeeds r.table("players") .orderBy({index: r.desc("score")}) .limit(3).changes() Track top three players by score Chain the changes command to an actual ReQL query:

Slide 11

Slide 11 text

Async Frameworks Tornado & EventMachine

Slide 12

Slide 12 text

Async Web Frameworks Tornado EventMachine

Slide 13

Slide 13 text

Async Web Frameworks • Event-driven programming • Non-blocking network I/O • Well-suited for the realtime Web

Slide 14

Slide 14 text

Async Web Frameworks • New in RethinkDB 2.0 Python & Ruby drivers • Download the release candidate today • Official release coming in April

Slide 15

Slide 15 text

Async Web Frameworks • Perform queries asynchronously • Consume multiple changefeeds at the same time without blocking

Slide 16

Slide 16 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes)

Slide 17

Slide 17 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Configure the event loop

Slide 18

Slide 18 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Add the coroutine decorator

Slide 19

Slide 19 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Connect to the database

Slide 20

Slide 20 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Perform the ReQL query

Slide 21

Slide 21 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Iterate over changefeed changes

Slide 22

Slide 22 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Fetch the latest change

Slide 23

Slide 23 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Print the change to stdout

Slide 24

Slide 24 text

Tornado import rethinkdb as r from tornado import ioloop, gen r.set_loop_type("tornado") @gen.coroutine def print_changes(): conn = yield r.connect(host="localhost", port=28015) feed = yield r.table("table").changes().run(conn) while (yield feed.fetch_next()) change = yield feed.next() print(change) ioloop.IOLoop.current().add_callback(print_changes) Run coroutine in the background

Slide 25

Slide 25 text

EventMachine require "rethinkdb" include RethinkDB::Shortcuts conn = r.connect host: "localhost", port: 28015 EM.run do r.table("table").changes.em_run(conn) do |err, change| puts change end end

Slide 26

Slide 26 text

EventMachine require "rethinkdb" include RethinkDB::Shortcuts conn = r.connect host: "localhost", port: 28015 EM.run do r.table("table").changes.em_run(conn) do |err, change| puts change end end Connect to the database

Slide 27

Slide 27 text

EventMachine require "rethinkdb" include RethinkDB::Shortcuts conn = r.connect host: "localhost", port: 28015 EM.run do r.table("table").changes.em_run(conn) do |err, change| puts change end end Create an EventMachine block

Slide 28

Slide 28 text

EventMachine require "rethinkdb" include RethinkDB::Shortcuts conn = r.connect host: "localhost", port: 28015 EM.run do r.table("table").changes.em_run(conn) do |err, change| puts change end end Perform the ReQL query

Slide 29

Slide 29 text

EventMachine require "rethinkdb" include RethinkDB::Shortcuts conn = r.connect host: "localhost", port: 28015 EM.run do r.table("table").changes.em_run(conn) do |err, change| puts change end end Print the change to stdout

Slide 30

Slide 30 text

Building Web Apps Realtime Ruby app with Faye

Slide 31

Slide 31 text

Faye Framework • Open source pub/sub framework for realtime messaging • Communication between frontend and backend • Supports Ruby and Node.js on the backend

Slide 32

Slide 32 text

Faye Framework EM.run do ... App = Faye::RackAdapter.new Sinatra::Application, mount: "/faye" conn = r.connect host: "localhost", port: 28015 r.table("todo").changes.em_run(conn) do |err, change| App.get_client.publish("/todo/update", change) end ... end Server-side Ruby code

Slide 33

Slide 33 text

Faye Framework EM.run do ... App = Faye::RackAdapter.new Sinatra::Application, mount: "/faye" conn = r.connect host: "localhost", port: 28015 r.table("todo").changes.em_run(conn) do |err, change| App.get_client.publish("/todo/update", change) end ... end Initialize Faye and bind URL route

Slide 34

Slide 34 text

Faye Framework EM.run do ... App = Faye::RackAdapter.new Sinatra::Application, mount: "/faye" conn = r.connect host: "localhost", port: 28015 r.table("todo").changes.em_run(conn) do |err, change| App.get_client.publish("/todo/update", change) end ... end Connect to the database

Slide 35

Slide 35 text

Faye Framework EM.run do ... App = Faye::RackAdapter.new Sinatra::Application, mount: "/faye" conn = r.connect host: "localhost", port: 28015 r.table("todo").changes.em_run(conn) do |err, change| App.get_client.publish("/todo/update", change) end ... end Perform the ReQL query

Slide 36

Slide 36 text

Faye Framework EM.run do ... App = Faye::RackAdapter.new Sinatra::Application, mount: "/faye" conn = r.connect host: "localhost", port: 28015 r.table("todo").changes.em_run(conn) do |err, change| App.get_client.publish("/todo/update", change) end ... end Publish the update to a channel

Slide 37

Slide 37 text

Faye Framework faye.subscribe("/todo/update", function(data) { console.log(data); }); Client-side JavaScript code

Slide 38

Slide 38 text

DEMO