Slide 1

Slide 1 text

Event Collaboration for the Rubyist by Luismi Cavallé

Slide 2

Slide 2 text

twitter.com/cavalle github.com/cavalle

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Event Collaboration?

Slide 5

Slide 5 text

Multiple components work together by communicating with each other by sending events when their internal state changes. — Martin Fowler http://tinyurl.com/eaaDev

Slide 6

Slide 6 text

Given one task is pending When I complete it Then my boss is noti ed Given I completed one task in 1 day And I completed other task in 2 days When I see the performance report Then my performance is 1.5 tasks/day

Slide 7

Slide 7 text

class Task def mark_as_completed! update_attributes! :completed => true notify_boss update_progress_report end def notify_boss # ... end def update_progress_report # ... end end

Slide 8

Slide 8 text

The Single Responsibility Principle “An object should have only a single responsibility.” — Uncle Bob http://tinyurl.com/OOPrinciples

Slide 9

Slide 9 text

class Task def mark_as_completed! update_attributes! :completed => true Notifier.notify_task_completed self ProgressReport.update_performance self end end

Slide 10

Slide 10 text

The Open Closed Principle “[An object] should be open for extension, but closed for modi cation.” — Uncle Bob http://tinyurl.com/OOPrinciples

Slide 11

Slide 11 text

class Task def mark_as_completed! update_attributes! :completed => true publish_event :task_completed, :task_name => name, :by => user.name end # ... end

Slide 12

Slide 12 text

class Notifier on :task_completed do |event| Notifier.new(:email => find_boss_email(event.by), :subject => "Task #{event.task_name} completed").send! end # ... end

Slide 13

Slide 13 text

module PerformanceStats on :task_created do |event| start_times[event.task_name] = Time.now end on :task_completed do |event| completion_time_sum += Time.now - start_times.delete(event.task_name) completion_time_count += 1 end def self.average_performance completion_time_sum / completion_time_count end # ... end

Slide 14

Slide 14 text

Task Noti er Performance Stats

Slide 15

Slide 15 text

Loose coupling Maintainability Scalability

Slide 16

Slide 16 text

Un momento de relax…

Slide 17

Slide 17 text

Eventwire Event Collaboration for the Masses http://github.com/cavalle/eventwire

Slide 18

Slide 18 text

Interface Middleware Adapters Your App Workers RabbitMQ Redis MongoDB ZeroMQ

Slide 19

Slide 19 text

Interface: Publisher class MyPublisher include Eventwire::Publisher def my_method publish_event :task_completed, :task_name => 'Name of the task', :username => 'Username' end end

Slide 20

Slide 20 text

Interface: Subscriber class MySubscriber include Eventwire::Subscriber on :task_completed do |data| puts "Task completed #{data.task_name}" end end

Slide 21

Slide 21 text

Adapters AMQP Redis MongoDB ZeroMQ Bunny InProcess Syslog

Slide 22

Slide 22 text

Middleware MsgPack ErrorHandler Logger DataObjects JSON BSON

Slide 23

Slide 23 text

Workers $ rake eventwire:work $ rake environment eventwire:work

Slide 24

Slide 24 text

Con guration Eventwire.configure do |config| config.adapter = :AMQP config.logger = Rails.logger config.middleware << MyCustomMiddleware end

Slide 25

Slide 25 text

P1 P2 S1 S3 S2 S2 S2 Pub / Sub Bus Sub. Balancing Messaging Patterns

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

Current status Not released to Rubygems yet Some adapters are very experimental Next milestone: Production at BeBanjo

Slide 28

Slide 28 text

Future Measure & Improve Adapters New Adapters Documentation Front-end ala Resque

Slide 29

Slide 29 text

Some tradeoffs Another layer of abstraction Lost messages Messages out of order

Slide 30

Slide 30 text

References http://github.com/cavalle/eventwire http://tinyurl.com/eaaDev http://rubyamqp.info/

Slide 31

Slide 31 text

¡Gracias! twitter.com/cavalle github.com/cavalle speakerdeck.com/u/cavalle