2. Ja
• opowiem wam o pewnym projekcie
• pisałem w PHP i już nie chcę (-:
• teraz piszę w Ruby
• i bardzo się staram, bo nie wiem kto siedzi
obok, a jak mówi chińskie przysłowie:
Zawsze pisz kod tak, jakby osoba która będzie
pracowała nad nim po tobie była psychopatycznym
mordercą, który wie gdzie mieszkasz.
3. Był sobie projekt
• Panel administracyjny z podstawową
funkcjonalnością
• RESTful API
• Serwer WebSocket
• Aplikacja mobilna dla iOS-a
9. RabbitMQ
• Message Broker
• po polsku: Mesedż Broker 😜
• po prostu działa ™
• Erlang, no trudno
• https://www.rabbitmq.com/
10. EventMachine
• implementuje wzorzec reaktora
• jest lekka i szybka
• cięższe zadania -> Deferrable
• https://github.com/eventmachine/
eventmachine
11. Bunny
• tunel do RabbitMQ
• prosty (bardzo)
• to już duży, dojrzały królik
• działa z… EM
• https://github.com/ruby-amqp/bunny
12. EM-WebSockets
• Serwer WebSocket w Ruby
• prosty (bardzo)
• działa z… EM
• deja vu, deja vu
• https://github.com/igrigorik/em-websocket
14. Pętla główna
require "event_machine"
EventMachine.run do
definition_of_some_useful_handlers
end
Disclaimer:
prezentowany kod to złożona forma cyfrowego odwzorowania ludzkiej
myśli. Jest obszerny i skomplikowany, może też być niezrozumiały.
żart, przecież to Ruby
20. Razem prezentuje się…
require "event_machine"
require "bunny"
require "em-websocket"
counter = 0
server_config_hash = {host: "0", port: 8080}
connection = Bunny.new
channel = connection.create_channel
queue = channel.queue("a_test_queue", durable: false)
EventMachine.run do
EM::WebSocket.run(server_config_hash) do |ws|
ws.onopen { |handshake| do_something_on_open(ws, handshake) }
ws.onmessage { |msg| do_something_else_on_message(ws, msg) }
ws.onclose { do_nothing_on_close(ws) }
ws.onerror { |error| definitely_do_nothing_on_error(error) }
end
queue.subscribe(manual_ack: true, block: false) do |delivery_info, properties, body|
message = JSON.parse(body) # it's smart and convenient to use JSON
do_magic_on(message)
channel.ack(delivery_info.delivery_tag)
end
EventMachine::PeriodicTimer.new(1) do
send_server_stats_to_manager_email
end
end
Niewiele kodu,
który sporo robi
bo Facebook
sam się nie uzupełni
21. Tymczasem w aplikacji…
class Message
def push_to_bunny
$rabbit_session.publish_message(self.id)
end
end
Tyle wystarczy, żeby wysłać
naszą wiadomość
do kolejki. Ruby rulez (-:
23. Obserwacje
• wyjątki dobrze jest obsługiwać w miejscu,
w którym się ich spodziewamy. EM
domyślnie je przechwytuje i tyle.
• nie należy serializować obiektów i
wrzucać ich do kolejek. Ale przecież nikt
tego nie robi. Robi?
24. Obserwacje…
• Bundler.require jest pożyteczny
• Obsługę poszczególnych sub-pętli dobrze
wrzucić do dedykowanych klas. Kod staje
się podatny na testowanie.