Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Make an Event of It! (RubyNation 2013)

Make an Event of It! (RubyNation 2013)

The upsurge in asynchronous programming has brought event-driven patterns to the forefront. But even if you aren't re-writing your app in Node.js, evented patterns can improve your application. This talk demonstrates concrete examples of how events can benefit the various layers of your application. It shows how events can pitch in the fight against fat controllers (and fat models too!) It applies eventing to simplify testing and decouple our app from external dependencies. It even reveals how eventing can help shape data to provide flexibility and auditing.

Jason R Clark

June 14, 2013
Tweet

More Decks by Jason R Clark

Other Decks in Technology

Transcript

  1. Jason Clark @jasonrclark Ruby Agent Engineer Make an Event of

    It! Evented Patterns in Ruby Friday, June 14, 13
  2. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 2 Friday, June 14, 13
  3. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events asEvents as Data Data 3 Friday, June 14, 13
  4. Events Aren't (Necessarily) 7 • Asynchronous • IO related •

    Distributed • Complicated Friday, June 14, 13
  5. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 13 Friday, June 14, 13
  6. 16 def connect() # ... setup connection config = config_from_server()

    finish_setup(config) end Friday, June 14, 13
  7. 18 def test_finish_setup_naming_rules @agent.naming_rules = RulesEngine.new config = { 'rules'

    => [...] } finish_setup(config) rules = @agent.transaction_rules assert_equal 2, rules.size end Friday, June 14, 13
  8. 23 def test_finish_setup called = false @events.subscribe(:configured) do called =

    true end finish_setup({}) assert called end Friday, June 14, 13
  9. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 30 Friday, June 14, 13
  10. 34 module NewRelic::Rack class AgentHooks def call(env) notify(:before_call, env) result

    = @app.call(env) notify(:after_call, env, result) result end end end Friday, June 14, 13
  11. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 40 Friday, June 14, 13
  12. 43 class SimpleEvents::Notifier ... def subscribe(event, &handler) @events[event] ||= []

    @events[event] << handler check_for_runaway_subscriptions(event) end ... end Friday, June 14, 13
  13. 44 class SimpleEvents::Notifier ... def notify(event, *args) return unless @events.has_key?(event)

    @events[event].each do |handler| begin handler.call(*args) rescue => err logger.debug("Fail #{@event}", err) end end end end Friday, June 14, 13
  14. 45 class SimpleEvents::Notifier ... def notify(event, *args) return unless @events.has_key?(event)

    @events[event].each do |handler| begin handler.call(*args) rescue => err logger.debug("Fail #{@event}", err) end end end end Friday, June 14, 13
  15. 46 class SimpleEvents::Notifier ... def notify(event, *args) return unless @events.has_key?(event)

    @events[event].each do |handler| begin handler.call(*args) rescue => err logger.debug("Fail #{@event}", err) end end end end Friday, June 14, 13
  16. 47 class SimpleEvents::Notifier ... def notify(event, *args) return unless @events.has_key?(event)

    @events[event].each do |handler| begin handler.call(*args) rescue => err logger.debug("Fail #{@event}", err) end end end end Friday, June 14, 13
  17. Subscribing 52 events = [] AS::Notifications.subscribe("event") \ do |*args| events

    << *args end ["render_template.action_view", "e2a1e92a3c613576c2b0" {:identifier=>"/file/path/here"}] Friday, June 14, 13
  18. Easier Access 53 e = AS::Notifications::Event.new(*args) e.name # => "render_template..."

    e.duration # => 10 (in milliseconds) e.payload # => { :identifier => ... } Friday, June 14, 13
  19. Other Functionality • Regexp on Notifications.subscribe • Event#parent_of? • Temporary

    subscription/Unsubscribe • LogSubscriber 56 Friday, June 14, 13
  20. Where Are We Going? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 58 Friday, June 14, 13
  21. 60 Opened Account $100 Check 0001 -$15 Deposit $20 Check

    0002 -$21 Total $84 Bank Transactions Friday, June 14, 13
  22. 62 customer_id date plan 1 1/1/2013 basic 1 1/2/2013 premium

    1 2/1/2013 basic 1 2/2/2013 premium Friday, June 14, 13
  23. 62 customer_id date plan 1 1/1/2013 basic 1 1/2/2013 premium

    1 2/1/2013 basic 1 2/2/2013 premium Friday, June 14, 13
  24. Other Examples 70 • Database replication • Log files •

    PubSub • Immutable data structures Friday, June 14, 13
  25. Upsides 71 ★ No Updates ★ Automatic Audits ★ Can

    Summarize/Transform/Cache Friday, June 14, 13
  26. Downsides - So Much Data! - Hard to Query Efficiently

    - More Complex Code 72 Friday, June 14, 13
  27. Where Have We Been? • The Pattern • Internal Coupling

    • External Coupling • Mechanics • Events as Data 73 Friday, June 14, 13