SlideShare une entreprise Scribd logo
1  sur  394
Télécharger pour lire hors ligne
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
APOLOGIES 
http://images.sodahead.com/blogs/000302881/sorry20really20truly20very20apology_xlarge.jpeg 
.
ALTERNATE TITLES 
AFTER SEEING 
ERNIE MILLER’S 
RUBY AFTER RAILS
! 
R A I L S W H I L E S T I L L 
USING RAILS
OR
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
PRELUDE
QUESTION 
http://wp.production.patheos.com/blogs/faithwalkers/files/2013/09/god-question.jpg
WHY ARE YOU HERE AT 
RUBYCONF?
AN ANSWER
YOU LIKE RUBY
WHY DO YOU LIKE 
RUBY?
BECAUSE IT MAKES YOU 
HAPPY
“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
“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
HAPPINESS IS 
THE RUBY WAY
OBJECTIVE
OBJECTIVE 
• To ensure you, the Rubyist, stays happy
HAPPINESS IS A RECURRING THEME 
• J 
• D 
• D 
IN MY TALKS, AS WELL AS HERE AT RUBYCONF
HAPPINESS IS A RECURRING THEME 
• J 
Joy 
• D 
• D 
IN MY TALKS, AS WELL AS HERE AT RUBYCONF
HAPPINESS IS A RECURRING THEME 
• J 
Joy 
Driven 
• D 
• D 
IN MY TALKS, AS WELL AS HERE AT RUBYCONF
HAPPINESS IS A RECURRING THEME 
• J 
Joy 
Driven 
Development 
• D 
• D 
IN MY TALKS, AS WELL AS HERE AT RUBYCONF
CODING AND LOVING IT
WHAT DO WE LIKE 
ABOUT RUBY?
1) LANGUAGE ITSELF IS DELIGHTFUL
1) LANGUAGE ITSELF IS DELIGHTFUL 
• An entire talk can be done on this
1) LANGUAGE ITSELF IS DELIGHTFUL 
• An entire talk can be done on this 
• So I won't do one
SINGLE EXAMPLE FROM DEVISE 
CONFIG 
# ==> Configuration for :validatable! 
# Range for password length. Default is 8..128.! 
config.password_length = 8..128
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
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
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)
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
RUBY MAKES ME HAPPY
RUBY MAKES ME HAPPY
2) GEMS AND FRAMEWORKS
2) GEMS AND FRAMEWORKS 
• Many gems, nearly anything you'd want ready to go
2) GEMS AND FRAMEWORKS 
• Many gems, nearly anything you'd want ready to go 
• Choice, often more than 1 gem for the job
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
800lb Gorilla of Rubygems 
http://www.examiner.com/images/blog/wysiwyg/image/4056_Landing_gorilla-1.jpg
RAILS
RAILS 
• Who codes in Rails?
RAILS 
• Who codes in Rails? 
• Who came to Ruby from Rails?
RAILS 
• Who codes in Rails? 
• Who came to Ruby from Rails? 
• Who was coding Ruby before Rails?
RAILS 
• Who codes in Rails? 
• Who came to Ruby from Rails? 
• Who was coding Ruby before Rails? 
• Who loves Rails?
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?
WHY WE LOVE RAILS
WHY WE LOVE RAILS 
• A whole talk can be done this
WHY WE LOVE RAILS 
• A whole talk can be done this 
• So I won't do one
WHY WE LOVE RAILS 
• A whole talk can be done this 
• So I won't do one 
• Productivity
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
RAILS CAN MAKES YOU HAPPY
RAILS CAN MAKES YOU HAPPY
RUBY IS NOT A 
PANACEA
SOME REASONS TO NOT USE RUBY
SOME REASONS TO NOT USE RUBY 
• Speed
SOME REASONS TO NOT USE RUBY 
• Speed 
• Image processing, video encoding
SOME REASONS TO NOT USE RUBY 
• Speed 
• Image processing, video encoding 
• Scaling
SOME REASONS TO NOT USE RUBY 
• Speed 
• Image processing, video encoding 
• Scaling 
• Resource heavy
SOME REASONS TO NOT USE RUBY 
• Speed 
• Image processing, video encoding 
• Scaling 
• Resource heavy 
• Computation heavy
SOME REASONS TO NOT USE RUBY 
• Speed 
• Image processing, video encoding 
• Scaling 
• Resource heavy 
• Computation heavy 
• More/better Library functionality elsewhere
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.
ALL LEGIT REASONS
PROBLEM
PROBLEM 
Some non Ruby technologies can be “Less Happy Making”
A COMMON ALTERNATIVE
NODE, WHAT IT IS GOOD FOR?
NODE, WHAT IT IS GOOD FOR?
NODE, WHAT IT IS GOOD FOR? 
• Quick, Non blocking I/O
NODE, WHAT IT IS GOOD FOR? 
• Quick, Non blocking I/O 
• Concurrency
NODE, WHAT IT IS GOOD FOR? 
• Quick, Non blocking I/O 
• Concurrency 
• Chat app demonstrates Node’s sweet spot
NODE, WHAT IT IS GOOD FOR? 
• Quick, Non blocking I/O 
• Concurrency 
• Chat app demonstrates Node’s sweet spot 
• high concurrency
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
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
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"
WHAT IT NODE BAD AT?
WHAT IT NODE BAD AT? 
• Vertical scaling
WHAT IT NODE BAD AT? 
• Vertical scaling 
• CPU intensive
WHAT IT NODE BAD AT? 
• Vertical scaling 
• CPU intensive 
• Integration with other systems
WHAT IT NODE BAD AT? 
• Vertical scaling 
• CPU intensive 
• Integration with other systems 
• Decent language (Ruby bias)
TOO MUCH JAVASCRIPT 
AND
SO, HOW DO WE
BRING BACK THAT LOVING 
FEELING?
BRING BACK THAT LOVING 
FEELING?
• Who's heard of it?
• Who's heard of it? 
• Oversimplified - Node for the JVM
• Who's heard of it? 
• Oversimplified - Node for the JVM 
• BUT much more - more like Node++ and then some
DESIGNED FOR MODERN APPLICATIONS
DESIGNED FOR MODERN APPLICATIONS
DESIGNED FOR MODERN APPLICATIONS 
Ruby/ 
JRuby
DESIGNED FOR MODERN APPLICATIONS 
Ruby/ 
JRuby
DESIGNED FOR MODERN APPLICATIONS 
Ruby/ 
JRuby
DESIGNED FOR MODERN APPLICATIONS 
Ruby/ 
JRuby
SOME KEY FEATURES
SOME KEY FEATURES
SOME KEY FEATURES
SOME KEY FEATURES
SOME KEY FEATURES
LIKE NODE
LIKE NODE 
• Concurrency - Implements the same Reactor Pattern
LIKE NODE 
• Concurrency - Implements the same Reactor Pattern 
• Non blocking i/o
LIKE NODE 
• Concurrency - Implements the same Reactor Pattern 
• Non blocking i/o 
• Fast
BETTER THAN NODE
BETTER THAN NODE 
• Handles CPU intensive
BETTER THAN NODE 
• Handles CPU intensive 
• JVM fast (JRuby fastes of the Rubies)
BETTER THAN NODE 
• Handles CPU intensive 
• JVM fast (JRuby fastes of the Rubies) 
• JVM thread friendly
BETTER THAN NODE 
• Handles CPU intensive 
• JVM fast (JRuby fastes of the Rubies) 
• JVM thread friendly 
• Handles Blocking IO or Long running operations
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
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
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
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
BETTER THAN NODE, PART 2
BETTER THAN NODE, PART 2 
• Polyglot
BETTER THAN NODE, PART 2 
• Polyglot 
• Official idiomatic API support: Java, Javascript, Groovy, 
Coffeescript, *Ruby (by way of JRuby)*, Python
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?)
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
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
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”
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
BETTER THAN NODE, PART 3
BETTER THAN NODE, PART 3 
• Designed to build systems of systems
BETTER THAN NODE, PART 3 
• Designed to build systems of systems 
• Easy High Availability
BETTER THAN NODE, PART 3 
• Designed to build systems of systems 
• Easy High Availability 
• Easy Clustering
BETTER THAN NODE, PART 3 
• Designed to build systems of systems 
• Easy High Availability 
• Easy Clustering 
• Easy subsystem Intercommunication
BETTER THAN NODE, PART 3 
• Designed to build systems of systems 
• Easy High Availability 
• Easy Clustering 
• Easy subsystem Intercommunication 
• Event Bus
BETTER THAN NODE, PART 3 
• Designed to build systems of systems 
• Easy High Availability 
• Easy Clustering 
• Easy subsystem Intercommunication 
• Event Bus 
• Shared Data
CORE APIS- WHAT YOU NEED
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets 
• SockJS
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets 
• SockJS 
• File system
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets 
• SockJS 
• File system 
• Event bus
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets 
• SockJS 
• File system 
• Event bus 
• DNS
CORE APIS- WHAT YOU NEED 
• TCP/SSL clients and servers 
• HTTP/HTTPS clients and servers 
• Websockets 
• SockJS 
• File system 
• Event bus 
• DNS 
• UDP
DUCT TAPE
DUCT TAPE 
• Open SourceSystems are duct taped together
DUCT TAPE 
• Open SourceSystems are duct taped together 
• We figure out how to do to put together things
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…
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
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
VERT.X DESIGNED FOR 
INTEGRATED SYSTEMS
DIFFERENT TYPES OF PROCESSES
DIFFERENT TYPES OF PROCESSES 
• Asynchronous - Verticle
DIFFERENT TYPES OF PROCESSES 
• Asynchronous - Verticle 
• Blocking/CPU intensive - worker verticle
INTER PROCESS/SYSTEM 
COMMUNICATION
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message 
• direct message reply
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message 
• direct message reply 
• extends into the browser
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message 
• direct message reply 
• extends into the browser 
• Shared Data
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message 
• direct message reply 
• extends into the browser 
• Shared Data 
• Hash
INTER PROCESS/SYSTEM 
COMMUNICATION 
• Event Bus 
• publish 
• direct message 
• direct message reply 
• extends into the browser 
• Shared Data 
• Hash 
• Set
SCALING BUILT I N
SCALING BUILT I N 
• Clustering
SCALING BUILT I N 
• Clustering 
• vertx process.rb —cluster
SCALING BUILT I N 
• Clustering 
• vertx process.rb —cluster 
• High Availability
SCALING BUILT I N 
• Clustering 
• vertx process.rb —cluster 
• High Availability 
• vertx process.rb —ha
AND MUCH MORE
AND MUCH MORE 
• A whole talk could be done on it
AND MUCH MORE 
• A whole talk could be done on it 
• So I won’t do one
AND MUCH MORE 
• A whole talk could be done on it 
• So I won’t do one 
• 2 Good overview videos
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
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
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
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
VERT. X I S P R E T T Y AWESOME
VERT. X I S P R E T T Y AWESOME
BUT IT’S MORE STUFF TO 
LEARN
WHAT IF I TOLD YOU YOU COULD?
ORIGINAL JUBILEE README SLOGAN
ORIGINAL JUBILEE README SLOGAN 
"We need a web framework for Vertx.", you said.
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."
JUBILEE
JUBILEE 
• Originally Rack server w/ vert.x 2.0 built in
JUBILEE 
• Originally Rack server w/ vert.x 2.0 built in 
• Now a Vert.x module that runs Rack
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
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
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!
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND 
• Concurrency
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND 
• Concurrency 
• Speed
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND 
• Concurrency 
• Speed 
• Expanded Ecosystem
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND 
• Concurrency 
• Speed 
• Expanded Ecosystem 
• Built in upgrade/scaling path
6 REASONS VERT.X COULD BE YOUR 
NEW BEST FRIEND 
• Concurrency 
• Speed 
• Expanded Ecosystem 
• Built in upgrade/scaling path 
• Easy web sockets support
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
1) CONCURRENCY
1) CONCURRENCY 
• Same Reactor pattern as Node
1) CONCURRENCY 
• Same Reactor pattern as Node 
• Each Verticle single threaded
1) CONCURRENCY 
• Same Reactor pattern as Node 
• Each Verticle single threaded 
• Simple concurrency model, no threading
1) CONCURRENCY 
• Same Reactor pattern as Node 
• Each Verticle single threaded 
• Simple concurrency model, no threading 
• Multiple verticles, can do 1 per CPU
2) SPEED
2) SPEED 
• JVM faster and getting faster all the time
2) SPEED 
• JVM faster and getting faster all the time 
• Can use threads, cpus
2) SPEED 
• JVM faster and getting faster all the time 
• Can use threads, cpus 
• Benchmarks
LIES, DAMN LIES, AND BENCHMARKS
LIES, DAMN LIES, AND BENCHMARKS 
• http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/
LIES, DAMN LIES, AND BENCHMARKS 
• http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ 
Ruby
LIES, DAMN LIES, AND BENCHMARKS 
• http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ 
Ruby 
Node
LIES, DAMN LIES, AND BENCHMARKS 
• http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ 
Ruby 
Node 6 
processes 
Node
Ruby
Ruby 
Best Node
JUBILEE - 2ND FASTEST RUBY SERVER
JUBILEE - 2ND FASTEST RUBY SERVER 
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark- 
report.html
JUBILEE - 2ND FASTEST RUBY SERVER 
• http://www.madebymarket.com/blog/dev/ruby-web-benchmark- 
report.html 
• Maximum speed benchmarks vs typical
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
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
Golang hello world was 10,500 reqs/sec
3 ) E X PANDED ECOSYSTEM
3 ) E X PANDED ECOSYSTEM 
• Rubygems
3 ) E X PANDED ECOSYSTEM 
• Rubygems 
• Must run under JRuby
3 ) E X PANDED ECOSYSTEM 
• Rubygems 
• Must run under JRuby 
• Vertx modules (200 at time of writing)
3 ) E X PANDED ECOSYSTEM 
• Rubygems 
• Must run under JRuby 
• Vertx modules (200 at time of writing) 
• Entire JVM ecosystem, languages, libraries
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
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
4 ) BUILT IN UPGRADE/SCALING PATH
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async)
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow)
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow) 
• Inter communication
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow) 
• Inter communication 
• Core APIs
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow) 
• Inter communication 
• Core APIs 
• Event Bus
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow) 
• Inter communication 
• Core APIs 
• Event Bus 
• Shared Data
4 ) BUILT IN UPGRADE/SCALING PATH 
• Designed for multiple verticles (async) 
• Worker verticles (slow) 
• Inter communication 
• Core APIs 
• Event Bus 
• Shared Data 
• Clustering
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
5) EASY WEBSOCKETS SUPPORT
5) EASY WEBSOCKETS SUPPORT 
• SocketIO support
5) EASY WEBSOCKETS SUPPORT 
• SocketIO support 
• SockJS support
5) EASY WEBSOCKETS SUPPORT 
• SocketIO support 
• SockJS support 
• ** Event Bus **
5) EASY WEBSOCKETS SUPPORT 
• SocketIO support 
• SockJS support 
• ** Event Bus ** 
• Easy
5) EASY WEBSOCKETS SUPPORT 
• SocketIO support 
• SockJS support 
• ** Event Bus ** 
• Easy 
• Extends into the browser
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES 
• Ruby
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES 
• Ruby 
• Rack programming
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES 
• Ruby 
• Rack programming 
• i.e. Rails, Sinatra, etc.
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES 
• Ruby 
• Rack programming 
• i.e. Rails, Sinatra, etc. 
• Gems
6 ) REUSE ALL YOUR EXISTING KNOWLEDGE/ 
RESOURCES 
• Ruby 
• Rack programming 
• i.e. Rails, Sinatra, etc. 
• Gems 
• Low barrier to entry for the Rubyist!
JUBILEE CAN MAKE YOU HAPPY
JUBILEE CAN MAKE YOU HAPPY
INSTALLATION 
$ gem install jubilee!
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 !
WHAT ABOUT HEROKU?
WHAT ABOUT HEROKU? 
• http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html
WHAT ABOUT HEROKU? 
• http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html 
Gemfile 
ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! 
gem 'jubilee', :platforms => [:jruby]! 
gem 'rails_12factor'
WHAT ABOUT HEROKU? 
• http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html 
Gemfile 
ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! 
gem 'jubilee', :platforms => [:jruby]! 
gem 'rails_12factor' 
Procfile 
web: jubilee --eventbus /eventbus -n 1 —e $RACK_ENV -p $PORT !
WHAT ABOUT HEROKU? 
• http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html 
Gemfile 
ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! 
gem 'jubilee', :platforms => [:jruby]! 
gem 'rails_12factor' 
Procfile 
web: jubilee --eventbus /eventbus -n 1 —e $RACK_ENV -p $PORT ! 
Set JRuby/JVM Opts 
heroku config:add JRUBY_OPTS="-J-Xmn128m -J-Xms768m -J-Xmx768m"!
GETTING THE MESSAGE ACROSS
GETTING THE MESSAGE ACROSS 
• Everyone has slides
GETTING THE MESSAGE ACROSS 
• Everyone has slides 
• Many have demos
GETTING THE MESSAGE ACROSS 
• Everyone has slides 
• Many have demos 
• I want 1st hand interaction -
AN EXPERIENCE
AN EXPERIENCE
NODE’S SWEET SPOT
NODE’S SWEET SPOT 
• Chat - The sample app that everyone makes
NODE’S SWEET SPOT 
• Chat - The sample app that everyone makes 
• How do I make a chat app a little more interesting?
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
MMO WHAT?
MMO WHAT? 
• Rock, Paper, Scissors
MMO WHAT? 
• Rock, Paper, Scissors 
• Really!
MMO WHAT? 
• Rock, Paper, Scissors 
• Really! 
• 4 kids, demanding job - World of Warcraft is out
EXPERIENCING JUBILEE IN ACTION
EXPERIENCING JUBILEE IN ACTION 
• Everyone in the room sign on
EXPERIENCING JUBILEE IN ACTION 
• Everyone in the room sign on 
• Play each other
EXPERIENCING JUBILEE IN ACTION 
• Everyone in the room sign on 
• Play each other 
• Have fun!
EXPERIENCING JUBILEE IN ACTION 
• Everyone in the room sign on 
• Play each other 
• Have fun! 
• Then we talk
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
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
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?)
ROCK 
R 
P 
PAPER 
S 
SCISSORS 
MAYHEM 
M
R 
P 
S 
M
! 
P 
HTTP://BIT. LY/RPSMAYHEM 
! 
! 
! 
! 
M 
! 
! 
R S
WHAT TO DO
WHAT TO DO 
• Go to http://bit.ly/rpsmayhem
WHAT TO DO 
• Go to http://bit.ly/rpsmayhem 
• Login with twitter
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)
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)
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
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
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
PLAY I T !
APP BREAKDOWN
RIGHT TOOL FOR THE JOB
RIGHT TOOL FOR THE JOB 
• Rails
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x 
• Event Bus - websockets, concurrency, subsystem communciation
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x 
• Event Bus - websockets, concurrency, subsystem communciation 
• Shared Data - quick shared memory
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x 
• Event Bus - websockets, concurrency, subsystem communciation 
• Shared Data - quick shared memory 
• Vertx::Timer - enforce challenge acceptance timeout
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x 
• Event Bus - websockets, concurrency, subsystem communciation 
• Shared Data - quick shared memory 
• Vertx::Timer - enforce challenge acceptance timeout 
• Additional Verticle - Bot
RIGHT TOOL FOR THE JOB 
• Rails 
• Login - omniauth, devise 
• Views - haml 
• DB - ActiveRecord, migrations 
• Jubilee/Vert.x 
• Event Bus - websockets, concurrency, subsystem communciation 
• Shared Data - quick shared memory 
• Vertx::Timer - enforce challenge acceptance timeout 
• Additional Verticle - Bot 
• Worker Verticle - TBI Leaderboard
APP SUMMARY
APP SUMMARY 
• Rails to get to the game
APP SUMMARY 
• Rails to get to the game 
• Jubilee/Vert.x to play the game
SCREEN BY SCREEN
MAIN PAGE
MAIN PAGE 
Main page is vanilla Rails 
Sign in
SIGN IN WITH TWITTER
SIGN IN WITH TWITTER 
Omniauth gem makes it easy
CHAT LIKE FEATURES OF THE GAME
CHAT LIKE FEATURES OF THE GAME 
You
CHAT LIKE FEATURES OF THE GAME 
You 
Live Activity Stream
CHAT LIKE FEATURES OF THE GAME 
You 
Live Activity Stream 
Live presence 
and state
CHALLENGE AN OPPONENT 
You can give up
CHALLENGE TIME OUT 
Jubilee/Vert.x Timer 
checks and cancels the 
challenge
REALTIME CHALLENGE
REALTIME CHALLENGE 
Connected to server and 
each other by EventBus
CHALLENGE TIME OUT
CHALLENGE TIME OUT 
Jubilee/Vert.x Timer 
checks and cancels the 
challenge
REALTIME MMO GAMEPLAY
REALTIME MMO GAMEPLAY 
Connected to server and 
each other by EventBus, 
uses SharedData for speed
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
ARCHITECTURE IN 1 DYNO 
RAILS 
EVENT 
BOT BUS 
SVR 
SHARED 
DATA 
BROWSER 
CLIENT 
TIMERS
ARCHITECTURE IN 1 DYNO 
Normal Rails App 
RAILS 
EVENT 
BOT BUS 
SVR 
SHARED 
DATA 
BROWSER 
CLIENT 
TIMERS
ARCHITECTURE IN 1 DYNO 
Normal Rails App 
RAILS 
EVENT 
BOT BUS 
SVR 
SHARED 
DATA 
BROWSER 
CLIENT 
Rabbit MQ or similar 
TIMERS
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
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
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
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
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
DESIGNED TO WORK 
TOGETHER
AS OPPOSED TO DUCT 
TAPED TOGETHER
DUCT TAPE
APP CODE STATS
APP CODE STATS 
• Client code 497 LOC Opal (including whitespace and 
debug)
APP CODE STATS 
• Client code 497 LOC Opal (including whitespace and 
debug) 
• game.js.rb 444
APP CODE STATS 
• Client code 497 LOC Opal (including whitespace and 
debug) 
• game.js.rb 444 
• event_bus.rb 52
APP CODE STATS 
• Client code 497 LOC Opal (including whitespace and 
debug) 
• game.js.rb 444 
• event_bus.rb 52 
• Server code: vertx initializer 50 LOC including 
whitespace and comments
CODE
CODE 
• Rails code - typical stuff you’re already doing - don’t need to see
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
CLIENT SIDE EVENTBUS SETUP (OPAL) 
def setup_eventbus! 
@event_bus = EventBus.new! 
@event_bus.onopen {! 
@event_bus.send_msg(:login, @uid)! 
@event_bus.register_handler(:new_user) do |data|! 
json = JSON.parse(data)! 
@player_info[json[:id]] = { name: json[:name], image: json[:image]}! 
render_potential_victim(json) unless json[:id].to_i == @uid.to_i! 
append_activity("#{json['name']} joined")! 
end
CLIENT SIDE EVENTBUS SETUP (OPAL) 
def setup_eventbus! 
@event_bus = EventBus.new! 
@event_bus.onopen {! 
@event_bus.send_msg(:login, @uid)! 
@event_bus.register_handler(:new_user) do |data|! 
json = JSON.parse(data)! 
@player_info[json[:id]] = { name: json[:name], image: json[:image]}! 
render_potential_victim(json) unless json[:id].to_i == @uid.to_i! 
append_activity("#{json['name']} joined")! 
end
CLIENT SIDE EVENTBUS SETUP (OPAL) 
def setup_eventbus! 
@event_bus = EventBus.new! 
@event_bus.onopen {! 
@event_bus.send_msg(:login, @uid)! 
@event_bus.register_handler(:new_user) do |data|! 
json = JSON.parse(data)! 
@player_info[json[:id]] = { name: json[:name], image: json[:image]}! 
render_potential_victim(json) unless json[:id].to_i == @uid.to_i! 
append_activity("#{json['name']} joined")! 
end
CLIENT SIDE EVENTBUS SETUP (OPAL) 
def setup_eventbus! 
@event_bus = EventBus.new! 
@event_bus.onopen {! 
@event_bus.send_msg(:login, @uid)! 
@event_bus.register_handler(:new_user) do |data|! 
json = JSON.parse(data)! 
@player_info[json[:id]] = { name: json[:name], image: json[:image]}! 
render_potential_victim(json) unless json[:id].to_i == @uid.to_i! 
append_activity("#{json['name']} joined")! 
end
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
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!
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
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
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
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
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
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
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
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
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
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
JUBILEE CONSIDERATIONS IN RAILS
JUBILEE CONSIDERATIONS IN RAILS 
• Setup server side EventBus in Rails initializer
JUBILEE CONSIDERATIONS IN RAILS 
• Setup server side EventBus in Rails initializer 
• Done in initializer so it is done for whole Rails app
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
DRAWBACKS
DRAWBACKS 
• JRuby still 2nd class citizen, sometime have gem trouble or 
hard to get the config right
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
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
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
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
ONE MORE THING
ONE MORE THING 
• Opal (Ruby in the browser) front end == All Ruby Stack
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!
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
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
RUBY IN THE BROWSER MAKES ME 
HAPPY
RUBY IN THE BROWSER MAKES ME 
HAPPY
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
ADVICE TO RUBYISTS
ADVICE TO RUBYISTS 
• Stay happy, you can still do most of your stuff in Ruby 
via Jubilee
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
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
6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend
6 reasons Jubilee could be a Rubyist's new best friend

Contenu connexe

Tendances

Choosing Javascript Libraries to Adopt for Development
Choosing Javascript Libraries to Adopt for DevelopmentChoosing Javascript Libraries to Adopt for Development
Choosing Javascript Libraries to Adopt for DevelopmentEdward Apostol
 
Untangling spring week3
Untangling spring week3Untangling spring week3
Untangling spring week3Derek Jacoby
 
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will come
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will comeHigher Ed Web 2013 presentation - Field of Dreams, build it and they will come
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will comePromet Source
 
Surviving in a Microservices environment -abridged
Surviving in a Microservices environment -abridgedSurviving in a Microservices environment -abridged
Surviving in a Microservices environment -abridgedSteve Pember
 
Front End page speed performance improvements for Drupal
Front End page speed performance improvements for DrupalFront End page speed performance improvements for Drupal
Front End page speed performance improvements for DrupalAndy Kucharski
 
Untangling the web week 2 - SEO
Untangling the web week 2 - SEOUntangling the web week 2 - SEO
Untangling the web week 2 - SEODerek Jacoby
 
Untangling the web week1
Untangling the web week1Untangling the web week1
Untangling the web week1Derek Jacoby
 
TDD - for people who don't need it
TDD - for people who don't need itTDD - for people who don't need it
TDD - for people who don't need itChoon Keat Chew
 
All about Front End - Girl Code @ ANWB
All about Front End - Girl Code @ ANWBAll about Front End - Girl Code @ ANWB
All about Front End - Girl Code @ ANWBIneke Scheffers
 
Is having no limits a limitation [distilled version]
Is having no limits a limitation [distilled version]Is having no limits a limitation [distilled version]
Is having no limits a limitation [distilled version]Ben Brignell
 
LeanStartup:Research is cheaper than development
LeanStartup:Research is cheaper than developmentLeanStartup:Research is cheaper than development
LeanStartup:Research is cheaper than developmentJohn McCaffrey
 
Surviving in a microservices environment
Surviving in a microservices environmentSurviving in a microservices environment
Surviving in a microservices environmentSteve Pember
 
TDC2016SP - Otimização Prematura: a Raíz de Todo o Mal
TDC2016SP - Otimização Prematura: a Raíz de Todo o MalTDC2016SP - Otimização Prematura: a Raíz de Todo o Mal
TDC2016SP - Otimização Prematura: a Raíz de Todo o Maltdc-globalcode
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykRuby Meditation
 
Totally Build Apps for Free! (not really)
Totally Build Apps for Free! (not really)Totally Build Apps for Free! (not really)
Totally Build Apps for Free! (not really)Tony Hillerson
 
AJAX & jQuery - City University WAD Module
AJAX & jQuery - City University WAD ModuleAJAX & jQuery - City University WAD Module
AJAX & jQuery - City University WAD ModuleCharlie Perrins
 
Don't fear our new robot overlords – A new way to test on mobile
Don't fear our new robot overlords – A new way to test on mobileDon't fear our new robot overlords – A new way to test on mobile
Don't fear our new robot overlords – A new way to test on mobilePhilip Brechler
 

Tendances (20)

Choosing Javascript Libraries to Adopt for Development
Choosing Javascript Libraries to Adopt for DevelopmentChoosing Javascript Libraries to Adopt for Development
Choosing Javascript Libraries to Adopt for Development
 
Untangling spring week3
Untangling spring week3Untangling spring week3
Untangling spring week3
 
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will come
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will comeHigher Ed Web 2013 presentation - Field of Dreams, build it and they will come
Higher Ed Web 2013 presentation - Field of Dreams, build it and they will come
 
Surviving in a Microservices environment -abridged
Surviving in a Microservices environment -abridgedSurviving in a Microservices environment -abridged
Surviving in a Microservices environment -abridged
 
Front End page speed performance improvements for Drupal
Front End page speed performance improvements for DrupalFront End page speed performance improvements for Drupal
Front End page speed performance improvements for Drupal
 
Untangling the web week 2 - SEO
Untangling the web week 2 - SEOUntangling the web week 2 - SEO
Untangling the web week 2 - SEO
 
File Upload 2015
File Upload 2015File Upload 2015
File Upload 2015
 
Untangling the web week1
Untangling the web week1Untangling the web week1
Untangling the web week1
 
TDD - for people who don't need it
TDD - for people who don't need itTDD - for people who don't need it
TDD - for people who don't need it
 
All about Front End - Girl Code @ ANWB
All about Front End - Girl Code @ ANWBAll about Front End - Girl Code @ ANWB
All about Front End - Girl Code @ ANWB
 
Is having no limits a limitation [distilled version]
Is having no limits a limitation [distilled version]Is having no limits a limitation [distilled version]
Is having no limits a limitation [distilled version]
 
LeanStartup:Research is cheaper than development
LeanStartup:Research is cheaper than developmentLeanStartup:Research is cheaper than development
LeanStartup:Research is cheaper than development
 
Surviving in a microservices environment
Surviving in a microservices environmentSurviving in a microservices environment
Surviving in a microservices environment
 
TDC2016SP - Otimização Prematura: a Raíz de Todo o Mal
TDC2016SP - Otimização Prematura: a Raíz de Todo o MalTDC2016SP - Otimização Prematura: a Raíz de Todo o Mal
TDC2016SP - Otimização Prematura: a Raíz de Todo o Mal
 
Funtional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail BortnykFuntional Ruby - Mikhail Bortnyk
Funtional Ruby - Mikhail Bortnyk
 
Tweakers Anonymous
Tweakers AnonymousTweakers Anonymous
Tweakers Anonymous
 
Totally Build Apps for Free! (not really)
Totally Build Apps for Free! (not really)Totally Build Apps for Free! (not really)
Totally Build Apps for Free! (not really)
 
AJAX & jQuery - City University WAD Module
AJAX & jQuery - City University WAD ModuleAJAX & jQuery - City University WAD Module
AJAX & jQuery - City University WAD Module
 
Don't fear our new robot overlords – A new way to test on mobile
Don't fear our new robot overlords – A new way to test on mobileDon't fear our new robot overlords – A new way to test on mobile
Don't fear our new robot overlords – A new way to test on mobile
 
Nuget
NugetNuget
Nuget
 

En vedette

ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2RORLAB
 
ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1RORLAB
 
Make your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On RailsMake your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On RailsNataly Tkachuk
 
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsPaul Gallagher
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsSerge Smetana
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Technologies
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on RailsAgnieszka Figiel
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and RailsWen-Tien Chang
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVMPhil Calçado
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails IntroductionThomas Fuchs
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017John Maeda
 

En vedette (16)

ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2ActiveRecord Validations, Season 2
ActiveRecord Validations, Season 2
 
ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1ActiveRecord Query Interface (1), Season 1
ActiveRecord Query Interface (1), Season 1
 
Make your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On RailsMake your app idea a reality with Ruby On Rails
Make your app idea a reality with Ruby On Rails
 
Rails Performance
Rails PerformanceRails Performance
Rails Performance
 
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/RailsActiveWarehouse/ETL - BI & DW for Ruby/Rails
ActiveWarehouse/ETL - BI & DW for Ruby/Rails
 
Performance Optimization of Rails Applications
Performance Optimization of Rails ApplicationsPerformance Optimization of Rails Applications
Performance Optimization of Rails Applications
 
Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)Neev Expertise in Ruby on Rails (RoR)
Neev Expertise in Ruby on Rails (RoR)
 
Introduction to Ruby on Rails
Introduction to Ruby on RailsIntroduction to Ruby on Rails
Introduction to Ruby on Rails
 
Ruby on Rails
Ruby on RailsRuby on Rails
Ruby on Rails
 
Vitamina B12 oral
Vitamina B12 oralVitamina B12 oral
Vitamina B12 oral
 
Distributed Ruby and Rails
Distributed Ruby and RailsDistributed Ruby and Rails
Distributed Ruby and Rails
 
Ruby Beyond Rails
Ruby Beyond RailsRuby Beyond Rails
Ruby Beyond Rails
 
From a monolithic Ruby on Rails app to the JVM
From a monolithic  Ruby on Rails app  to the JVMFrom a monolithic  Ruby on Rails app  to the JVM
From a monolithic Ruby on Rails app to the JVM
 
GE Predix - The IIoT Platform
GE Predix - The IIoT PlatformGE Predix - The IIoT Platform
GE Predix - The IIoT Platform
 
Ruby On Rails Introduction
Ruby On Rails IntroductionRuby On Rails Introduction
Ruby On Rails Introduction
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017
 

Similaire à 6 reasons Jubilee could be a Rubyist's new best friend

Scaling with swagger
Scaling with swaggerScaling with swagger
Scaling with swaggerTony Tam
 
Cloud conference - mongodb
Cloud conference - mongodbCloud conference - mongodb
Cloud conference - mongodbMitch Pirtle
 
Inside Wordnik's Architecture
Inside Wordnik's ArchitectureInside Wordnik's Architecture
Inside Wordnik's ArchitectureTony Tam
 
WebGL Camp 4 - A3 3D Engine
WebGL Camp 4 - A3 3D EngineWebGL Camp 4 - A3 3D Engine
WebGL Camp 4 - A3 3D Engineaerotwist
 
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)[.Net开发交流会][2010.06.19]better framework better life(吕国宁)
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)Shanda innovation institute
 
Better Framework Better Life
Better Framework Better LifeBetter Framework Better Life
Better Framework Better Lifejeffz
 
The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018Charles Nutter
 
Contributing to rails
Contributing to railsContributing to rails
Contributing to railsLukas Eppler
 
Better framework, better life
Better framework, better lifeBetter framework, better life
Better framework, better lifeDaniel Lv
 
Voice Applications with Adhearsion
Voice Applications with AdhearsionVoice Applications with Adhearsion
Voice Applications with AdhearsionMojo Lingo
 
Rust is for Robots!
Rust is for Robots!Rust is for Robots!
Rust is for Robots!Andy Grove
 
Exploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQLExploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQLBarry Jones
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009pratiknaik
 
How to Build a High Performance Application with PHP and Swoole?
How to Build a High Performance Application with PHP and Swoole?How to Build a High Performance Application with PHP and Swoole?
How to Build a High Performance Application with PHP and Swoole?Albert Chen
 
Message:Passing - lpw 2012
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012Tomas Doran
 
Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06jimbojsb
 
Windycityrails page performance
Windycityrails page performanceWindycityrails page performance
Windycityrails page performanceJohn McCaffrey
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Charles Nutter
 
Selenium IDE and Beyond
Selenium IDE and BeyondSelenium IDE and Beyond
Selenium IDE and BeyondSamit Badle
 

Similaire à 6 reasons Jubilee could be a Rubyist's new best friend (20)

Scaling with swagger
Scaling with swaggerScaling with swagger
Scaling with swagger
 
Cloud conference - mongodb
Cloud conference - mongodbCloud conference - mongodb
Cloud conference - mongodb
 
Inside Wordnik's Architecture
Inside Wordnik's ArchitectureInside Wordnik's Architecture
Inside Wordnik's Architecture
 
WebGL Camp 4 - A3 3D Engine
WebGL Camp 4 - A3 3D EngineWebGL Camp 4 - A3 3D Engine
WebGL Camp 4 - A3 3D Engine
 
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)[.Net开发交流会][2010.06.19]better framework better life(吕国宁)
[.Net开发交流会][2010.06.19]better framework better life(吕国宁)
 
Better Framework Better Life
Better Framework Better LifeBetter Framework Better Life
Better Framework Better Life
 
The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018The Year of JRuby - RubyC 2018
The Year of JRuby - RubyC 2018
 
Contributing to rails
Contributing to railsContributing to rails
Contributing to rails
 
Better framework, better life
Better framework, better lifeBetter framework, better life
Better framework, better life
 
Polyglot Grails
Polyglot GrailsPolyglot Grails
Polyglot Grails
 
Voice Applications with Adhearsion
Voice Applications with AdhearsionVoice Applications with Adhearsion
Voice Applications with Adhearsion
 
Rust is for Robots!
Rust is for Robots!Rust is for Robots!
Rust is for Robots!
 
Exploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQLExploring Ruby on Rails and PostgreSQL
Exploring Ruby on Rails and PostgreSQL
 
Lessons Learnt in 2009
Lessons Learnt in 2009Lessons Learnt in 2009
Lessons Learnt in 2009
 
How to Build a High Performance Application with PHP and Swoole?
How to Build a High Performance Application with PHP and Swoole?How to Build a High Performance Application with PHP and Swoole?
How to Build a High Performance Application with PHP and Swoole?
 
Message:Passing - lpw 2012
Message:Passing - lpw 2012Message:Passing - lpw 2012
Message:Passing - lpw 2012
 
Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06Austin NoSQL 2011-07-06
Austin NoSQL 2011-07-06
 
Windycityrails page performance
Windycityrails page performanceWindycityrails page performance
Windycityrails page performance
 
Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016Ruby Performance - The Last Mile - RubyConf India 2016
Ruby Performance - The Last Mile - RubyConf India 2016
 
Selenium IDE and Beyond
Selenium IDE and BeyondSelenium IDE and Beyond
Selenium IDE and Beyond
 

Plus de Forrest Chang

Crystal is a Rubyists friend (quick anecdote)
Crystal is a Rubyists friend (quick anecdote)Crystal is a Rubyists friend (quick anecdote)
Crystal is a Rubyists friend (quick anecdote)Forrest Chang
 
Making terminal based apps w:ruby
Making terminal based apps w:rubyMaking terminal based apps w:ruby
Making terminal based apps w:rubyForrest Chang
 
Working Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalWorking Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalForrest Chang
 
Ruby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery SpaghettiRuby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery SpaghettiForrest Chang
 
Opal chapter 4_a_new_hope
Opal chapter 4_a_new_hopeOpal chapter 4_a_new_hope
Opal chapter 4_a_new_hopeForrest Chang
 
Data Intensive RIAs on Rails with very little code (Netzke)
Data Intensive RIAs on Rails with very little code (Netzke)Data Intensive RIAs on Rails with very little code (Netzke)
Data Intensive RIAs on Rails with very little code (Netzke)Forrest Chang
 
Opal - Ruby Style!! Ruby in the browser
Opal - Ruby Style!!  Ruby in the browserOpal - Ruby Style!!  Ruby in the browser
Opal - Ruby Style!! Ruby in the browserForrest Chang
 

Plus de Forrest Chang (11)

Crystal is a Rubyists friend (quick anecdote)
Crystal is a Rubyists friend (quick anecdote)Crystal is a Rubyists friend (quick anecdote)
Crystal is a Rubyists friend (quick anecdote)
 
Making terminal based apps w:ruby
Making terminal based apps w:rubyMaking terminal based apps w:ruby
Making terminal based apps w:ruby
 
Working Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in OpalWorking Effectively with Legacy Javascript code in Opal
Working Effectively with Legacy Javascript code in Opal
 
Opal-hot-reloader
Opal-hot-reloaderOpal-hot-reloader
Opal-hot-reloader
 
Ruby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery SpaghettiRuby-ying Javascript: Avoiding jQuery Spaghetti
Ruby-ying Javascript: Avoiding jQuery Spaghetti
 
Rubyconf 2014 recap
Rubyconf 2014 recapRubyconf 2014 recap
Rubyconf 2014 recap
 
Opal a new_hope
Opal a new_hopeOpal a new_hope
Opal a new_hope
 
Opal chapter 4_a_new_hope
Opal chapter 4_a_new_hopeOpal chapter 4_a_new_hope
Opal chapter 4_a_new_hope
 
Data Intensive RIAs on Rails with very little code (Netzke)
Data Intensive RIAs on Rails with very little code (Netzke)Data Intensive RIAs on Rails with very little code (Netzke)
Data Intensive RIAs on Rails with very little code (Netzke)
 
Rubyconf2012 recap
Rubyconf2012 recapRubyconf2012 recap
Rubyconf2012 recap
 
Opal - Ruby Style!! Ruby in the browser
Opal - Ruby Style!!  Ruby in the browserOpal - Ruby Style!!  Ruby in the browser
Opal - Ruby Style!! Ruby in the browser
 

Dernier

CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfBalamuruganV28
 
Robotics Group 10 (Control Schemes) cse.pdf
Robotics Group 10  (Control Schemes) cse.pdfRobotics Group 10  (Control Schemes) cse.pdf
Robotics Group 10 (Control Schemes) cse.pdfsahilsajad201
 
The Satellite applications in telecommunication
The Satellite applications in telecommunicationThe Satellite applications in telecommunication
The Satellite applications in telecommunicationnovrain7111
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...Erbil Polytechnic University
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewsandhya757531
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptxmohitesoham12
 
Indian Tradition, Culture & Societies.pdf
Indian Tradition, Culture & Societies.pdfIndian Tradition, Culture & Societies.pdf
Indian Tradition, Culture & Societies.pdfalokitpathak01
 
priority interrupt computer organization
priority interrupt computer organizationpriority interrupt computer organization
priority interrupt computer organizationchnrketan
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionSneha Padhiar
 
ADM100 Running Book for sap basis domain study
ADM100 Running Book for sap basis domain studyADM100 Running Book for sap basis domain study
ADM100 Running Book for sap basis domain studydhruvamdhruvil123
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communicationpanditadesh123
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSsandhya757531
 
AntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxAntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxLina Kadam
 
STATE TRANSITION DIAGRAM in psoc subject
STATE TRANSITION DIAGRAM in psoc subjectSTATE TRANSITION DIAGRAM in psoc subject
STATE TRANSITION DIAGRAM in psoc subjectGayathriM270621
 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHSneha Padhiar
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
 
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...arifengg7
 
70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical trainingGladiatorsKasper
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Sumanth A
 

Dernier (20)

CS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdfCS 3251 Programming in c all unit notes pdf
CS 3251 Programming in c all unit notes pdf
 
Robotics Group 10 (Control Schemes) cse.pdf
Robotics Group 10  (Control Schemes) cse.pdfRobotics Group 10  (Control Schemes) cse.pdf
Robotics Group 10 (Control Schemes) cse.pdf
 
The Satellite applications in telecommunication
The Satellite applications in telecommunicationThe Satellite applications in telecommunication
The Satellite applications in telecommunication
 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...
 
Artificial Intelligence in Power System overview
Artificial Intelligence in Power System overviewArtificial Intelligence in Power System overview
Artificial Intelligence in Power System overview
 
Python Programming for basic beginners.pptx
Python Programming for basic beginners.pptxPython Programming for basic beginners.pptx
Python Programming for basic beginners.pptx
 
Indian Tradition, Culture & Societies.pdf
Indian Tradition, Culture & Societies.pdfIndian Tradition, Culture & Societies.pdf
Indian Tradition, Culture & Societies.pdf
 
priority interrupt computer organization
priority interrupt computer organizationpriority interrupt computer organization
priority interrupt computer organization
 
Cost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based questionCost estimation approach: FP to COCOMO scenario based question
Cost estimation approach: FP to COCOMO scenario based question
 
ADM100 Running Book for sap basis domain study
ADM100 Running Book for sap basis domain studyADM100 Running Book for sap basis domain study
ADM100 Running Book for sap basis domain study
 
multiple access in wireless communication
multiple access in wireless communicationmultiple access in wireless communication
multiple access in wireless communication
 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
 
AntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptxAntColonyOptimizationManetNetworkAODV.pptx
AntColonyOptimizationManetNetworkAODV.pptx
 
STATE TRANSITION DIAGRAM in psoc subject
STATE TRANSITION DIAGRAM in psoc subjectSTATE TRANSITION DIAGRAM in psoc subject
STATE TRANSITION DIAGRAM in psoc subject
 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
 
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
Analysis and Evaluation of Dal Lake Biomass for Conversion to Fuel/Green fert...
 
70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training70 POWER PLANT IAE V2500 technical training
70 POWER PLANT IAE V2500 technical training
 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
 
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
Robotics-Asimov's Laws, Mechanical Subsystems, Robot Kinematics, Robot Dynami...
 

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
  • 3. ALTERNATE TITLES AFTER SEEING ERNIE MILLER’S RUBY AFTER RAILS
  • 4. ! R A I L S W H I L E S T I L L USING RAILS
  • 5. OR
  • 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
  • 9. WHY ARE YOU HERE AT RUBYCONF?
  • 12. WHY DO YOU LIKE RUBY?
  • 13. BECAUSE IT MAKES YOU HAPPY
  • 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
  • 16. HAPPINESS IS THE RUBY WAY
  • 18. OBJECTIVE • To ensure you, the Rubyist, stays happy
  • 19. HAPPINESS IS A RECURRING THEME • J • D • D IN MY TALKS, AS WELL AS HERE AT RUBYCONF
  • 20. HAPPINESS IS A RECURRING THEME • J Joy • D • D IN MY TALKS, AS WELL AS HERE AT RUBYCONF
  • 21. HAPPINESS IS A RECURRING THEME • J Joy Driven • D • D IN MY TALKS, AS WELL AS HERE AT RUBYCONF
  • 22. HAPPINESS IS A RECURRING THEME • J Joy Driven Development • D • D IN MY TALKS, AS WELL AS HERE AT RUBYCONF
  • 24. WHAT DO WE LIKE ABOUT RUBY?
  • 25. 1) LANGUAGE ITSELF IS DELIGHTFUL
  • 26. 1) LANGUAGE ITSELF IS DELIGHTFUL • An entire talk can be done on this
  • 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
  • 33. RUBY MAKES ME HAPPY
  • 34. RUBY MAKES ME HAPPY
  • 35. 2) GEMS AND FRAMEWORKS
  • 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
  • 40. RAILS
  • 41. RAILS • Who codes in Rails?
  • 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?
  • 46. WHY WE LOVE 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
  • 51. RAILS CAN MAKES YOU HAPPY
  • 52. RAILS CAN MAKES YOU HAPPY
  • 53. RUBY IS NOT A PANACEA
  • 54. SOME REASONS TO NOT USE RUBY
  • 55. SOME REASONS TO NOT USE RUBY • Speed
  • 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.
  • 64. PROBLEM Some non Ruby technologies can be “Less Happy Making”
  • 66. NODE, WHAT IT IS GOOD FOR?
  • 67. NODE, WHAT IT IS GOOD FOR?
  • 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"
  • 75. WHAT IT NODE BAD AT?
  • 76. WHAT IT NODE BAD AT? • Vertical scaling
  • 77. WHAT IT NODE BAD AT? • Vertical scaling • CPU intensive
  • 78. WHAT IT NODE BAD AT? • Vertical scaling • CPU intensive • Integration with other systems
  • 79. WHAT IT NODE BAD AT? • Vertical scaling • CPU intensive • Integration with other systems • Decent language (Ruby bias)
  • 82. BRING BACK THAT LOVING FEELING?
  • 83. BRING BACK THAT LOVING FEELING?
  • 84.
  • 85. • Who's heard of it?
  • 86. • Who's heard of it? • Oversimplified - Node for the JVM
  • 87. • Who's heard of it? • Oversimplified - Node for the JVM • BUT much more - more like Node++ and then some
  • 88. DESIGNED FOR MODERN APPLICATIONS
  • 89. DESIGNED FOR MODERN APPLICATIONS
  • 90. DESIGNED FOR MODERN APPLICATIONS Ruby/ JRuby
  • 91. DESIGNED FOR MODERN APPLICATIONS Ruby/ JRuby
  • 92. DESIGNED FOR MODERN APPLICATIONS Ruby/ JRuby
  • 93. DESIGNED FOR MODERN APPLICATIONS Ruby/ JRuby
  • 100. LIKE NODE • Concurrency - Implements the same Reactor Pattern
  • 101. LIKE NODE • Concurrency - Implements the same Reactor Pattern • Non blocking i/o
  • 102. LIKE NODE • Concurrency - Implements the same Reactor Pattern • Non blocking i/o • Fast
  • 104. BETTER THAN NODE • Handles CPU intensive
  • 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
  • 112. BETTER THAN NODE, PART 2
  • 113. BETTER THAN NODE, PART 2 • Polyglot
  • 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
  • 120. BETTER THAN NODE, PART 3
  • 121. BETTER THAN NODE, PART 3 • Designed to build systems of systems
  • 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
  • 127. CORE APIS- WHAT YOU NEED
  • 128. CORE APIS- WHAT YOU NEED • TCP/SSL clients and servers
  • 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
  • 142. VERT.X DESIGNED FOR INTEGRATED SYSTEMS
  • 143. DIFFERENT TYPES OF PROCESSES
  • 144. DIFFERENT TYPES OF PROCESSES • Asynchronous - Verticle
  • 145. DIFFERENT TYPES OF PROCESSES • Asynchronous - Verticle • Blocking/CPU intensive - worker verticle
  • 148. INTER PROCESS/SYSTEM COMMUNICATION • Event Bus • publish
  • 149. INTER PROCESS/SYSTEM COMMUNICATION • Event Bus • publish • direct message
  • 150. INTER PROCESS/SYSTEM COMMUNICATION • Event Bus • publish • direct message • direct message reply
  • 151. INTER PROCESS/SYSTEM COMMUNICATION • Event Bus • publish • direct message • direct message reply • extends into the browser
  • 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
  • 156. SCALING BUILT I N • Clustering
  • 157. SCALING BUILT I N • Clustering • vertx process.rb —cluster
  • 158. SCALING BUILT I N • Clustering • vertx process.rb —cluster • High Availability
  • 159. SCALING BUILT I N • Clustering • vertx process.rb —cluster • High Availability • vertx process.rb —ha
  • 161. AND MUCH MORE • A whole talk could be done on it
  • 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
  • 168. VERT. X I S P R E T T Y AWESOME
  • 169. VERT. X I S P R E T T Y AWESOME
  • 170. BUT IT’S MORE STUFF TO LEARN
  • 171.
  • 172. WHAT IF I TOLD YOU YOU COULD?
  • 173.
  • 175. ORIGINAL JUBILEE README SLOGAN "We need a web framework for Vertx.", you said.
  • 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."
  • 178. JUBILEE • Originally Rack server w/ vert.x 2.0 built in
  • 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!
  • 183. 6 REASONS VERT.X COULD BE YOUR NEW BEST FRIEND
  • 184. 6 REASONS VERT.X COULD BE YOUR NEW BEST FRIEND • Concurrency
  • 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
  • 191. 1) CONCURRENCY • Same Reactor pattern as Node
  • 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
  • 196. 2) SPEED • JVM faster and getting faster all the time
  • 197. 2) SPEED • JVM faster and getting faster all the time • Can use threads, cpus
  • 198. 2) SPEED • JVM faster and getting faster all the time • Can use threads, cpus • Benchmarks
  • 199. LIES, DAMN LIES, AND BENCHMARKS
  • 200. LIES, DAMN LIES, AND BENCHMARKS • http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/
  • 201. LIES, DAMN LIES, AND BENCHMARKS • http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ Ruby
  • 202. LIES, DAMN LIES, AND BENCHMARKS • http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ Ruby Node
  • 203. LIES, DAMN LIES, AND BENCHMARKS • http://vertxproject.wordpress.com/2012/05/09/vert-x-vs-node-js-simple-http-benchmarks/ Ruby Node 6 processes Node
  • 204.
  • 205. Ruby
  • 207. JUBILEE - 2ND FASTEST RUBY SERVER
  • 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
  • 212.
  • 213.
  • 214.
  • 215. Golang hello world was 10,500 reqs/sec
  • 216. 3 ) E X PANDED ECOSYSTEM
  • 217. 3 ) E X PANDED ECOSYSTEM • Rubygems
  • 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
  • 223. 4 ) BUILT IN UPGRADE/SCALING PATH
  • 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
  • 232. 5) EASY WEBSOCKETS SUPPORT
  • 233. 5) EASY WEBSOCKETS SUPPORT • SocketIO support
  • 234. 5) EASY WEBSOCKETS SUPPORT • SocketIO support • SockJS support
  • 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!
  • 244. JUBILEE CAN MAKE YOU HAPPY
  • 245. JUBILEE CAN MAKE YOU HAPPY
  • 246. INSTALLATION $ gem install jubilee!
  • 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 !
  • 249. WHAT ABOUT HEROKU? • http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html
  • 250. WHAT ABOUT HEROKU? • http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html Gemfile ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! gem 'jubilee', :platforms => [:jruby]! gem 'rails_12factor'
  • 251. WHAT ABOUT HEROKU? • http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html Gemfile ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! gem 'jubilee', :platforms => [:jruby]! gem 'rails_12factor' Procfile web: jubilee --eventbus /eventbus -n 1 —e $RACK_ENV -p $PORT !
  • 252. WHAT ABOUT HEROKU? • http://funkworks.blogspot.com/2014/08/deploying-rails-41-app-served-by.html Gemfile ruby '2.0.0', engine: 'jruby', engine_version: '1.7.13'! gem 'jubilee', :platforms => [:jruby]! gem 'rails_12factor' Procfile web: jubilee --eventbus /eventbus -n 1 —e $RACK_ENV -p $PORT ! Set JRuby/JVM Opts heroku config:add JRUBY_OPTS="-J-Xmn128m -J-Xms768m -J-Xmx768m"!
  • 254. GETTING THE MESSAGE ACROSS • Everyone has slides
  • 255. GETTING THE MESSAGE ACROSS • Everyone has slides • Many have demos
  • 256. GETTING THE MESSAGE ACROSS • Everyone has slides • Many have demos • I want 1st hand interaction -
  • 260. NODE’S SWEET SPOT • Chat - The sample app that everyone makes
  • 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
  • 264. MMO WHAT? • Rock, Paper, Scissors
  • 265. MMO WHAT? • Rock, Paper, Scissors • Really!
  • 266. MMO WHAT? • Rock, Paper, Scissors • Really! • 4 kids, demanding job - World of Warcraft is out
  • 268. EXPERIENCING JUBILEE IN ACTION • Everyone in the room sign on
  • 269. EXPERIENCING JUBILEE IN ACTION • Everyone in the room sign on • Play each other
  • 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?)
  • 275. ROCK R P PAPER S SCISSORS MAYHEM M
  • 276. R P S M
  • 277. ! P HTTP://BIT. LY/RPSMAYHEM ! ! ! ! M ! ! R S
  • 279. WHAT TO DO • Go to http://bit.ly/rpsmayhem
  • 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
  • 286. PLAY I T !
  • 288. RIGHT TOOL FOR THE JOB
  • 289. RIGHT TOOL FOR THE JOB • Rails
  • 290. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise
  • 291. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml
  • 292. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations
  • 293. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x
  • 294. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x • Event Bus - websockets, concurrency, subsystem communciation
  • 295. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x • Event Bus - websockets, concurrency, subsystem communciation • Shared Data - quick shared memory
  • 296. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x • Event Bus - websockets, concurrency, subsystem communciation • Shared Data - quick shared memory • Vertx::Timer - enforce challenge acceptance timeout
  • 297. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x • Event Bus - websockets, concurrency, subsystem communciation • Shared Data - quick shared memory • Vertx::Timer - enforce challenge acceptance timeout • Additional Verticle - Bot
  • 298. RIGHT TOOL FOR THE JOB • Rails • Login - omniauth, devise • Views - haml • DB - ActiveRecord, migrations • Jubilee/Vert.x • Event Bus - websockets, concurrency, subsystem communciation • Shared Data - quick shared memory • Vertx::Timer - enforce challenge acceptance timeout • Additional Verticle - Bot • Worker Verticle - TBI Leaderboard
  • 300. APP SUMMARY • Rails to get to the game
  • 301. APP SUMMARY • Rails to get to the game • Jubilee/Vert.x to play the game
  • 304. MAIN PAGE Main page is vanilla Rails Sign in
  • 305. SIGN IN WITH TWITTER
  • 306. SIGN IN WITH TWITTER Omniauth gem makes it easy
  • 307. CHAT LIKE FEATURES OF THE GAME
  • 308. CHAT LIKE FEATURES OF THE GAME You
  • 309. CHAT LIKE FEATURES OF THE GAME You Live Activity Stream
  • 310. CHAT LIKE FEATURES OF THE GAME You Live Activity Stream Live presence and state
  • 311. CHALLENGE AN OPPONENT You can give up
  • 312. CHALLENGE TIME OUT Jubilee/Vert.x Timer checks and cancels the challenge
  • 314. REALTIME CHALLENGE Connected to server and each other by EventBus
  • 316. CHALLENGE TIME OUT Jubilee/Vert.x Timer checks and cancels the challenge
  • 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
  • 328. DESIGNED TO WORK TOGETHER
  • 329. AS OPPOSED TO DUCT TAPED TOGETHER
  • 332. APP CODE STATS • Client code 497 LOC Opal (including whitespace and debug)
  • 333. APP CODE STATS • Client code 497 LOC Opal (including whitespace and debug) • game.js.rb 444
  • 334. APP CODE STATS • Client code 497 LOC Opal (including whitespace and debug) • game.js.rb 444 • event_bus.rb 52
  • 335. APP CODE STATS • Client code 497 LOC Opal (including whitespace and debug) • game.js.rb 444 • event_bus.rb 52 • Server code: vertx initializer 50 LOC including whitespace and comments
  • 336. CODE
  • 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
  • 353. CLIENT SIDE EVENTBUS SETUP (OPAL) def setup_eventbus! @event_bus = EventBus.new! @event_bus.onopen {! @event_bus.send_msg(:login, @uid)! @event_bus.register_handler(:new_user) do |data|! json = JSON.parse(data)! @player_info[json[:id]] = { name: json[:name], image: json[:image]}! render_potential_victim(json) unless json[:id].to_i == @uid.to_i! append_activity("#{json['name']} joined")! end
  • 354. CLIENT SIDE EVENTBUS SETUP (OPAL) def setup_eventbus! @event_bus = EventBus.new! @event_bus.onopen {! @event_bus.send_msg(:login, @uid)! @event_bus.register_handler(:new_user) do |data|! json = JSON.parse(data)! @player_info[json[:id]] = { name: json[:name], image: json[:image]}! render_potential_victim(json) unless json[:id].to_i == @uid.to_i! append_activity("#{json['name']} joined")! end
  • 355. CLIENT SIDE EVENTBUS SETUP (OPAL) def setup_eventbus! @event_bus = EventBus.new! @event_bus.onopen {! @event_bus.send_msg(:login, @uid)! @event_bus.register_handler(:new_user) do |data|! json = JSON.parse(data)! @player_info[json[:id]] = { name: json[:name], image: json[:image]}! render_potential_victim(json) unless json[:id].to_i == @uid.to_i! append_activity("#{json['name']} joined")! end
  • 356. CLIENT SIDE EVENTBUS SETUP (OPAL) def setup_eventbus! @event_bus = EventBus.new! @event_bus.onopen {! @event_bus.send_msg(:login, @uid)! @event_bus.register_handler(:new_user) do |data|! json = JSON.parse(data)! @player_info[json[:id]] = { name: json[:name], image: json[:image]}! render_potential_victim(json) unless json[:id].to_i == @uid.to_i! append_activity("#{json['name']} joined")! 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
  • 370. JUBILEE CONSIDERATIONS IN RAILS • Setup server side EventBus in Rails initializer
  • 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
  • 384. RUBY IN THE BROWSER MAKES ME HAPPY
  • 385. RUBY IN THE BROWSER MAKES ME HAPPY
  • 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