Roda and Rails
y-yagi@Railsdm 2019
自己紹介
今日お話すること
About Roda
Roda
Roda
route do |r|� r.is 'artist/:id' do |artist_id|� r.get do� view :artist� end�� r.post do� @artist.update(r['artist'])� r.redirect� end� end�end�
Roda
Jeremy Evans
何故Rodaか
はやい
Roda is fast
Web Framework Benchmarks
Web Framework Benchmarks
Web Framework Benchmarks
Web Framework Benchmarks
Roda is fast?
Roda is fast?
Plugin system
class MyTodo < Roda� plugin :csrf� plugin :render, escape: true�� # ...�end�
Roda is fast?
Roda or Rails
Rodaは"Routing Tree Web Framework Toolkit"なのでRouterについて考えてみる
Rails Router
Rails Router
Rails Router
GraphQL
graphql gemをつかう場合
Rails.application.routes.draw do� post "/graphql", to: "graphql#execute"�end�
GraphQL
Roda on Rails
ここまでで半分くらい
Roda on Rails
GraphQL endpoint(Rails)
class GraphqlController < ApplicationController� def execute� variables = ensure_hash(params[:variables])� query = params[:query]� operation_name = params[:operationName]� context = { current_user: current_user }� result = BeholderSchema.execute(query, variables: variables, context: context, operation_name: operation_name)� render json: result� rescue => e� # ...� end�end�
GraphQL endpoint(Roda)
class RodaRoutes < Roda� plugin :json� plugin :json_parser� route do |r|� r.post "graphql" do� variables = ensure_hash(request.params["variables"])� query = request.params["query"]� operation_name = request.params["operationName"]� context = { current_user: current_user }� BeholderSchema.execute(query, variables: variables, context: context, operation_name: operation_name).to_h� rescue => e� # ...� end� end�end�
Roda Application
# routes.rb�Rails.application.routes.draw do� post "/graphql", to: "graphql#execute"� mount RodaRoutes.freeze.app => "/roda"�end�
性能検証
性能検証
性能検証
| Requests/sec | Latency(Avg) |
Rails | 190.89 | 26.20ms |
mount | 229.78 | 21.76ms |
性能検証
RailsにそのままRodaのっけただけでも多少速くなる
他のパターンも試してみよう
先のパターンではRailsのrouterはそのまま使用したがそこを変えたらどうなるか
Railsアプリケーション
Railsアプリケーション
endpoint
def app� @app || @app_build_lock.synchronize {� @app ||= begin� stack = default_middleware_stack� config.middleware = build_middleware.merge_into(stack)� config.middleware.build(endpoint)� end� }�end��def endpoint� self.class.endpoint || routes�end��https://github.com/rails/rails/blob/870377915af301c98a54f7f588e077610b2190aa/railties/lib/rails/engine.rb#L503-L518
endpoint
# config/application.rb�class Application < Rails::Application� endpoint RodaRoutes.freeze.app� # ...�end�
性能検証
| Requests/sec | Latency(Avg) |
Rails | 190.89 | 26.20ms |
mount | 229.78 | 21.76ms |
endpoint | 227.25 | 22.00ms |
Rackミドルウェア
Rackミドルウェア(API-only)
$ RAILS_ENV=production ./bin/rails middleware�use ActionDispatch::HostAuthorization�use Rack::Sendfile�use ActionDispatch::Executor�use ActiveSupport::Cache::Strategy::LocalCache::Middleware�use Rack::Runtime�use ActionDispatch::RequestId�use ActionDispatch::RemoteIp�use Rails::Rack::Logger�use ActionDispatch::ShowExceptions�use ActionDispatch::DebugExceptions�use ActionDispatch::Callbacks�use Rack::Head�use Rack::ConditionalGet�use Rack::ETag�
Rackミドルウェア
Rackミドルウェア
使わないミドルウェアは個別に削除出来る
# config/application.rb�class Application < Rails::Application� config.middleware.delete Rack::Sendfile� # ...�end�
Rackミドルウェア
Roda
class RodaRoutes < Roda� use Rack::JWT::Auth� use ActionDispatch::RequestId�� # ...�end�
config.ru
require_relative 'config/environment'��- run Rails.application�+ run RodaRoutes.freeze.app�
性能検証
| Requests/sec | Latency(Avg) |
Rails | 190.89 | 26.20ms |
mount | 229.78 | 21.76ms |
endpoint | 227.25 | 22.00ms |
Roda | 281.94 | 17.74ms |
Roda
Rackアプリケーション
railroad-switch
config.ru
Railroad::Switch.register(path: "/roda/graphql", app: RodaRoutes.freeze.app)�Railroad::Switch.fallback_to = Rails.application�run Railroad::Switch.app�
性能検証
| Requests/sec | Latency(Avg) |
Rails | 190.89 | 26.20ms |
mount | 229.78 | 21.76ms |
endpoint | 227.25 | 22.00ms |
Roda | 281.94 | 17.74ms |
Rails(SW) | 188.27 | 26.52ms |
Roda(SW) | 281.11 | 17.76ms |
まとめ
まとめ
おまけ
因みに、Rodaでアプリケーションを作る方法についてもうちょっと知りたい方は、"First step of Roda"という同人誌を去年書いたのでそれを見て頂ければと
https://github.com/y-yagi/roda-first/blob/master/book.pdf