(Video here: http://confreaks.com/videos/5014-RubyConf2014-6-reasons-jubilee-could-be-a-rubyist-s-new-best-friend or https://www.youtube.com/watch?feature=player_embedded&v=FFR0G89WXI8)
Rubyconf 2014 talk on Jubilee, a Vert.x module that runs rack apps.
Alternate titles
Beyond Rails while using Rails
Rails can't do everything I want and <fill> makes me want to cry
Rubyconf abstract
Do you do web development in Ruby? Have you been forced to go to node or other technologies just for concurrency/websockets etc. Do miss your gems, and tire of functionality you have to implement from scratch? Do you hate javascript?
Well no need to switch languages/platforms, Jubilee could be your new best friend.
Jubilee, a rack server on top of Vert.x gives you
* Concurrency
* Speed
* Easy Websockets support
* Shared Memory
* Access to the JVM ecosystem
* Ability to reuse your existing Ruby knowledge and gems
"Say Hello to your new friend" - Al Pacino
FEA Based Level 3 Assessment of Deformed Tanks with Fluid Induced Loads
6 reasons Jubilee could be a Rubyist's new best friend
1. 6 REASONS JUBILEE COULD BE
A RUBYIST’S NEW BEST FRIEND
FORREST CHANG
@FKCHANG2000
https://bambegin.files.wordpress.com/2014/09/tumblr_mfm9lq28cn1s14crlo1_500.jpg
6. RAILS CAN’T DO ALL THE
STUFF I WANT ANYMORE
AND <FILL IN THE TECH>
MAKES ME WANT TO CRY
http://www.louiseoneillauthor.com/wp-content/uploads/2014/06/crying-baby.jpg
14. “For me the purpose of life is partly to have joy.
Programmers often feel joy when they can
concentrate on the creative side of programming,
So Ruby is designed to make programmers happy.”
–MATZ
http://euruko.org/img/matz_800.jpg
15. “For me the purpose of life is partly to have joy.
Programmers often feel joy when they can
concentrate on the creative side of programming,
So Ruby is designed to make programmers happy.”
–MATZ
http://euruko.org/img/matz_800.jpg
27. 1) LANGUAGE ITSELF IS DELIGHTFUL
• An entire talk can be done on this
• So I won't do one
28. SINGLE EXAMPLE FROM DEVISE
CONFIG
# ==> Configuration for :validatable!
# Range for password length. Default is 8..128.!
config.password_length = 8..128
29. SINGLE EXAMPLE FROM DEVISE
CONFIG
# ==> Configuration for :validatable!
# Range for password length. Default is 8..128.!
config.password_length = 8..128
• Intent is so clear
30. SINGLE EXAMPLE FROM DEVISE
CONFIG
# ==> Configuration for :validatable!
# Range for password length. Default is 8..128.!
config.password_length = 8..128
• Intent is so clear
• Nothing extraneous
31. SINGLE EXAMPLE FROM DEVISE
CONFIG
# ==> Configuration for :validatable!
# Range for password length. Default is 8..128.!
config.password_length = 8..128
• Intent is so clear
• Nothing extraneous
• Compared to new TimeRange(8, 128)
32. SINGLE EXAMPLE FROM DEVISE
CONFIG
# ==> Configuration for :validatable!
# Range for password length. Default is 8..128.!
config.password_length = 8..128
• Intent is so clear
• Nothing extraneous
• Compared to new TimeRange(8, 128)
• Beautiful
36. 2) GEMS AND FRAMEWORKS
• Many gems, nearly anything you'd want ready to go
37. 2) GEMS AND FRAMEWORKS
• Many gems, nearly anything you'd want ready to go
• Choice, often more than 1 gem for the job
38. 2) GEMS AND FRAMEWORKS
• Many gems, nearly anything you'd want ready to go
• Choice, often more than 1 gem for the job
• Gem authors tend to emulate Matz and try to make the
programmer happy
39. 800lb Gorilla of Rubygems
http://www.examiner.com/images/blog/wysiwyg/image/4056_Landing_gorilla-1.jpg
42. RAILS
• Who codes in Rails?
• Who came to Ruby from Rails?
43. RAILS
• Who codes in Rails?
• Who came to Ruby from Rails?
• Who was coding Ruby before Rails?
44. RAILS
• Who codes in Rails?
• Who came to Ruby from Rails?
• Who was coding Ruby before Rails?
• Who loves Rails?
45. RAILS
• Who codes in Rails?
• Who came to Ruby from Rails?
• Who was coding Ruby before Rails?
• Who loves Rails?
• Who has a job because of Rails?
47. WHY WE LOVE RAILS
• A whole talk can be done this
48. WHY WE LOVE RAILS
• A whole talk can be done this
• So I won't do one
49. WHY WE LOVE RAILS
• A whole talk can be done this
• So I won't do one
• Productivity
50. WHY WE LOVE RAILS
• A whole talk can be done this
• So I won't do one
• Productivity
• Programmer interface - Omokase, designed to make
the coder happy
56. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
57. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
• Scaling
58. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
• Scaling
• Resource heavy
59. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
• Scaling
• Resource heavy
• Computation heavy
60. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
• Scaling
• Resource heavy
• Computation heavy
• More/better Library functionality elsewhere
61. SOME REASONS TO NOT USE RUBY
• Speed
• Image processing, video encoding
• Scaling
• Resource heavy
• Computation heavy
• More/better Library functionality elsewhere
• Scientific programming support better in Python, etc.
68. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
69. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
70. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
• Chat app demonstrates Node’s sweet spot
71. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
• Chat app demonstrates Node’s sweet spot
• high concurrency
72. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
• Chat app demonstrates Node’s sweet spot
• high concurrency
• quick, low CPU usage transactions
73. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
• Chat app demonstrates Node’s sweet spot
• high concurrency
• quick, low CPU usage transactions
• server push
74. NODE, WHAT IT IS GOOD FOR?
• Quick, Non blocking I/O
• Concurrency
• Chat app demonstrates Node’s sweet spot
• high concurrency
• quick, low CPU usage transactions
• server push
• so called "modern webapp"
105. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
106. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
107. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
• Handles Blocking IO or Long running operations
108. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
• Handles Blocking IO or Long running operations
• Worker verticles - uses threadpools
109. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
• Handles Blocking IO or Long running operations
• Worker verticles - uses threadpools
• System scaling
110. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
• Handles Blocking IO or Long running operations
• Worker verticles - uses threadpools
• System scaling
• Horizontal scaling- Clustering
111. BETTER THAN NODE
• Handles CPU intensive
• JVM fast (JRuby fastes of the Rubies)
• JVM thread friendly
• Handles Blocking IO or Long running operations
• Worker verticles - uses threadpools
• System scaling
• Horizontal scaling- Clustering
• Vertical scaling- Verticle per CPU
114. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
115. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
• Beta: Clojure, Scala, PhP (really?)
116. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
• Beta: Clojure, Scala, PhP (really?)
• any JVM lang or one compiles to a JVM language
117. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
• Beta: Clojure, Scala, PhP (really?)
• any JVM lang or one compiles to a JVM language
• General Applications platform
118. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
• Beta: Clojure, Scala, PhP (really?)
• any JVM lang or one compiles to a JVM language
• General Applications platform
• “modern web pages”
119. BETTER THAN NODE, PART 2
• Polyglot
• Official idiomatic API support: Java, Javascript, Groovy,
Coffeescript, *Ruby (by way of JRuby)*, Python
• Beta: Clojure, Scala, PhP (really?)
• any JVM lang or one compiles to a JVM language
• General Applications platform
• “modern web pages”
• traditional enterprise backends
122. BETTER THAN NODE, PART 3
• Designed to build systems of systems
• Easy High Availability
123. BETTER THAN NODE, PART 3
• Designed to build systems of systems
• Easy High Availability
• Easy Clustering
124. BETTER THAN NODE, PART 3
• Designed to build systems of systems
• Easy High Availability
• Easy Clustering
• Easy subsystem Intercommunication
125. BETTER THAN NODE, PART 3
• Designed to build systems of systems
• Easy High Availability
• Easy Clustering
• Easy subsystem Intercommunication
• Event Bus
126. BETTER THAN NODE, PART 3
• Designed to build systems of systems
• Easy High Availability
• Easy Clustering
• Easy subsystem Intercommunication
• Event Bus
• Shared Data
129. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
130. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
131. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
• SockJS
132. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
• SockJS
• File system
133. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
• SockJS
• File system
• Event bus
134. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
• SockJS
• File system
• Event bus
• DNS
135. CORE APIS- WHAT YOU NEED
• TCP/SSL clients and servers
• HTTP/HTTPS clients and servers
• Websockets
• SockJS
• File system
• Event bus
• DNS
• UDP
137. DUCT TAPE
• Open SourceSystems are duct taped together
138. DUCT TAPE
• Open SourceSystems are duct taped together
• We figure out how to do to put together things
139. DUCT TAPE
• Open SourceSystems are duct taped together
• We figure out how to do to put together things
• Perl used to be the duct tape of the internet, Ruby a
cleaner Perl…
140. DUCT TAPE
• Open SourceSystems are duct taped together
• We figure out how to do to put together things
• Perl used to be the duct tape of the internet, Ruby a
cleaner Perl…
• Gems formalize that
141. DUCT TAPE
• Open SourceSystems are duct taped together
• We figure out how to do to put together things
• Perl used to be the duct tape of the internet, Ruby a
cleaner Perl…
• Gems formalize that
• In Node, thats what you do even more
152. INTER PROCESS/SYSTEM
COMMUNICATION
• Event Bus
• publish
• direct message
• direct message reply
• extends into the browser
• Shared Data
153. INTER PROCESS/SYSTEM
COMMUNICATION
• Event Bus
• publish
• direct message
• direct message reply
• extends into the browser
• Shared Data
• Hash
154. INTER PROCESS/SYSTEM
COMMUNICATION
• Event Bus
• publish
• direct message
• direct message reply
• extends into the browser
• Shared Data
• Hash
• Set
162. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
163. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
• 2 Good overview videos
164. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
• 2 Good overview videos
• Tim Fox: Introducing Vert.x 2.0 - Taking Polyglot Application
Development to the Next Level https://www.youtube.com/watch?
v=3hv4QD5ZvKE
165. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
• 2 Good overview videos
• Tim Fox: Introducing Vert.x 2.0 - Taking Polyglot Application
Development to the Next Level https://www.youtube.com/watch?
v=3hv4QD5ZvKE
• good over view of vert.x capabilities w/lots of live demos
166. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
• 2 Good overview videos
• Tim Fox: Introducing Vert.x 2.0 - Taking Polyglot Application
Development to the Next Level https://www.youtube.com/watch?
v=3hv4QD5ZvKE
• good over view of vert.x capabilities w/lots of live demos
• Vert.x: This ain't your Dad's Node. https://www.youtube.com/watch?
v=8ClYUo_A3h0
167. AND MUCH MORE
• A whole talk could be done on it
• So I won’t do one
• 2 Good overview videos
• Tim Fox: Introducing Vert.x 2.0 - Taking Polyglot Application
Development to the Next Level https://www.youtube.com/watch?
v=3hv4QD5ZvKE
• good over view of vert.x capabilities w/lots of live demos
• Vert.x: This ain't your Dad's Node. https://www.youtube.com/watch?
v=8ClYUo_A3h0
• good at showing Vert.x's advantages over Node.js
176. ORIGINAL JUBILEE README SLOGAN
"We need a web framework for Vertx.", you said.
"But why not use Vertx in your Rails applications,
it's the most productive
web framework ever created."
179. JUBILEE
• Originally Rack server w/ vert.x 2.0 built in
• Now a Vert.x module that runs Rack
180. JUBILEE
• Originally Rack server w/ vert.x 2.0 built in
• Now a Vert.x module that runs Rack
• improved performance and interaction with the
Vert.x ecosystem
181. JUBILEE
• Originally Rack server w/ vert.x 2.0 built in
• Now a Vert.x module that runs Rack
• improved performance and interaction with the
Vert.x ecosystem
• All the power of vert.x AND you can keep doing
Ruby/Rack programming
182. JUBILEE
• Originally Rack server w/ vert.x 2.0 built in
• Now a Vert.x module that runs Rack
• improved performance and interaction with the
Vert.x ecosystem
• All the power of vert.x AND you can keep doing
Ruby/Rack programming
• Try that with Node!
185. 6 REASONS VERT.X COULD BE YOUR
NEW BEST FRIEND
• Concurrency
• Speed
186. 6 REASONS VERT.X COULD BE YOUR
NEW BEST FRIEND
• Concurrency
• Speed
• Expanded Ecosystem
187. 6 REASONS VERT.X COULD BE YOUR
NEW BEST FRIEND
• Concurrency
• Speed
• Expanded Ecosystem
• Built in upgrade/scaling path
188. 6 REASONS VERT.X COULD BE YOUR
NEW BEST FRIEND
• Concurrency
• Speed
• Expanded Ecosystem
• Built in upgrade/scaling path
• Easy web sockets support
189. 6 REASONS VERT.X COULD BE YOUR
NEW BEST FRIEND
• Concurrency
• Speed
• Expanded Ecosystem
• Built in upgrade/scaling path
• Easy web sockets support
• Reuse all your existing knowledge/resources
192. 1) CONCURRENCY
• Same Reactor pattern as Node
• Each Verticle single threaded
193. 1) CONCURRENCY
• Same Reactor pattern as Node
• Each Verticle single threaded
• Simple concurrency model, no threading
194. 1) CONCURRENCY
• Same Reactor pattern as Node
• Each Verticle single threaded
• Simple concurrency model, no threading
• Multiple verticles, can do 1 per CPU
208. JUBILEE - 2ND FASTEST RUBY SERVER
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark-
report.html
209. JUBILEE - 2ND FASTEST RUBY SERVER
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark-
report.html
• Maximum speed benchmarks vs typical
210. JUBILEE - 2ND FASTEST RUBY SERVER
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark-
report.html
• Maximum speed benchmarks vs typical
• JRuby clear leader across the board
211. JUBILEE - 2ND FASTEST RUBY SERVER
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark-
report.html
• Maximum speed benchmarks vs typical
• JRuby clear leader across the board
• Almost as fast as golang
218. 3 ) E X PANDED ECOSYSTEM
• Rubygems
• Must run under JRuby
219. 3 ) E X PANDED ECOSYSTEM
• Rubygems
• Must run under JRuby
• Vertx modules (200 at time of writing)
220. 3 ) E X PANDED ECOSYSTEM
• Rubygems
• Must run under JRuby
• Vertx modules (200 at time of writing)
• Entire JVM ecosystem, languages, libraries
221. 3 ) E X PANDED ECOSYSTEM
• Rubygems
• Must run under JRuby
• Vertx modules (200 at time of writing)
• Entire JVM ecosystem, languages, libraries
• Call other JVM languages directly from JRuby
222. 3 ) E X PANDED ECOSYSTEM
• Rubygems
• Must run under JRuby
• Vertx modules (200 at time of writing)
• Entire JVM ecosystem, languages, libraries
• Call other JVM languages directly from JRuby
• Can run other JVM language verticles and
communicate via Event Bus
224. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
225. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
226. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
227. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
• Core APIs
228. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
• Core APIs
• Event Bus
229. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
• Core APIs
• Event Bus
• Shared Data
230. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
• Core APIs
• Event Bus
• Shared Data
• Clustering
231. 4 ) BUILT IN UPGRADE/SCALING PATH
• Designed for multiple verticles (async)
• Worker verticles (slow)
• Inter communication
• Core APIs
• Event Bus
• Shared Data
• Clustering
• High Availability
235. 5) EASY WEBSOCKETS SUPPORT
• SocketIO support
• SockJS support
• ** Event Bus **
236. 5) EASY WEBSOCKETS SUPPORT
• SocketIO support
• SockJS support
• ** Event Bus **
• Easy
237. 5) EASY WEBSOCKETS SUPPORT
• SocketIO support
• SockJS support
• ** Event Bus **
• Easy
• Extends into the browser
238. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
239. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
• Ruby
240. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
• Ruby
• Rack programming
241. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
• Ruby
• Rack programming
• i.e. Rails, Sinatra, etc.
242. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
• Ruby
• Rack programming
• i.e. Rails, Sinatra, etc.
• Gems
243. 6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/
RESOURCES
• Ruby
• Rack programming
• i.e. Rails, Sinatra, etc.
• Gems
• Low barrier to entry for the Rubyist!
247. RUNNING WITH RACK
$ cd a-jruby-compatible-rack-app!
# Start it, several options available!
$ jubilee <options> !
# If you don’t need jubilee options!
$ rails s jubilee!
$ rackup -s jubilee!
# running as vertx module!
$ vertx run config.ru -conf config.json !
261. NODE’S SWEET SPOT
• Chat - The sample app that everyone makes
• How do I make a chat app a little more interesting?
262. NODE’S SWEET SPOT
• Chat - The sample app that everyone makes
• How do I make a chat app a little more interesting?
• How about a game with chat characterstics
270. EXPERIENCING JUBILEE IN ACTION
• Everyone in the room sign on
• Play each other
• Have fun!
271. EXPERIENCING JUBILEE IN ACTION
• Everyone in the room sign on
• Play each other
• Have fun!
• Then we talk
272. EXPERIENCING JUBILEE IN ACTION
• Everyone in the room sign on
• Play each other
• Have fun!
• Then we talk
• EXPERIMENT WARNING: Intentionally running in 1 dyno,
curious to see how it scales
273. EXPERIENCING JUBILEE IN ACTION
• Everyone in the room sign on
• Play each other
• Have fun!
• Then we talk
• EXPERIMENT WARNING: Intentionally running in 1 dyno,
curious to see how it scales
• Conference WIFI
274. EXPERIENCING JUBILEE IN ACTION
• Everyone in the room sign on
• Play each other
• Have fun!
• Then we talk
• EXPERIMENT WARNING: Intentionally running in 1 dyno,
curious to see how it scales
• Conference WIFI
• Sound effects file (bad decision?)
280. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
281. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
• Android users click the “Play Sound” button to prime sound
(HTML5 audio not quite there yet)
282. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
• Android users click the “Play Sound” button to prime sound
(HTML5 audio not quite there yet)
• Likely to be the most taxing on conference wifi, (experiment)
283. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
• Android users click the “Play Sound” button to prime sound
(HTML5 audio not quite there yet)
• Likely to be the most taxing on conference wifi, (experiment)
• Pick opponents and play
284. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
• Android users click the “Play Sound” button to prime sound
(HTML5 audio not quite there yet)
• Likely to be the most taxing on conference wifi, (experiment)
• Pick opponents and play
• Observe activity, player states
285. WHAT TO DO
• Go to http://bit.ly/rpsmayhem
• Login with twitter
• Android users click the “Play Sound” button to prime sound
(HTML5 audio not quite there yet)
• Likely to be the most taxing on conference wifi, (experiment)
• Pick opponents and play
• Observe activity, player states
• If something’s off, refresh page, in progress matches will get
rejoined
318. REALTIME MMO GAMEPLAY
Connected to server and
each other by EventBus,
uses SharedData for speed
319. REALTIME MMO GAMEPLAY
Connected to server and
each other by EventBus,
uses SharedData for speed
The bot is it’s own
Verticle, playing via
EventBus
320. ARCHITECTURE IN 1 DYNO
RAILS
EVENT
BOT BUS
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
321. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
BOT BUS
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
322. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
BOT BUS
SVR
SHARED
DATA
BROWSER
CLIENT
Rabbit MQ or similar
TIMERS
323. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
BOT BUS
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
Server is EventBus handler,
would be
another process
to handle concurrency
Rabbit MQ or similar
324. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
BOT BUS
Redis, Tokyo Cabinet, etc. Rabbit MQ or similar
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
Server is EventBus handler,
would be
another process
to handle concurrency
325. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
BOT BUS
Redis, Tokyo Cabinet, etc. Rabbit MQ or similar
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
Server is EventBus handler,
would be
another process
to handle concurrency
Websocket
server/push
326. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
Bot Verticle would be
another process
BOT BUS
Redis, Tokyo Cabinet, etc. Rabbit MQ or similar
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
Server is EventBus handler,
would be
another process
to handle concurrency
Websocket
server/push
327. ARCHITECTURE IN 1 DYNO
Normal Rails App
RAILS
EVENT
Bot Verticle would be
another process
BOT BUS
Redis, Tokyo Cabinet, etc. Rabbit MQ or similar
SVR
SHARED
DATA
BROWSER
CLIENT
TIMERS
Server is EventBus handler,
would be
another process
to handle concurrency
Websocket
server/push
Expire unanswered challenges
Delayed job
337. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
338. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
339. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
• Jubilee Code - you’ll want to see
340. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
• Jubilee Code - you’ll want to see
• EventBus communication code - the heart of a Jubilee/Vert.x
app
341. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
• Jubilee Code - you’ll want to see
• EventBus communication code - the heart of a Jubilee/Vert.x
app
• Deploying another verticle, Bot, TBI Leaderboard
342. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
• Jubilee Code - you’ll want to see
• EventBus communication code - the heart of a Jubilee/Vert.x
app
• Deploying another verticle, Bot, TBI Leaderboard
• Shared Data
343. CODE
• Rails code - typical stuff you’re already doing - don’t need to see
• Client Game code - similar to what you might do browser side -
don’t need to see
• Jubilee Code - you’ll want to see
• EventBus communication code - the heart of a Jubilee/Vert.x
app
• Deploying another verticle, Bot, TBI Leaderboard
• Shared Data
• Timer
344. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
345. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
346. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
347. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
348. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
349. EVENTBUS SETUP - RAILS
begin!
require 'vertx'!
def to_array(shared_set)!
ret = []!
shared_set.each{ |item| ret << item}!
ret!
end!
!
Vertx::EventBus.register_handler('logout') do |message|!
user_id = message.body!
puts "logging out #{user_id}"!
Vertx::SharedData.get_set(:users).delete(user_id)!
Vertx::EventBus.publish("user_logout", user_id)!
end!
!
# register the user and return the previous users!
Vertx::EventBus.register_handler('login') do |message|!
user_id = message.body!
users = Vertx::SharedData.get_set(:users).add(user_id)!
user_records = User.find(to_array(users)).to_json!
message.reply(users: to_array(users))!
user = User.find user_id!
Vertx::EventBus.publish("new_user", user.to_json)!
end!
end
350. SERVER CONTINUED
begin!
Vertx::EventBus.register_handler('game') do |message|!
server = Server.new(Vertx::EventBus, Vertx)!
cmd_hash = message.body["map"]!
case cmd_hash["cmd"]!
when "new_game"!
server.new_game(cmd_hash["challenge_id"], cmd_hash["challenger_id"], cmd_hash["challenged_id"])!
when "move"!
server.move(cmd_hash["game_id"], cmd_hash["user_id"], cmd_hash["move"])!
when "challenge_accepted"!
server.challenge_accepted(cmd_hash["challenge_id"], cmd_hash["challenger_id"],
cmd_hash["challenged_id"])!
when "give_up_challenge"!
server.give_up_challenge(cmd_hash["challenged_id"], cmd_hash["challenger_id"])!
else!
puts("Unhandled cmd: #{cmd_hash.inspect}")!
end!
end!
Vertx.deploy_verticle("bot.rb")!
rescue LoadError!
puts "Vertx is NOT defined - no loading of vertx initializer"!
end
351. SERVER CONTINUED
begin!
Vertx::EventBus.register_handler('game') do |message|!
server = Server.new(Vertx::EventBus, Vertx)!
cmd_hash = message.body["map"]!
case cmd_hash["cmd"]!
when "new_game"!
server.new_game(cmd_hash["challenge_id"], cmd_hash["challenger_id"], cmd_hash["challenged_id"])!
when "move"!
server.move(cmd_hash["game_id"], cmd_hash["user_id"], cmd_hash["move"])!
when "challenge_accepted"!
server.challenge_accepted(cmd_hash["challenge_id"], cmd_hash["challenger_id"],
cmd_hash["challenged_id"])!
when "give_up_challenge"!
server.give_up_challenge(cmd_hash["challenged_id"], cmd_hash["challenger_id"])!
else!
puts("Unhandled cmd: #{cmd_hash.inspect}")!
end!
end!
Vertx.deploy_verticle("bot.rb")!
rescue LoadError!
puts "Vertx is NOT defined - no loading of vertx initializer"!
end
352. SERVER CONTINUED
begin!
Vertx::EventBus.register_handler('game') do |message|!
server = Server.new(Vertx::EventBus, Vertx)!
cmd_hash = message.body["map"]!
case cmd_hash["cmd"]!
when "new_game"!
server.new_game(cmd_hash["challenge_id"], cmd_hash["challenger_id"], cmd_hash["challenged_id"])!
when "move"!
server.move(cmd_hash["game_id"], cmd_hash["user_id"], cmd_hash["move"])!
when "challenge_accepted"!
server.challenge_accepted(cmd_hash["challenge_id"], cmd_hash["challenger_id"],
cmd_hash["challenged_id"])!
when "give_up_challenge"!
server.give_up_challenge(cmd_hash["challenged_id"], cmd_hash["challenger_id"])!
else!
puts("Unhandled cmd: #{cmd_hash.inspect}")!
end!
end!
Vertx.deploy_verticle("bot.rb")!
rescue LoadError!
puts "Vertx is NOT defined - no loading of vertx initializer"!
end
357. CLIENT CONTINUED
@event_bus.register_handler(@uid) do |data|!
cmd_hash = Native(data)!
case cmd_hash["cmd"]!
when "challenge"!
show_challenge(cmd_hash)!
when "new_game"!
new_game(cmd_hash["challenger_id"], cmd_hash["challenged_id"], cmd_hash["game_id"])!
when "move"!
process_move(cmd_hash)!
when "give_up_challenge"!
give_up_challenge(cmd_hash)!
when "challenge_aborted"!
challenger_name = @player_info[cmd_hash["challenged_id"]][:name]!
hide_overlay!
swal("You missed a challenge from #{challenger_name}")!
when "user_details"!
json = @player_info[@uid].merge({id: @uid}).to_json!
puts "Sending user_details #{json}"!
replier.call(json)!
when "not_available"!
hide_overlay!
swal "#{@player_info[@desired_challenged_id][:name]} is not available to play"!
else!
puts "can't handle "!
end!
end!
end # split in half
358. def cont!
@event_bus.register_handler(:activity) do |data|!
append_activity(data)!
end!
@event_bus.register_handler(:player_state) do |data|!
`console.log(data); `!
state_hash = Native(data)!
set_player_states(state_hash)!
end!
@event_bus.register_handler(:user_logout) do |data|!
user_id = data!
puts "logging out #{user_id}"!
append_activity("#{@player_info[user_id]['name']} left")!
Element.find("##{user_id}").hide!
end!
}!
end!
359. BOT CODE
@handler = Vertx::EventBus.register_handler(BOT_ID) do |message|!
cmd_hash = message.body!
puts "nBOT handling #{cmd_hash['cmd']}"!
case cmd_hash["cmd"]!
when "challenge"!
Vertx::EventBus.send("game",!
{ cmd: "challenge_accepted",!
challenge_id: cmd_hash["challenge_id"],!
challenger_id: cmd_hash["challenger_id"],!
challenged_id: BOT_ID!
}!
)!
when "move"!
process_move(cmd_hash)!
when "give_up_challenge", "challenge_aborted", "not_available", "challenge_accepted"!
# NO OP!
else!
puts "nBOT can't handle #{cmd_hash.inspect}"!
p cmd_hash!
end!
!
end!
!
def vertx_stop!
puts "Must exterminate self!"!
Vertx::EventBus.unregister_handler( BOT_ID, @handler)!
end
360. BOT CODE
@handler = Vertx::EventBus.register_handler(BOT_ID) do |message|!
cmd_hash = message.body!
puts "nBOT handling #{cmd_hash['cmd']}"!
case cmd_hash["cmd"]!
when "challenge"!
Vertx::EventBus.send("game",!
{ cmd: "challenge_accepted",!
challenge_id: cmd_hash["challenge_id"],!
challenger_id: cmd_hash["challenger_id"],!
challenged_id: BOT_ID!
}!
)!
when "move"!
process_move(cmd_hash)!
when "give_up_challenge", "challenge_aborted", "not_available", "challenge_accepted"!
# NO OP!
else!
puts "nBOT can't handle #{cmd_hash.inspect}"!
p cmd_hash!
end!
!
end!
!
def vertx_stop!
puts "Must exterminate self!"!
Vertx::EventBus.unregister_handler( BOT_ID, @handler)!
end
361. BOT CODE
@handler = Vertx::EventBus.register_handler(BOT_ID) do |message|!
cmd_hash = message.body!
puts "nBOT handling #{cmd_hash['cmd']}"!
case cmd_hash["cmd"]!
when "challenge"!
Vertx::EventBus.send("game",!
{ cmd: "challenge_accepted",!
challenge_id: cmd_hash["challenge_id"],!
challenger_id: cmd_hash["challenger_id"],!
challenged_id: BOT_ID!
}!
)!
when "move"!
process_move(cmd_hash)!
when "give_up_challenge", "challenge_aborted", "not_available", "challenge_accepted"!
# NO OP!
else!
puts "nBOT can't handle #{cmd_hash.inspect}"!
p cmd_hash!
end!
!
end!
!
def vertx_stop!
puts "Must exterminate self!"!
Vertx::EventBus.unregister_handler( BOT_ID, @handler)!
end
362. BOT CODE
@handler = Vertx::EventBus.register_handler(BOT_ID) do |message|!
cmd_hash = message.body!
puts "nBOT handling #{cmd_hash['cmd']}"!
case cmd_hash["cmd"]!
when "challenge"!
Vertx::EventBus.send("game",!
{ cmd: "challenge_accepted",!
challenge_id: cmd_hash["challenge_id"],!
challenger_id: cmd_hash["challenger_id"],!
challenged_id: BOT_ID!
}!
)!
when "move"!
process_move(cmd_hash)!
when "give_up_challenge", "challenge_aborted", "not_available", "challenge_accepted"!
# NO OP!
else!
puts "nBOT can't handle #{cmd_hash.inspect}"!
p cmd_hash!
end!
!
end!
!
def vertx_stop!
puts "Must exterminate self!"!
Vertx::EventBus.unregister_handler( BOT_ID, @handler)!
end
363. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
364. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
365. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
366. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
367. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
368. SERVER TIMER CODE
# timer when challenged!
timer_id = @container.set_timer(10000) do |timer_id|!
check_accepted?(challenge_id, challenger_id, challenged_id)!
end!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_map[challenge_id] = timer_id!
!
# clear the timer if user aborts his challenge!
timer_map = Vertx::SharedData.get_hash(:timers)!
timer_id = timer_map[challenge_id]!
if timer_id!
Vertx.cancel_timer timer_id!
timer_map.delete challenge_id!
end
371. JUBILEE CONSIDERATIONS IN RAILS
• Setup server side EventBus in Rails initializer
• Done in initializer so it is done for whole Rails app
372. JUBILEE CONSIDERATIONS IN RAILS
• Setup server side EventBus in Rails initializer
• Done in initializer so it is done for whole Rails app
• Wrap vertx initialization in begin rescue so Rake tasks
(not running vert.x server) will run
374. DRAWBACKS
• JRuby still 2nd class citizen, sometime have gem trouble or
hard to get the config right
375. DRAWBACKS
• JRuby still 2nd class citizen, sometime have gem trouble or
hard to get the config right
• Debugging asynchronous multi agent systems still hard
regardless
376. DRAWBACKS
• JRuby still 2nd class citizen, sometime have gem trouble or
hard to get the config right
• Debugging asynchronous multi agent systems still hard
regardless
• Fine control will require vertx style deploy instead of Rails
friendly jubilee
377. DRAWBACKS
• JRuby still 2nd class citizen, sometime have gem trouble or
hard to get the config right
• Debugging asynchronous multi agent systems still hard
regardless
• Fine control will require vertx style deploy instead of Rails
friendly jubilee
• Error messages can get swallowed inside of Event Handlers
378. DRAWBACKS
• JRuby still 2nd class citizen, sometime have gem trouble or
hard to get the config right
• Debugging asynchronous multi agent systems still hard
regardless
• Fine control will require vertx style deploy instead of Rails
friendly jubilee
• Error messages can get swallowed inside of Event Handlers
• Haven’t found the right place so that Jubilee/Vertx code
auto reloads on Rails completely consistently
380. ONE MORE THING
• Opal (Ruby in the browser) front end == All Ruby Stack
381. ONE MORE THING
• Opal (Ruby in the browser) front end == All Ruby Stack
• The same language on front end/back end advantage
that Node touts is nice!
382. ONE MORE THING
• Opal (Ruby in the browser) front end == All Ruby Stack
• The same language on front end/back end advantage
that Node touts is nice!
• This could be it’s own talk
383. ONE MORE THING
• Opal (Ruby in the browser) front end == All Ruby Stack
• The same language on front end/back end advantage
that Node touts is nice!
• This could be it’s own talk
• I already did that (RubyConf 2013 https://vimeo.com/
82573680 ) So I won’t do it here
386. THANKS
• Matz - Ruby
• DHH - Rails and jobs
• Charles Nutter, Tom Enebo - JRuby
• Tim Fox & Vert.x team - Vert.x
• Isaiah Peng - Jubilee
• Adam Beynon, Elia Schito, Meh’ - Opal
• You for listening
388. ADVICE TO RUBYISTS
• Stay happy, you can still do most of your stuff in Ruby
via Jubilee
389. ADVICE TO RUBYISTS
• Stay happy, you can still do most of your stuff in Ruby
via Jubilee
• Stay happy, you can grow/scale in Ruby via Jubilee
390. ADVICE TO RUBYISTS
• Stay happy, you can still do most of your stuff in Ruby
via Jubilee
• Stay happy, you can grow/scale in Ruby via Jubilee
• Don’t worry, Be Happy