<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Peter Ohler</title>
    <description>The latest articles on DEV Community by Peter Ohler (@ohler55).</description>
    <link>https://dev.to/ohler55</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F96516%2Fe149858e-b03b-4e4d-b5e4-bd0b5526447c.jpeg</url>
      <title>DEV Community: Peter Ohler</title>
      <link>https://dev.to/ohler55</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ohler55"/>
    <language>en</language>
    <item>
      <title>The Pretty JSON Revolution</title>
      <dc:creator>Peter Ohler</dc:creator>
      <pubDate>Tue, 23 Feb 2021 00:11:46 +0000</pubDate>
      <link>https://dev.to/ohler55/the-pretty-json-revolution-30ah</link>
      <guid>https://dev.to/ohler55/the-pretty-json-revolution-30ah</guid>
      <description>&lt;p&gt;Having a bit of fun with JSON formatting. &lt;a href="http://www.ohler.com/dev/pretty.html"&gt;http://www.ohler.com/dev/pretty.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>json</category>
      <category>go</category>
    </item>
    <item>
      <title>Building Solid Go GraphQL Applications Quickly</title>
      <dc:creator>Peter Ohler</dc:creator>
      <pubDate>Tue, 02 Feb 2021 19:40:34 +0000</pubDate>
      <link>https://dev.to/ohler55/building-solid-go-graphql-applications-quickly-343a</link>
      <guid>https://dev.to/ohler55/building-solid-go-graphql-applications-quickly-343a</guid>
      <description>&lt;p&gt;Black box testing is a great way to build GraphQL applications quickly. Check out a step by step with code that can be reused &lt;a href="https://github.com/ohler55/graphql-test-tool/blob/develop/example/solid-quick.md"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>graphql</category>
      <category>testing</category>
    </item>
    <item>
      <title>Testing Asynchronous Threads in Ruby</title>
      <dc:creator>Peter Ohler</dc:creator>
      <pubDate>Tue, 06 Nov 2018 13:56:33 +0000</pubDate>
      <link>https://dev.to/appsignal/testing-asynchronous-threads-in-ruby-3ggl</link>
      <guid>https://dev.to/appsignal/testing-asynchronous-threads-in-ruby-3ggl</guid>
      <description>&lt;p&gt;Threads and asynchronous environments are initially a bit tricky. Without a good mental model to organize interaction, it is easy to get into trouble and end up with unexpected results. On top of that, testing asynchronous code can be difficult without the right tools or test patterns.&lt;/p&gt;

&lt;p&gt;Thinking about threads as people and shared objects as ‘things’ that can be owned helps to organize the working of a multithreaded system. In this episode we will go through an example to learn all about testing asynchronous Ruby code.&lt;/p&gt;

&lt;p&gt;If you are using Rails or Rack or really any application that as a web browser front end you are in an asynchronous environment. The Rack &lt;code&gt;#call&lt;/code&gt; is always called asynchronously. So whether you know it or not, there is a good chance you are already using multithreaded components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing: Trigger, collect and check
&lt;/h2&gt;

&lt;p&gt;Testing an asynchronous callback API can be made synchronous by following a pattern of three steps; &lt;em&gt;trigger&lt;/em&gt;, &lt;em&gt;collect&lt;/em&gt;, and &lt;em&gt;check&lt;/em&gt;. Think if each thread as a separate individual and objects as, well, things that can be owned by just one individual at a time.&lt;/p&gt;

&lt;p&gt;We’ll use the example of Batman and his 7 different suits. Because that is a practical example and we can understand the importance of knowing whether all suits are with Alfred to be washed when you are about to run out and save the city.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: Laundry day at the batcave
&lt;/h2&gt;

&lt;p&gt;The example is Alfred washing Batman's suits. The SuitWashScheduler is a scheduler that invokes a callback for each washing event. The scheduler makes seven callbacks at one-second intervals starting one second after starting. The trigger is the&lt;br&gt;
creation of the &lt;code&gt;SuitWashScheduler&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SuitWashScheduler&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;cnt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Collecting
&lt;/h2&gt;

&lt;p&gt;Collecting results must be thread safe to avoid &lt;a href="https://en.wikipedia.org/wiki/Race_condition"&gt;race conditions&lt;/a&gt;. Any object shared across more than one thread has to be protected. Protection is a way of keeping track of the owner of an object. Only the owner can make changes or view the object. A suit can only be with Batman to use in fights, or with Alfred to be washed.&lt;/p&gt;

&lt;p&gt;To stay friendly a thread (in the metaphor Batman or Alfred) only takes ownership for short times and then gives up the ownership. A &lt;code&gt;Mutex&lt;/code&gt; is usually used to keep track of the owner. The &lt;code&gt;SuitwashScheduler&lt;/code&gt; callback will own the result counter when the counter is incremented. The callback that is run in the &lt;code&gt;SuitWashScheduler&lt;/code&gt; thread signals that all results have been received when the counter hits the target.&lt;/p&gt;

&lt;p&gt;Writing the example starts with setting up some globals. In a real application the globals would be replaced by class or object attributes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$main_thread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;current&lt;/span&gt;
&lt;span class="vg"&gt;$mu&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
&lt;span class="vg"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="vg"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Management and owners
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;$main_thread&lt;/code&gt; and &lt;code&gt;$mu&lt;/code&gt; are used to manage the threads and waiting for completion of the test while the &lt;code&gt;$target&lt;/code&gt; and &lt;code&gt;$count&lt;/code&gt; track the test results. Remember this is a trivial test so collecting and checking results has to be simple.&lt;/p&gt;

&lt;p&gt;The test is started by creating a new instance of the &lt;code&gt;SuitWashScheduler&lt;/code&gt;, giving the initializer the &lt;code&gt;$target&lt;/code&gt; number of iterations. In this case, the 7 suits that need washing.&lt;br&gt;
The block provided will be run in the &lt;code&gt;SuitWashScheduler&lt;/code&gt; thread. For each iteration the &lt;code&gt;$count&lt;/code&gt; is incremented and printed.&lt;/p&gt;

&lt;p&gt;Looking ahead we realize that the main, test thread is going to be checking the&lt;code&gt;$count&lt;/code&gt; also which means it will need ownership of the &lt;code&gt;$count&lt;/code&gt; as well so a means of taking ownership of &lt;code&gt;$count&lt;/code&gt; is needed. The &lt;code&gt;$mu&lt;/code&gt; &lt;code&gt;Mutex&lt;/code&gt; instance is the ownership token. In the block passed to the &lt;code&gt;SuitWashScheduler.new&lt;/code&gt; call a &lt;code&gt;$mu.synchronize&lt;/code&gt; block takes ownership long enough to set the &lt;code&gt;$count&lt;/code&gt; and check the results. More on the results check in a moment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;SuitWashScheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="vg"&gt;$mu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synchronize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="vg"&gt;$count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="vg"&gt;$count&lt;/span&gt;
    &lt;span class="vg"&gt;$main_thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wakeup&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="vg"&gt;$count&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Check: are all suits done?
&lt;/h2&gt;

&lt;p&gt;Back at the main thread we need to wait for the test to finish. Batman needs to wait before all 7 suits are done. There are two conditions to check for; the tests updates the &lt;code&gt;$count&lt;/code&gt; as expected or Batman gets bored waiting for the test to finish and times out. Before checking the &lt;code&gt;$count&lt;/code&gt; to see if it has reached the &lt;code&gt;$target&lt;/code&gt;, the ownership of &lt;code&gt;$count&lt;/code&gt; is needed. Just like in the block for the &lt;code&gt;SuitWashScheduler&lt;/code&gt; a call to &lt;code&gt;$mu.synchronize&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;But that can't be right, if we lock up the main thread how can the &lt;code&gt;SuitWashScheduler&lt;/code&gt; thread ever change the &lt;code&gt;$count&lt;/code&gt;? Luckily for us there is a neat trick that takes care of this. The &lt;code&gt;Mutex&lt;/code&gt; class has a &lt;code&gt;#sleep&lt;/code&gt; method that gives up ownership and waits until either it times out or is woken. Once woken either through the timeout or a &lt;code&gt;#wakeup&lt;/code&gt; call to the main thread &lt;code&gt;$mu&lt;/code&gt; attempts to take ownership again before continuing. Once ownership has been achieved the results can be checked and a determination of the pass or fail state of the test can be made.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$mu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;synchronize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="vg"&gt;$mu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vg"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vg"&gt;$target&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="vg"&gt;$count&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'FAILED'&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'Passed! All suits are washed and clean'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you want to get deeper into this, you can make the example a bit more interesting by trying to create multiple schedulers and see how the Mutex keep the &lt;code&gt;$count&lt;/code&gt; changes from colliding. As if Batman sends some suits to Alfred to be washed, and some others to the dry cleaners. Make sure to change the logic to make sure the &lt;code&gt;$target&lt;/code&gt; check is a total of all the expected yields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roundup
&lt;/h2&gt;

&lt;p&gt;Working with threads and asynchronous environment gets easier with the right mental model.&lt;br&gt;
In this post we used people as a metaphor for threads and physical objects (suits) as metaphor for shared objects, that can only be owned by one thread or person at a time. We think this way to abstract makes it easier to understand and remember.&lt;/p&gt;

&lt;p&gt;We hope the examples with make you remember the mechanisms of async, but we hope the image of Batman running out while all his suits are being washed won’t stick with you for too long.&lt;/p&gt;

&lt;p&gt;PS If you are done with all the batman metaphors on the blog, let us know.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="http://www.ohler.com"&gt;Peter Ohler&lt;/a&gt; creates quite bit of a high performance code, and writes about it too, every now and then. He made the Agoo gem, which is a pretty cool high performance HTTP server.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>learning</category>
      <category>beginners</category>
      <category>testing</category>
    </item>
    <item>
      <title>Push and Pub/Sub in Ruby</title>
      <dc:creator>Peter Ohler</dc:creator>
      <pubDate>Wed, 29 Aug 2018 05:37:39 +0000</pubDate>
      <link>https://dev.to/appsignal/push-and-pubsub-in-ruby-2ie7</link>
      <guid>https://dev.to/appsignal/push-and-pubsub-in-ruby-2ie7</guid>
      <description>&lt;p&gt;Building real time features in Rails has gotten a lot easier to do with libraries like &lt;a href="https://guides.rubyonrails.org/action_cable_overview.html"&gt;Action Cable&lt;/a&gt;. In this episode of &lt;a href="https://blog.appsignal.com/category/academy.html"&gt;AppSignal Academy&lt;/a&gt;, we'll dive into real time updating and toy around with building a minimal WebSocket server to look at how it works under the hood.&lt;/p&gt;

&lt;p&gt;We'll be building an application that &lt;strong&gt;pushes&lt;/strong&gt; data, and uses &lt;strong&gt;Pub/Sub&lt;/strong&gt; over a &lt;strong&gt;WebSocket&lt;/strong&gt;. Before we start on the code, let's first spend a little time covering what those three concepts mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Push&lt;/em&gt;&lt;/strong&gt; refers to pushing data to a receiver instead of having the receiver poll for that data. A must have in realtime updates like stock prices, chat applications, or operations consoles.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Pub/Sub&lt;/em&gt;&lt;/strong&gt; or publish and subscribe is an interaction model for pushing data made popular by TIBCO on Wall Street in the 1990s. A receiver subscribes to a subject and waits for a publisher to push data to that subject. It is common to include wildcard pattern matching to match a published message to a listener, although some simpler implementations only use named channels instead of wildcards in the subject. I got started at TIBCO in those early days so I like the flexibility of the wildcard pattern matching.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;WebSocket&lt;/em&gt;&lt;/strong&gt; is a protocol for exchanging data - usually between a web browser and an application. An HTTP connection is upgraded to a WebSocket connection and then data can be sent both ways between the two endpoints. WebSockets can push data from an application to the browser. It also provides another mechanism other than a POST or PUT for sending data from your JavaScript code in the browser back to the application. Pretty nice, huh?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Under the Hood
&lt;/h2&gt;

&lt;p&gt;Let's look at how an example of a WebSocket server could work. From a browser, the client tries to make a WebSocket connection to a server with JavaScript code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/upgrade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server receives an HTTP request with an indicator that an upgrade was requested. Generally, the server lets an application decide on whether to upgrade or not. How it does that depends on the API provided to the app. A server that supports Rack provides an option to hijack the socket and let the developer handle all the protocol details or, according to a &lt;a href="https://github.com/rack/rack/pull/1272"&gt;proposed PR&lt;/a&gt;, a response to upgrade is enough.&lt;/p&gt;

&lt;p&gt;The upgrade is a set of exchanges between the server and the client. All browsers and some server gems hide these details. Once the connection is established, messages can be exchanged following the WebSocket protocol.&lt;/p&gt;

&lt;p&gt;The magic under the hood handles encoding, decoding, and the message exchange protocol. Messages are binary, fixed-width structures with a trailing payload, encrypted using SHA1. The WebSocket protocol includes several message types and exchanges, like ping/pong heartbeats and opening and closing message exchanges. That's the magic the servers perform by not using the connection-hijack approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Diving In
&lt;/h2&gt;

&lt;p&gt;We'll use the example of a clock thread that is started to publish the current time to all listening clients. We'll use &lt;a href="https://github.com/ohler55/agoo"&gt;Agoo&lt;/a&gt; to build our server because it's fast and keeps the complexity to a minimum.&lt;/p&gt;

&lt;p&gt;We will start out with some JavaScript as a client by showing the current time on an HTML page. After creating a new &lt;code&gt;WebSocket&lt;/code&gt; an &lt;code&gt;onopen&lt;/code&gt; callback is set that changes the status HTML element. The &lt;code&gt;onmessage&lt;/code&gt; callback updates the &lt;code&gt;message&lt;/code&gt; HTML element. Callbacks are a common design pattern when working with asynchronous calls such as publish and subscribe exchanges.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- websocket.html --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; ... &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt; ... waiting ... &lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text/javascript"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ws://&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/upgrade&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onopen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onmessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With our client done, let's implement the server, which is a Ruby application using the Rack API. The &lt;code&gt;Clock&lt;/code&gt; class itself will be a handler for all HTTP requests on the &lt;code&gt;/upgrade&lt;/code&gt; path. If the request is for an upgrade we simply return Success with an HTTP status code of 200, otherwise, we return a 404 for Page Not Found. The only other step in the &lt;code&gt;#call&lt;/code&gt; method is the assignment of the WebSocket handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Clock&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'rack.upgrade?'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
      &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'rack.upgrade'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Clock&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API is based on callbacks. The only callback we care about for our server is the &lt;code&gt;#on_open&lt;/code&gt; callback which enables us to create a subscription to the "time" subject. Messages are exchanged over channels identified by subjects or topics. &lt;code&gt;#on_open&lt;/code&gt; is called when a web socket connection is established.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Clock&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on_open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's start publishing with a thread that publishes the time after every second. The call to &lt;code&gt;Agoo.publish&lt;/code&gt; sends a message on the "time" subject, then all subscribers receive the message. The server keeps track of the subscriptions and connections and delivers the message to the JavaScript client which updates the HTML element.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'agoo'&lt;/span&gt;

&lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;
    &lt;span class="no"&gt;Agoo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'time'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"%02d:%02d:%02d"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sec&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nb"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only other code needed is the code that initializes and starts the server. The call to &lt;code&gt;Agoo::Server.handle(:GET, '/upgrade', Clock)&lt;/code&gt; tells the server to listen for HTTP GET requests on the &lt;code&gt;/upgrade&lt;/code&gt; URL path and to pass those requests to the &lt;code&gt;Clock&lt;/code&gt; class. This allows the routing to occur outside Ruby for improved performance and flexibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Agoo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6464&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;thread_count: &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Agoo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:GET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/upgrade'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="no"&gt;Agoo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are almost there. Run the server with this command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ruby pubsub.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A log entry should appear showing something like the following, indicating that the server is running and listening on port 6464.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I 2018/08/14 19:49:45.170618000 INFO: Agoo 2.5.0 with pid 40366 is listening on http://:6464.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Time To See If It's Working
&lt;/h2&gt;

&lt;p&gt;Let's open &lt;a href="http://localhost:6464/websocket.html"&gt;http://localhost:6464/websocket.html&lt;/a&gt;. After an initial flicker as a connection is established, the connection status and the time should be displayed. The time will increment every second as the clock ticks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connected

19:50:12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations on making a publish and subscribe web application ;-)&lt;/p&gt;

&lt;p&gt;In today's episode, we looked at using WebSocket. Server Side Events (SSE) offers another option of doing the same, and we have included SSE in the &lt;a href="https://github.com/ohler55/agoo/blob/master/example/push/pubsub.rb"&gt;full source code example&lt;/a&gt;. If you want to find out more, take a look at the &lt;a href="https://github.com/ohler55/agoo"&gt;Agoo&lt;/a&gt; server we used or &lt;a href="https://github.com/boazsegev/iodine"&gt;Iodine&lt;/a&gt; WebSocket Server. &lt;/p&gt;

&lt;p&gt;We'd love to know what you thought of this article, or if you have any questions. We're always on the lookout for topics to investigate and explain, so if there's anything magical in Ruby you'd like to read about, don't hesitate to leave a comment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is written by guest author &lt;a href="http://www.ohler.com"&gt;Peter Ohler&lt;/a&gt;. Peter creates quite bit of a high performance code, and writes about it too, every now and then. He made the Agoo gem, which is a pretty cool high performance HTTP server.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>learning</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
