{"id":48362,"date":"2013-02-11T14:00:51","date_gmt":"2013-02-11T11:00:51","guid":{"rendered":"https:\/\/www.altoros.com\/blog\/?p=48362"},"modified":"2022-01-03T15:50:02","modified_gmt":"2022-01-03T12:50:02","slug":"using-couchbase-ruby-gem-with-eventmachine","status":"publish","type":"post","link":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/","title":{"rendered":"Using the Couchbase Ruby Gem with EventMachine"},"content":{"rendered":"<p>As you might have noticed, the new <a href=\"https:\/\/rubygems.org\/gems\/couchbase\" rel=\"noopener noreferrer\" target=\"_blank\">Couchbase Ruby gem<\/a> has been released. Version 1.2.2 is mostly a maintenance release with several bug fixes. Yet, you can try a new experimental feature\u2014integration with the <a href=\"https:\/\/rubygems.org\/gems\/eventmachine\" rel=\"noopener noreferrer\" target=\"_blank\">EventMachine<\/a> library. Currently, the EventMachine integration is only accessible on UNIX-like systems (such as Linux, Solaris, and BSD). As the integration uses fibers, it also requires Ruby MRI version 1.9 or later.<\/p>\n<p>This blog post provides a quick intro of how to start using <a href=\"https:\/\/www.couchbase.com\/products\/server\" rel=\"noopener noreferrer\" target=\"_blank\">Couchbase Server<\/a> in your Ruby apps based on the EventMachine asynchronous model.<\/p>\n<p>&nbsp;<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-transparent ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#Set_up_your_sandbox\" >Set up your sandbox<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#Building_the_app\" >Building the app<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#Bonus_points\" >Bonus points<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#Further_reading\" >Further reading<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#About_the_author\" >About the author<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"Set_up_your_sandbox\"><\/span>Set up your sandbox<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The first step is to install the <a href=\"https:\/\/github.com\/couchbase\/libcouchbase\" rel=\"noopener noreferrer\" target=\"_blank\">libcouchbase<\/a> library that handles all low-level Couchbase protocol details. You can check out the <a href=\"https:\/\/docs.couchbase.com\/c-sdk\/2.10\/client-settings.html\" rel=\"noopener noreferrer\" target=\"_blank\">official installation guide<\/a>. Below, I\u2019ll only replicate the steps needed for a typical GNU\/Linux box (I\u2019m using Debian unstable).<\/p>\n<ol>\n<li style=\"margin-bottom: 6px;\">Install a repository PGP key.<\/li>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>$ wget -O- http:\/\/packages.couchbase.com\/ubuntu\/couchbase.key | sudo apt-key add -\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<li style=\"margin-bottom: 6px;\">Set up a repository source. Here, I\u2019m using the link for Ubuntu 12.04. In general, however, it doesn\u2019t matter, because we are going to use the EventMachine plugin that is built into the gem itself. The packages in different repositories are built using the same codebase with the only difference in versions of IO libraries (<a href=\"http:\/\/libevent.org\" rel=\"noopener noreferrer\" target=\"_blank\">libevent<\/a> and <a href=\"http:\/\/software.schmorp.de\/pkg\/libev.html\" rel=\"noopener noreferrer\" target=\"_blank\">libev<\/a>).<\/li>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>$ sudo wget -O\/etc\/apt\/sources.list.d\/couchbase.list http:\/\/packages.couchbase.com\/ubuntu\/couchbase-ubuntu1204.list\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<li style=\"margin-bottom: 6px;\">Install <code style=\"color: black; background-color: #e6e6e6;\">libcouchbase<\/code> headers, a core library, and debug symbols. Again, you might want to install command-line tools or one of the IO backends, but they are optional for our current task.<\/li>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>$ sudo apt-get update\r\n$ sudo sudo apt-get install libcouchbase-dev libcouchbase2-core libcouchbase-dbg\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<li style=\"margin-bottom: 6px;\">Now, you need to install Couchbase Server. For the purpose, follow the <a href=\"https:\/\/www.couchbase.com\/downloads\" rel=\"noopener noreferrer\" target=\"_blank\">official instructions<\/a>. After installation, you will get an administrator console running at http:\/\/localhost:8091 and the REST API accessible on the same port. Go through initial configuration steps, and, eventually, you will allocate a bucket with the <b>default<\/b> name.<\/li>\n<li style=\"margin-bottom: 6px;\">Finally, you need to install the gem itself. It is as easy as type the following command into the terminal.<\/li>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>$ gem install couchbase\r\nBuilding native extensions.  This could take a while...\r\nSuccessfully installed couchbase-1.2.2\r\n1 gem installed\r\nInstalling ri documentation for couchbase-1.2.2...\r\nInstalling RDoc documentation for couchbase-1.2.2...\r\n<\/code><\/pre>\n<\/div><\/div>\n<\/ol>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Building_the_app\"><\/span>Building the app<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>To demonstrate the integration, let&#8217;s build a simple chat application using EventMachine and add logging for all events to the Couchbase bucket. It is extremely easy to build an asynchronous application with EventMachine. To prove it, I will put a complete source code in this blog post. The code can be also found in the <a href=\"https:\/\/github.com\/couchbase\/couchbase-ruby-client\/tree\/master\/examples\/chat-em\" rel=\"noopener noreferrer\" target=\"_blank\">examples\/chat-em<\/a> directory of the gem sources.<\/p>\n<figure class=\"highlight\">\n<pre><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"k\">class<\/span> <span class=\"nc\">ChatServer<\/span> <span class=\"o\">&lt;<\/span> <span class=\"no\">EM<\/span><span class=\"o\">::<\/span><span class=\"no\">Connection<\/span>\r\n\r\n  <span class=\"vc\">@@clients<\/span> <span class=\"o\">=<\/span> <span class=\"p\">[]<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">post_init<\/span>\r\n    <span class=\"vi\">@username<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span>\r\n    <span class=\"n\">send_data<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"*** What is your name?<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">receive_data<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"vi\">@username<\/span>\r\n      <span class=\"n\">broadcast<\/span><span class=\"p\">(<\/span><span class=\"n\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">strip<\/span><span class=\"p\">,<\/span> <span class=\"vi\">@username<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">else<\/span>\r\n      <span class=\"nb\">name<\/span> <span class=\"o\">=<\/span> <span class=\"n\">data<\/span><span class=\"p\">.<\/span><span class=\"nf\">gsub<\/span><span class=\"p\">(<\/span><span class=\"sr\">\/\\s+|[\\[\\]]\/<\/span><span class=\"p\">,<\/span> <span class=\"s1\">''<\/span><span class=\"p\">).<\/span><span class=\"nf\">strip<\/span><span class=\"p\">[<\/span><span class=\"mi\">0<\/span><span class=\"o\">..<\/span><span class=\"mi\">20<\/span><span class=\"p\">]<\/span>\r\n      <span class=\"k\">if<\/span> <span class=\"nb\">name<\/span><span class=\"p\">.<\/span><span class=\"nf\">empty?<\/span>\r\n        <span class=\"n\">send_data<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"*** What is your name?<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">else<\/span>\r\n        <span class=\"vi\">@username<\/span> <span class=\"o\">=<\/span> <span class=\"nb\">name<\/span>\r\n        <span class=\"vc\">@@clients<\/span><span class=\"p\">.<\/span><span class=\"nf\">push<\/span><span class=\"p\">(<\/span><span class=\"nb\">self<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">broadcast<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@username<\/span><span class=\"si\">}<\/span><span class=\"s2\"> has joined\"<\/span><span class=\"p\">)<\/span>\r\n        <span class=\"n\">send_data<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"*** Hi, <\/span><span class=\"si\">#{<\/span><span class=\"vi\">@username<\/span><span class=\"si\">}<\/span><span class=\"s2\">!<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">unbind<\/span>\r\n    <span class=\"vc\">@@clients<\/span><span class=\"p\">.<\/span><span class=\"nf\">delete<\/span><span class=\"p\">(<\/span><span class=\"nb\">self<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">broadcast<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@username<\/span><span class=\"si\">}<\/span><span class=\"s2\"> has left\"<\/span><span class=\"p\">)<\/span> <span class=\"k\">if<\/span> <span class=\"vi\">@username<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n  <span class=\"k\">def<\/span> <span class=\"nf\">broadcast<\/span><span class=\"p\">(<\/span><span class=\"n\">message<\/span><span class=\"p\">,<\/span> <span class=\"n\">author<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"n\">prefix<\/span> <span class=\"o\">=<\/span> <span class=\"n\">author<\/span> <span class=\"p\">?<\/span> <span class=\"s2\">\"&lt;<\/span><span class=\"si\">#{<\/span><span class=\"vi\">@username<\/span><span class=\"si\">}<\/span><span class=\"s2\">&gt;\"<\/span> <span class=\"p\">:<\/span> <span class=\"s2\">\"***\"<\/span>\r\n    <span class=\"vc\">@@clients<\/span><span class=\"p\">.<\/span><span class=\"nf\">each<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">client<\/span><span class=\"o\">|<\/span>\r\n      <span class=\"k\">unless<\/span> <span class=\"n\">client<\/span> <span class=\"o\">==<\/span> <span class=\"nb\">self<\/span>\r\n        <span class=\"n\">client<\/span><span class=\"p\">.<\/span><span class=\"nf\">send_data<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"<\/span><span class=\"si\">#{<\/span><span class=\"n\">prefix<\/span><span class=\"si\">}<\/span><span class=\"s2\"> <\/span><span class=\"si\">#{<\/span><span class=\"n\">message<\/span><span class=\"si\">}<\/span><span class=\"se\">\\n<\/span><span class=\"s2\">\"<\/span><span class=\"p\">)<\/span>\r\n      <span class=\"k\">end<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n\r\n<span class=\"k\">end<\/span>\r\n\r\n<span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">run<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"c1\"># hit Control + C to stop<\/span>\r\n  <span class=\"no\">Signal<\/span><span class=\"p\">.<\/span><span class=\"nf\">trap<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"INT\"<\/span><span class=\"p\">)<\/span>  <span class=\"p\">{<\/span> <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">stop<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"no\">Signal<\/span><span class=\"p\">.<\/span><span class=\"nf\">trap<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"TERM\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">stop<\/span> <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">start_server<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"0.0.0.0\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9999<\/span><span class=\"p\">,<\/span> <span class=\"no\">ChatServer<\/span><span class=\"p\">)<\/span>\r\n<span class=\"k\">end<\/span><\/code><\/pre>\n<\/figure>\n<p>This is a typical EventMachine server based on <code style=\"color: black; background-color: #e6e6e6;\">EM::Connection<\/code>. For those who don&#8217;t know the meaning of these redefined methods, below, I will provide an exceprt from the <a href=\"http:\/\/eventmachine.rubyforge.org\/EventMachine\/Connection.html\" rel=\"noopener noreferrer\" target=\"_blank\">official documentation<\/a>.<\/p>\n<blockquote>\n<p><code style=\"color: black; background-color: #e6e6e6;\">EventMachine::Connection<\/code> is a class that is instantiated by EventMachine\u2019s processing loop whenever a new connection is created. New connections can be either initiated locally to a remote server or accepted locally from a remote client. When the Connection object is instantiated, it mixes in the functionality contained in the user-defined module specified in calls to connect or <code style=\"color: black; background-color: #e6e6e6;\">start_server<\/code>. User-defined handler modules may redefine any or all of the standard methods defined here, as well as add arbitrary additional code that will also be mixed in.<\/p>\n<p>EventMachine manages a single object inherited from <code style=\"color: black; background-color: #e6e6e6;\">EventMachine::Connection<\/code> (and containing the mixed-in user code) for every network connection that is active at any given time. The event loop will automatically call methods on <code style=\"color: black; background-color: #e6e6e6;\">EventMachine::Connection<\/code> objects whenever specific events occur on the corresponding connections as described below.<\/p>\n<p>This class is never instantiated by user code and does not publish an initialize method. The instance methods of <code style=\"color: black; background-color: #e6e6e6;\">EventMachine::Connection<\/code> that may be called by the event loop are as follows: <code style=\"color: black; background-color: #e6e6e6;\">#post_init<\/code>, <code style=\"color: black; background-color: #e6e6e6;\">#connection_completed<\/code>, <code style=\"color: black; background-color: #e6e6e6;\">#receive_data<\/code>, <code style=\"color: black; background-color: #e6e6e6;\">#unbind<\/code>, <code style=\"color: black; background-color: #e6e6e6;\">#ssl_verify_peer<\/code> (if TLS is used), and <code style=\"color: black; background-color: #e6e6e6;\">#ssl_handshake_completed<\/code>.<\/p>\n<p>All other instance methods defined here are called only by user code.<\/p>\n<\/blockquote>\n<p>The protocol is very simple and line-oriented. For each connection, EventMachine will create an instance of <code style=\"color: black; background-color: #e6e6e6;\">ChatServer<\/code> that first asks the name of a new participant and then broadcasts all the messages to the group. You can use your favorite tool, such as <code style=\"color: black; background-color: #e6e6e6;\">telnet<\/code> or <code style=\"color: black; background-color: #e6e6e6;\">nc<\/code>, that allows you to communicate over the arbitrary text protocol. Below is a sample of the session between endpoints.<\/p>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>~ $ telnet localhost 9999           \u2502 ~ $ nc localhost 9999\r\nTrying 127.0.0.1...                 \u2502 *** What is your name?\r\nConnected to localhost.             \u2502 alice\r\nEscape character is '^]'.           \u2502 *** Hi, alice!\r\n*** What is your name?              \u2502 *** bob has joined\r\nbob                                 \u2502 &lt;bob&gt; hi everyone\r\n*** Hi, bob!                        \u2502 hello, bob! how are you?\r\nhi everyone                         \u2502 ^C\r\n&lt;alice&gt; hello, bob! how are you?    \u2502 ~ $\r\n*** alice has left                  \u2502\r\n^]                                  \u2502\r\ntelnet&gt; Connection closed.          \u2502\r\n~ $                                 \u2502\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Now, it\u2019s time to add a bit of Couchbase. Imagine I\u2019d like to keep all the messages in a <a href=\"https:\/\/www.couchbase.com\/resources\/why-nosql\" rel=\"noopener noreferrer\" target=\"_blank\">distributed database<\/a> as efficiently as I can. Couchbase is the answer. For the purpose, I need to perform the following steps:<\/p>\n<ol>\n<li style=\"margin-bottom: 6px;\">Implement the <code style=\"color: black; background-color: #e6e6e6;\">log<\/code> method in the <code style=\"color: black; background-color: #e6e6e6;\">ChatServer<\/code> class that should accept a message and an optional author (for system events, it will be <code style=\"color: black; background-color: #e6e6e6;\">nil<\/code>).<\/li>\n<figure class=\"highlight\">\n<pre><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"k\">def<\/span> <span class=\"nf\">log<\/span><span class=\"p\">(<\/span><span class=\"n\">message<\/span><span class=\"p\">,<\/span> <span class=\"n\">author<\/span> <span class=\"o\">=<\/span> <span class=\"kp\">nil<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"no\">Couchbase<\/span><span class=\"p\">.<\/span><span class=\"nf\">bucket<\/span><span class=\"p\">.<\/span><span class=\"nf\">incr<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"log:key\"<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:initial<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"mi\">1<\/span><span class=\"p\">)<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">res<\/span><span class=\"o\">|<\/span>\r\n    <span class=\"n\">entry<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"s1\">'time'<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"no\">Time<\/span><span class=\"p\">.<\/span><span class=\"nf\">now<\/span><span class=\"p\">.<\/span><span class=\"nf\">utc<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"s1\">'author'<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">author<\/span> <span class=\"o\">||<\/span> <span class=\"s2\">\"[system]\"<\/span><span class=\"p\">,<\/span>\r\n      <span class=\"s1\">'message'<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"n\">message<\/span>\r\n    <span class=\"p\">}<\/span>\r\n    <span class=\"no\">Couchbase<\/span><span class=\"p\">.<\/span><span class=\"nf\">bucket<\/span><span class=\"p\">.<\/span><span class=\"nf\">set<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"log:<\/span><span class=\"si\">#{<\/span><span class=\"n\">res<\/span><span class=\"p\">.<\/span><span class=\"nf\">value<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span><span class=\"p\">,<\/span> <span class=\"n\">entry<\/span><span class=\"p\">)<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span><\/code><\/pre>\n<\/figure>\n<li style=\"margin-bottom: 6px;\">Add a call to <code style=\"color: black; background-color: #e6e6e6;\">log(message, author)<\/code> in the broadcast method just before iterating all connected clients. Then wrap the <code style=\"color: black; background-color: #e6e6e6;\">EventMachine.start_server<\/code> with the <code style=\"color: black; background-color: #e6e6e6;\">Couchbase::Bucket#on_connect<\/code> callback to execute the server just after the client was connected. The resulting loop execution will look like this.<\/li>\n<figure class=\"highlight\">\n<pre><code class=\"language-ruby\" data-lang=\"ruby\"><span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">run<\/span> <span class=\"k\">do<\/span>\r\n  <span class=\"c1\"># hit Control + C to stop<\/span>\r\n  <span class=\"no\">Signal<\/span><span class=\"p\">.<\/span><span class=\"nf\">trap<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"INT\"<\/span><span class=\"p\">)<\/span>  <span class=\"p\">{<\/span> <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">stop<\/span> <span class=\"p\">}<\/span>\r\n  <span class=\"no\">Signal<\/span><span class=\"p\">.<\/span><span class=\"nf\">trap<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"TERM\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span> <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">stop<\/span> <span class=\"p\">}<\/span>\r\n\r\n  <span class=\"no\">Couchbase<\/span><span class=\"p\">.<\/span><span class=\"nf\">connection_options<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><span class=\"ss\">:async<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"kp\">true<\/span><span class=\"p\">,<\/span> <span class=\"ss\">:engine<\/span> <span class=\"o\">=&gt;<\/span> <span class=\"ss\">:eventmachine<\/span><span class=\"p\">}<\/span>\r\n  <span class=\"no\">Couchbase<\/span><span class=\"p\">.<\/span><span class=\"nf\">bucket<\/span><span class=\"p\">.<\/span><span class=\"nf\">on_connect<\/span> <span class=\"k\">do<\/span> <span class=\"o\">|<\/span><span class=\"n\">res<\/span><span class=\"o\">|<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"n\">res<\/span><span class=\"p\">.<\/span><span class=\"nf\">success?<\/span>\r\n      <span class=\"no\">EventMachine<\/span><span class=\"p\">.<\/span><span class=\"nf\">start_server<\/span><span class=\"p\">(<\/span><span class=\"s2\">\"0.0.0.0\"<\/span><span class=\"p\">,<\/span> <span class=\"mi\">9999<\/span><span class=\"p\">,<\/span> <span class=\"no\">ChatServer<\/span><span class=\"p\">)<\/span>\r\n    <span class=\"k\">else<\/span>\r\n      <span class=\"nb\">puts<\/span> <span class=\"s2\">\"Cannot connect to Couchbase Server: <\/span><span class=\"si\">#{<\/span><span class=\"n\">res<\/span><span class=\"p\">.<\/span><span class=\"nf\">error<\/span><span class=\"si\">}<\/span><span class=\"s2\">\"<\/span>\r\n    <span class=\"k\">end<\/span>\r\n  <span class=\"k\">end<\/span>\r\n<span class=\"k\">end<\/span><\/code><\/pre>\n<\/figure>\n<\/ol>\n<p>That\u2019s it for now! In the future, we can expand this example to use more modern techniques, such as <a href=\"https:\/\/github.com\/igrigorik\/em-synchrony\/\" rel=\"noopener noreferrer\" target=\"_blank\">em-synchrony<\/a> and <a href=\"https:\/\/www.altoros.com\/blog\/websocket-rails-gem\/\">WebSocket<\/a>. Follow <a href=\"http:\/\/blog.couchbase.com\" rel=\"noopener noreferrer\" target=\"_blank\">this blog<\/a> for updates.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Bonus_points\"><\/span>Bonus points<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Logging itself might not be that interesting. With Couchbase Server, you can perform simple analytics with <b>View<\/b> queries using Couchbase\u2019s incremental &#8216;Map-Reduce&#8217; awesomeness. For example, below is the <code style=\"color: black; background-color: #e6e6e6;\">Map<\/code> function used to get all entries in a chronological order.<\/p>\n<figure class=\"highlight\">\n<pre><code class=\"language-javascript\" data-lang=\"javascript\"><span class=\"kd\">function<\/span> <span class=\"p\">(<\/span><span class=\"nx\">doc<\/span><span class=\"p\">,<\/span> <span class=\"nx\">meta<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n  <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n    <span class=\"k\">if<\/span> <span class=\"p\">(<\/span><span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">author<\/span> <span class=\"o\">==<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">[system]<\/span><span class=\"dl\">\"<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">emit<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">time<\/span><span class=\"p\">),<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">*** <\/span><span class=\"dl\">\"<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">);<\/span>\r\n    <span class=\"p\">}<\/span> <span class=\"k\">else<\/span> <span class=\"p\">{<\/span>\r\n      <span class=\"nx\">emit<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"nb\">Date<\/span><span class=\"p\">(<\/span><span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">time<\/span><span class=\"p\">),<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">&lt;<\/span><span class=\"dl\">\"<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">author<\/span> <span class=\"o\">+<\/span> <span class=\"dl\">\"<\/span><span class=\"s2\">&gt; <\/span><span class=\"dl\">\"<\/span> <span class=\"o\">+<\/span> <span class=\"nx\">doc<\/span><span class=\"p\">.<\/span><span class=\"nx\">message<\/span><span class=\"p\">);<\/span>\r\n    <span class=\"p\">}<\/span>\r\n  <span class=\"p\">}<\/span>\r\n<span class=\"p\">}<\/span><\/code><\/pre>\n<\/figure>\n<p>Below is the JSON output.<\/p>\n<div style=\"color: black; background-color: #e6e6e6;\">\n<div class=\"highlight\">\n<pre class=\"highlight\"><code>{\"total_rows\":6,\"rows\":[\r\n  {\"id\":\"log:1\",\"key\":\"2013-02-11T19:08:05.000Z\",\"value\":\"*** alice has joined\"},\r\n  {\"id\":\"log:2\",\"key\":\"2013-02-11T19:08:18.000Z\",\"value\":\"*** bob has joined\"},\r\n  {\"id\":\"log:3\",\"key\":\"2013-02-11T19:08:38.000Z\",\"value\":\"<bob> hi everyone\"},\r\n  {\"id\":\"log:4\",\"key\":\"2013-02-11T19:08:48.000Z\",\"value\":\"<alice> hello, bob! how are you?\"},\r\n  {\"id\":\"log:5\",\"key\":\"2013-02-11T19:08:58.000Z\",\"value\":\"*** alice has left\"},\r\n  {\"id\":\"log:6\",\"key\":\"2013-02-11T19:09:01.000Z\",\"value\":\"*** bob has left\"}\r\n]}\r\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>Okay, that\u2019s really it for now. Enjoy this experimental new feature. It\u2019ll be fully supported in a future release. If you run into any trouble, please file an issue at the <a href=\"https:\/\/issues.couchbase.com\/browse\/RCBC\" rel=\"noopener noreferrer\" target=\"_blank\">RCBC project issue tracker<\/a>. Fixes and contributions are always welcome, as well. The feature is open-sourced under the Apache 2.0 License. You\u2019ll find the <a href=\"https:\/\/github.com\/couchbase\/couchbase-ruby-client\/\" rel=\"noopener noreferrer\" target=\"_blank\"> code sources<\/a> on GitHub. You can also check the original article at the <a href=\"https:\/\/blog.couchbase.com\/using-couchbase-ruby-gem-eventmachine\/\" rel=\"noopener noreferrer\" target=\"_blank\">Couchbase blog<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"Further_reading\"><\/span>Further reading<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<ul>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/nosql-performance-benchmark-2019-couchbase-server-v6-0-datastax-enterprise-v6-7-cassandra-and-mongodb-v4-0\/\">Technical NoSQL Comparison Report 2019: Couchbase Server v6.0, DataStax Enterprise v6.7 (Cassandra), and MongoDB v4.0<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/performance-evaluation-of-nosql-databases-with-ycsb-couchbase-server-datastax-enterprise-cassandra-and-mongodb\/\">Performance Evaluation of NoSQL Databases 2021: Couchbase Server, DataStax Enterprise (Cassandra), and MongoDB<\/a><\/li>\n<li><a href=\"https:\/\/www.altoros.com\/research-papers\/mongodb-vs-couchbase-server-architectural-differences-and-their-impact\/\">MongoDB vs. Couchbase Server: Architectural Differences and Their Impact<\/a><\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<h3><span class=\"ez-toc-section\" id=\"About_the_author\"><\/span>About the author<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/sergey-avseyev.png\" width=\"110\" class=\"alignright size-thumbnail wp-image-64162\" \/><\/p>\n<p><small><a href=\"https:\/\/www.linkedin.com\/in\/avsej\/\" rel=\"noopener noreferrer\" target=\"_blank\">Sergey Avseyev<\/a> likes to analyze, design, develop, and maintain server-side applications and user interfaces. He is experienced in ANSI C, Ruby, and JavaScript, etc. Sergey also works with relational databases, such as PostgreSQL and MySQL server. Find him on <a href=\"https:\/\/github.com\/avsej\" rel=\"noopener noreferrer\" target=\"_blank\">GitHub<\/a>.<\/small><\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to integrate your EventMachine application with couchbase ruby gem<\/p>\n","protected":false},"author":34,"featured_media":58416,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"content-type":"","footnotes":"","_links_to":"","_links_to_target":""},"categories":[214],"tags":[1000,692,895],"class_list":["post-48362","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-github","tag-nosql","tag-research-and-development"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Using the Couchbase Ruby Gem with EventMachine | Altoros<\/title>\n<meta name=\"description\" content=\"Explore how to start using Couchbase Server in your Ruby apps based on the EventMachine asynchronous model.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using the Couchbase Ruby Gem with EventMachine | Altoros\" \/>\n<meta property=\"og:description\" content=\"How to integrate your EventMachine application with couchbase ruby gem\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/\" \/>\n<meta property=\"og:site_name\" content=\"Altoros\" \/>\n<meta property=\"article:published_time\" content=\"2013-02-11T11:00:51+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-01-03T12:50:02+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"576\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alena Vasilenko\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alena Vasilenko\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/\",\"name\":\"Using the Couchbase Ruby Gem with EventMachine | Altoros\",\"isPartOf\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png\",\"datePublished\":\"2013-02-11T11:00:51+00:00\",\"dateModified\":\"2022-01-03T12:50:02+00:00\",\"author\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/019e8147b835bc8f1b4abd8a4fa42c7f\"},\"description\":\"How to integrate your EventMachine application with couchbase ruby gem\",\"breadcrumb\":{\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png\",\"width\":1024,\"height\":576},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.altoros.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using the Couchbase Ruby Gem with EventMachine\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#website\",\"url\":\"https:\/\/www.altoros.com\/blog\/\",\"name\":\"Altoros\",\"description\":\"Insight\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.altoros.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/019e8147b835bc8f1b4abd8a4fa42c7f\",\"name\":\"Alena Vasilenko\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/alena-vasilenko-author-e1561752194994-96x96.jpg\",\"contentUrl\":\"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/alena-vasilenko-author-e1561752194994-96x96.jpg\",\"caption\":\"Alena Vasilenko\"},\"description\":\"Alena Vasilenko is Communications Manager at Altoros. She has proven track record of supporting R&amp;D engineers in their research activities on such topics as big data and cloud computing, translating the research results into easy-to-understand stories.\",\"url\":\"https:\/\/www.altoros.com\/blog\/author\/alena-vasilenko\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using the Couchbase Ruby Gem with EventMachine | Altoros","description":"Explore how to start using Couchbase Server in your Ruby apps based on the EventMachine asynchronous model.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/","og_locale":"en_US","og_type":"article","og_title":"Using the Couchbase Ruby Gem with EventMachine | Altoros","og_description":"How to integrate your EventMachine application with couchbase ruby gem","og_url":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/","og_site_name":"Altoros","article_published_time":"2013-02-11T11:00:51+00:00","article_modified_time":"2022-01-03T12:50:02+00:00","og_image":[{"width":1024,"height":576,"url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png","type":"image\/png"}],"author":"Alena Vasilenko","twitter_misc":{"Written by":"Alena Vasilenko","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/","url":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/","name":"Using the Couchbase Ruby Gem with EventMachine | Altoros","isPartOf":{"@id":"https:\/\/www.altoros.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage"},"image":{"@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage"},"thumbnailUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png","datePublished":"2013-02-11T11:00:51+00:00","dateModified":"2022-01-03T12:50:02+00:00","author":{"@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/019e8147b835bc8f1b4abd8a4fa42c7f"},"description":"How to integrate your EventMachine application with couchbase ruby gem","breadcrumb":{"@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#primaryimage","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2013\/02\/using-the-couchbase-ruby-gem-with-eventmachine-featured-image.png","width":1024,"height":576},{"@type":"BreadcrumbList","@id":"https:\/\/www.altoros.com\/blog\/using-couchbase-ruby-gem-with-eventmachine\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.altoros.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Using the Couchbase Ruby Gem with EventMachine"}]},{"@type":"WebSite","@id":"https:\/\/www.altoros.com\/blog\/#website","url":"https:\/\/www.altoros.com\/blog\/","name":"Altoros","description":"Insight","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.altoros.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/019e8147b835bc8f1b4abd8a4fa42c7f","name":"Alena Vasilenko","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.altoros.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/alena-vasilenko-author-e1561752194994-96x96.jpg","contentUrl":"https:\/\/www.altoros.com\/blog\/wp-content\/uploads\/2019\/06\/alena-vasilenko-author-e1561752194994-96x96.jpg","caption":"Alena Vasilenko"},"description":"Alena Vasilenko is Communications Manager at Altoros. She has proven track record of supporting R&amp;D engineers in their research activities on such topics as big data and cloud computing, translating the research results into easy-to-understand stories.","url":"https:\/\/www.altoros.com\/blog\/author\/alena-vasilenko\/"}]}},"_links":{"self":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/48362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/users\/34"}],"replies":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/comments?post=48362"}],"version-history":[{"count":22,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/48362\/revisions"}],"predecessor-version":[{"id":66003,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/posts\/48362\/revisions\/66003"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media\/58416"}],"wp:attachment":[{"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/media?parent=48362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/categories?post=48362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.altoros.com\/blog\/wp-json\/wp\/v2\/tags?post=48362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}