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

Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)

Mojolicious - Perl Framework for the Real-Time Web (Lightning Talk)

A lightning talk given at Rails Israel 2014
(http://railsisrael2014.events.co.il/presentations/1319-mojolicious-perl-framework-for-the-real-time-web).
Uses some slides lifted from Glen Hinkle's YAPC 2012 talk
(https://speakerdeck.com/tempire/intro-to-mojolicious-perl)
and an image created by Marcus Ramburg.

Dotan Dimet

November 04, 2014
Tweet

Other Decks in Programming

Transcript

  1. Perl  People   •  But  some  came   back  

    •  And  brought  back   cool  ideas  
  2. Real  Time  Web     •  Non-­‐blocking  I/O   • 

    Event-­‐driven  code   •  Asynchronous  APIs   – Not  mandatory   – SomeJmes  necessary  
  3. Example   use  Mojolicious::Lite;   use  5.20.0;   use  experimental

     'signatures';     get  '/'  =>  {template  =>  'index'};     websocket  '/title'  =>  sub  ($c)  {      $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $title  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('title')-­‐>text;          $c-­‐>send($title);      });   };     app-­‐>start;   __DATA__     @@  index.html.ep   %  my  $url  =  url_for  'title';   <script>      var  ws  =  new  WebSocket('<%=  $url-­‐>to_abs  %>');      ws.onmessage  =  function  (event)  {  document.body.innerHTML  +=  event.data  };      ws.onopen        =  function  (event)  {  ws.send('http://mojolicio.us')  };   </script>    
  4. First  Route:    render  a  template        

                                     get  '/'  =>  {template  =>  'index'};      
  5. use  Mojolicious::Lite;   use  5.20.0;   use  experimental  'signatures';  

      get  '/'  =>  {template  =>  'index'};         websocket  '/title'  =>  sub  ($c)  {      $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $title  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('title')-­‐>text;          $c-­‐>send($title);      });   };     app-­‐>start;   __DATA__     @@  index.html.ep   %  my  $url  =  url_for  'title';   <script>      var  ws  =  new  WebSocket('<%=  $url-­‐>to_abs  %>');      ws.onmessage  =  function  (event)  {  document.body.innerHTML  +=  event.data  };      ws.onopen        =  function  (event)  {  ws.send('http://mojolicio.us')  };   </script>    
  6. Template  (embedded  Perl)   %  my  $url  =  url_for  'Jtle';

      <script>      var  ws  =  new  WebSocket('<%=  $url-­‐>to_abs  %>');      ws.onmessage  =  funcJon  (event)   {  document.body.innerHTML  +=  event.data  };      ws.onopen        =  funcJon  (event)  {  ws.send('h]p:// mojolicio.us')  };   </script>    
  7. Websocket  Message  Event   websocket  '/Jtle'  =>  sub  ($c)  {

         $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $Jtle  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('Jtle')-­‐>text;          $c-­‐>send($Jtle);      });   };   Event  driven  –  subscribe  to  message  event,   triggered  when  complete  message  arrives  
  8. Websocket  Message  Event   websocket  '/Jtle'  =>  sub  ($c)  {

         $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $Jtle  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('Jtle')-­‐>text;          $c-­‐>send($Jtle);      });   };   •  Send  response  when  done  
  9. Built-­‐in  Web  Client   websocket  '/Jtle'  =>  sub  ($c)  {

         $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $Jtle  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('Jtle')-­‐>text;          $c-­‐>send($Jtle);      });   };   Get  a  web  page,  parse  into  DOM,  return  the  Jtle   text.  
  10. Web  Client   •  Mojo::UserAgent   – Blocking  and  non-­‐blocking  HTTP

     requests   •  Mojo::DOM   – Supports  most  CSS  selectors  like  jQuery  
  11. Web  Client  2   •  Get  Haaretz.co.il  full  arJcle  text:

      self-­‐>ua-­‐>get(  $url,     {  'User-­‐Agent'  =>  'Googlebot/2.1;  +h]p://www.google.com/ bot.html)'  }    )-­‐>res-­‐>dom-­‐>find('#arJcle-­‐box  p')-­‐>join("\n");  
  12. But  this  is  blocking  code!    $c-­‐>on(message  =>  sub  ($c,

     $msg)  {          my  $Jtle  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('Jtle')-­‐>text;          $c-­‐>send($Jtle);      });     When  we  trigger  the  message  event,  we  block   the  event  loop  unJl  we  get  a  response  from  the   web  page  
  13. SomeJmes  blocking  is  OK   •  TradiJonal  Database  connecJon  

    •  Small  apps,  querying  fast  remote  sites  
  14. But  we  don’t  have  to  block   $c-­‐>ua-­‐>get($url,  sub  {

     ...  });   The  Mojo::UserAgent  calls  can  take  a  callback  to   make  non-­‐blocking  requests  
  15. SomeJmes  we  can’t  block   $c-­‐>ua-­‐>get($c-­‐>url_for(‘index’)-­‐>to_abs)   •  For  example,

     when  demoing  without  internet,   we  want  to  fetch  a  web  page  we  are  serving   from  the  same  process...  
  16. More     •  h]p://mojolicio.us   •  h]p://mojocasts.com    

    – Glen  Hinkle  @tempire     •   (I  stole  the  nice  slides  from  him)   •  irc  irc://irc.perl.org/#mojo     •  mailing  list  [email protected]    
  17. use  Mojolicious::Lite;   use  5.20.0;   use  experimental  'signatures';  

      get  '/'  =>  {template  =>  'index'};     websocket  '/title'  =>  sub  ($c)  {      $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $title  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('title')-­‐>text;          $c-­‐>send($title);      });   };     app-­‐>start;   __DATA__     @@  index.html.ep   %  my  $url  =  url_for  'title';   <script>      var  ws  =  new  WebSocket('<%=  $url-­‐>to_abs  %>');      ws.onmessage  =  function  (event)  {  document.body.innerHTML  +=  event.data  };      ws.onopen        =  function  (event)  {  ws.send('http://mojolicio.us')  };   </script>    
  18. Signatures   use  Mojolicious::Lite;   Use  5.20.0;   Use  experimental

     'signatures';     get  '/'  =>  {template  =>  'index'};     websocket  '/title'  =>  sub  ($c)  {      $c-­‐>on(message  =>  sub  ($c,  $msg)  {          my  $title  =  $c-­‐>ua-­‐>get($msg)-­‐>res-­‐>dom-­‐>at('title')-­‐>text;          $c-­‐>send($title);      });   };     app-­‐>start;   __DATA__     @@  index.html.ep   %  my  $url  =  url_for  'title';   <script>      var  ws  =  new  WebSocket('<%=  $url-­‐>to_abs  %>');      ws.onmessage  =  function  (event)  {  document.body.innerHTML  +=  event.data  };      ws.onopen        =  function  (event)  {  ws.send('http://mojolicio.us')  };   </script>