<?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: Jeremy Pollock</title>
    <description>The latest articles on DEV Community by Jeremy Pollock (@jpollock).</description>
    <link>https://dev.to/jpollock</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%2F699807%2F6c050d7a-f8b2-4389-8e15-d782f7ade243.jpeg</url>
      <title>DEV Community: Jeremy Pollock</title>
      <link>https://dev.to/jpollock</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jpollock"/>
    <language>en</language>
    <item>
      <title>Postman-powered testing of Akka Serverless gRPC APIs</title>
      <dc:creator>Jeremy Pollock</dc:creator>
      <pubDate>Thu, 06 Jan 2022 13:39:57 +0000</pubDate>
      <link>https://dev.to/jpollock/postman-powered-testing-of-akka-serverless-grpc-apis-24ha</link>
      <guid>https://dev.to/jpollock/postman-powered-testing-of-akka-serverless-grpc-apis-24ha</guid>
      <description>&lt;p&gt;Over the holidays, 2021, &lt;a href="https://www.postman.com/"&gt;Postman&lt;/a&gt; gifted a fine upgrade to its users: beta support for the gRPC protocol in its API platform. As a Product Manager for Lightbend and helping out on its new gRPC native PaaS for building and running APIs and microservices, I was excited, to say the least. In another, recent blog &lt;a href="https://dev.to/jpollock/grpc-test-and-try-with-akka-serverless-and-evans-5gcc"&gt;post&lt;/a&gt;, I mentioned my desire to leverage UI test-and-try tools for APIs (my time in the REST API world of Mashery and PubNub was the source of such desire). In that same post though, I noted the lack of several important gRPC features, like server reflection and more robust import capabilities, as blockers; hence, my deep dive, in that post, into the CLI tool, &lt;a href="https://github.com/ktr0731/evans"&gt;Evans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But just because one builds APIs and services in Akka Serverless, using gRPC as a first class citizen, doesn't mean that one has to rely solely on gRPC tooling. When running your logic on this serverless platform, you can access your developed, and running, APIs through direct HTTP requests. The product has an "always-on" feature called &lt;em&gt;HTTP transcoding&lt;/em&gt;, and its default behaviour is to expose every gRPC method as a &lt;code&gt;POST&lt;/code&gt; request to a &lt;code&gt;URI&lt;/code&gt; of &lt;code&gt;/&amp;lt;fully qualified service name&amp;gt;/&amp;lt;method name&amp;gt;&lt;/code&gt; , with that resource accepting a JSON representation of the full protobuf message. One simply has to look at their API definitions, as captured in a &lt;code&gt;protobuf&lt;/code&gt; to get the URIs that are needed. Let's check out what that really means!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you just want to go make some API calls in Postman, you can access the demo collection using the below:&lt;br&gt;
&lt;a href="https://app.getpostman.com/run-collection/34862-3e1b7880-536c-41f9-a97b-8b1bef5cd88e?action=collection%2Ffork&amp;amp;collection-url=entityId%3D34862-3e1b7880-536c-41f9-a97b-8b1bef5cd88e%26entityType%3Dcollection%26workspaceId%3Ddee50495-76e5-4399-afea-21035ae2759d"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V37vEqA7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://run.pstmn.io/button.svg" alt="Run in Postman" width="123" height="30"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Parsing out URIs from a protobuf
&lt;/h2&gt;

&lt;p&gt;Ready to parse, human? To read through a possibly strangely constructed file and deduce &lt;code&gt;URIs&lt;/code&gt; that match the above format of &lt;code&gt;/&amp;lt;fully qualified service name&amp;gt;/&amp;lt;method name&amp;gt;&lt;/code&gt;? Well, even if you're not, let's learn!&lt;/p&gt;

&lt;p&gt;Below is a &lt;code&gt;protobuf&lt;/code&gt; file. If you have no idea what &lt;code&gt;protobuf&lt;/code&gt; is, you might want to check out this site: &lt;a href="https://developers.google.com/protocol-buffers"&gt;https://developers.google.com/protocol-buffers&lt;/a&gt;.  For purposes of this post, it can be thought of as our API contract. WSDL? OpenAPI specification? Well, like those, yes. The below file defines what API requests can be made, and what the inputs and outputs are Knowing this, we can look at the API contract and divine an API request.&lt;/p&gt;

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

// This will be part of the fully qualified service name &amp;lt;1&amp;gt;
package com.example;

import "akkaserverless/annotations.proto";
import "google/api/annotations.proto";
import "google/protobuf/empty.proto";

option java_outer_classname = "CounterApi";

message IncreaseValue {
    string counter_id = 1 [(akkaserverless.field).entity_key = true];
    int32 value = 2;
}

message DecreaseValue {
    string counter_id = 1 [(akkaserverless.field).entity_key = true];
    int32 value = 2;
}

message ResetValue {
    string counter_id = 1 [(akkaserverless.field).entity_key = true];
}

message GetCounter {
    string counter_id = 1 [(akkaserverless.field).entity_key = true];
}

message CurrentCounter {
    int32 value = 1;
}

// This will be part of the fully qualified service name, appended to the package name &amp;lt;2&amp;gt;
service CounterService {
    option (akkaserverless.codegen) = {
        value_entity: {
            name: "com.example.domain.Counter"
            entity_type: "counter"
            state: "com.example.domain.CounterState"

        }
    };

    // each of the below can be an URI API call, appended to the fully qualified service name (separated by a forward slash) &amp;lt;3&amp;gt;
    rpc Increase (IncreaseValue) returns (google.protobuf.Empty);
    rpc Decrease (DecreaseValue) returns (google.protobuf.Empty);
    rpc Reset (ResetValue) returns (google.protobuf.Empty);
    rpc GetCurrentCounter (GetCounter) returns (CurrentCounter);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Going from top to bottom, let me call out the critical parts, respective of our &lt;code&gt;URI&lt;/code&gt; generation exercise.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We pick up the first part of our &lt;code&gt;fully qualified service name&lt;/code&gt; in the &lt;code&gt;package&lt;/code&gt; line. In this case, as we start building our URI, &lt;code&gt;/com.example&lt;/code&gt; starts us off!&lt;/li&gt;
&lt;li&gt;The second important line is the &lt;code&gt;service CounterService&lt;/code&gt; one; it contains the structure of the API requests that are supported by the API service. To our &lt;code&gt;fully qualified service name&lt;/code&gt; string, we will append the &lt;code&gt;CounterService&lt;/code&gt; to form &lt;code&gt;/com.example.CounterService&lt;/code&gt;. And as such, we're done with that.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Onward to determining the &lt;code&gt;method&lt;/code&gt; name. For each of the &lt;code&gt;rpc&lt;/code&gt; lines, contained within the &lt;code&gt;service&lt;/code&gt;, there will be an URI created, appending &lt;code&gt;method&lt;/code&gt; to our &lt;code&gt;fully qualified service name&lt;/code&gt;. What this looks like, would be a set of partial URIs:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/com.example.CounterService/Increase
/com.example.CounterService/Decrease
/com.example.CounterService/Reset
/com.example.CounterService/GetCurrentCounter
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're ready to go! Get me to Postman!&lt;/p&gt;

&lt;p&gt;Well, not so fast. We know that the &lt;code&gt;Always-on HTTP Transcoding&lt;/code&gt; feature in Akka Serverless is expecting a &lt;code&gt;POST&lt;/code&gt; with a &lt;code&gt;body&lt;/code&gt;, in JSON format, representing the API inputs. Where do we find these?&lt;/p&gt;

&lt;p&gt;As you look back at the part of the &lt;code&gt;protobuf&lt;/code&gt; file that had the method names, as marked by the &lt;code&gt;rpc&lt;/code&gt; designation, you will notice that immediately after the &lt;code&gt;method&lt;/code&gt; name, there is additional text, wrapped in parentheses. This is the input that the API method in question is expecting. Those input names, e.g. &lt;code&gt;IncreaseValue&lt;/code&gt;, map to &lt;code&gt;messages&lt;/code&gt; defined further up in the &lt;code&gt;protobuf&lt;/code&gt;. And from those &lt;code&gt;messages&lt;/code&gt;, we can determine the appropriate JSON to send in our API requests. We simply create a JSON attribute, with values matching the data type specified in the &lt;code&gt;message&lt;/code&gt;.  For example, message &lt;code&gt;IncreaseValue&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message IncreaseValue {
    string counter_id = 1 [(akkaserverless.field).entity_key = true];
    int32 value = 2;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The following JSON could be used as an input to our API request:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"counter_id": "foo", "value": 1}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Putting the two (&lt;code&gt;URI&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt;) together, adding the hostname of the running service, we can build a &lt;code&gt;curl&lt;/code&gt; command:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -XPOST -H "Content-Type: application/json" -d '{"counter_id": "foo", "value": 1}' https://nameless-thunder-9740.us-east1.akkaserverless.app/com.example.CounterService/Increase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we're ready for Postman!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating HTTP Requests in Postman
&lt;/h2&gt;

&lt;p&gt;Postman has great documentation and is a very intuitive application. So really, I'm not sure I need to lay out the steps to do this. But given that this approach is all about making everyday "normal" HTTP requests to a gRPC service/API, perhaps a quick run-through will be good.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you have to make a choice, blue pill or red...Wait. This isn't The Matrix! But with the recent beta release of &lt;code&gt;gRPC&lt;/code&gt; support in Postman, you'll be tempted to pick that path when creating a new request. Don't! Choose HTTP Request! &lt;/p&gt;




&lt;p&gt;Let's do this!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you don't have Postman installed on your machine, head &lt;a href="https://www.postman.com/"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Once you're ready, open up the Postman application.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &lt;strong&gt;New&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XdgiDF1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgn1toradhk0vnyal2l3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XdgiDF1Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dgn1toradhk0vnyal2l3.png" alt="Creating a new request in Postman" width="373" height="89"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &lt;strong&gt;HTTP Request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ps4QMkYc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lfpc5wxxpf38ad0n2ji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ps4QMkYc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6lfpc5wxxpf38ad0n2ji.png" alt="Choosing request type" width="853" height="568"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Change HTTP Method from &lt;strong&gt;GET&lt;/strong&gt; to &lt;strong&gt;POST&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in the &lt;code&gt;Enter request URL&lt;/code&gt; text field with our API URI: &lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://nameless-thunder-9740.us-east1.akkaserverless.app/com.example.CounterService/Increase
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your request should look like this now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rJVJW517--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ffhtkb05ww26sqj1vtr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rJVJW517--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ffhtkb05ww26sqj1vtr.png" alt="Entering URI" width="880" height="106"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;strong&gt;Body&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click on &lt;strong&gt;raw&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're not finding the above two, they're here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b82zTg71--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5tjdqm8p8cb8klyle3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b82zTg71--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s5tjdqm8p8cb8klyle3q.png" alt="Adding body" width="880" height="161"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Fill in the large text area with the above &lt;code&gt;POST&lt;/code&gt; body:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"counter_id": "foo", "value": 1}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Change &lt;strong&gt;Text&lt;/strong&gt; type to &lt;strong&gt;JSON&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aGfT2ZuM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whsgtwu3pg4x1nieyh7f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aGfT2ZuM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/whsgtwu3pg4x1nieyh7f.png" alt="Changing content type" width="880" height="317"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Send&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Profit!&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your Postman app should looking something like this. &lt;code&gt;200 OK&lt;/code&gt;, in green, means success!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0rOvKadO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9grzt4hnmn3tdc8du6nj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0rOvKadO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9grzt4hnmn3tdc8du6nj.png" alt="Completed request" width="880" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can rinse-and-repeat the above steps for each of the four API requests defined the &lt;code&gt;protobuf&lt;/code&gt; file. You can also access a fully-finished Postman Collection (a set of API requests) by clicking on the below button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.getpostman.com/run-collection/34862-3e1b7880-536c-41f9-a97b-8b1bef5cd88e?action=collection%2Ffork&amp;amp;collection-url=entityId%3D34862-3e1b7880-536c-41f9-a97b-8b1bef5cd88e%26entityType%3Dcollection%26workspaceId%3Ddee50495-76e5-4399-afea-21035ae2759d"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V37vEqA7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://run.pstmn.io/button.svg" alt="Run in Postman" width="123" height="30"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Where to go next
&lt;/h3&gt;

&lt;p&gt;If you're wanting to build out your first &lt;code&gt;gRPC&lt;/code&gt; API (or just build more!), head to &lt;a href="https://console.akkaserverless.lightbend.com/p/register#"&gt;Akka Serverless&lt;/a&gt; to get a free account. Or if you want to read first, the docs are at &lt;a href="https://developer.lightbend.com/docs/akka-serverless/quickstart/index.html"&gt;https://developer.lightbend.com/docs/akka-serverless/quickstart/index.html&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>postman</category>
      <category>microservices</category>
      <category>akka</category>
      <category>grpc</category>
    </item>
    <item>
      <title>gRPC test-and-try with Akka Serverless and Evans</title>
      <dc:creator>Jeremy Pollock</dc:creator>
      <pubDate>Tue, 04 Jan 2022 03:52:33 +0000</pubDate>
      <link>https://dev.to/jpollock/grpc-test-and-try-with-akka-serverless-and-evans-5gcc</link>
      <guid>https://dev.to/jpollock/grpc-test-and-try-with-akka-serverless-and-evans-5gcc</guid>
      <description>&lt;p&gt;&lt;code&gt;gRPC&lt;/code&gt; is awesome but this post isn't going to delve too deep there. Plenty of resources out there to learn more (definitely check out &lt;a href="https://github.com/grpc-ecosystem/awesome-grpc"&gt;https://github.com/grpc-ecosystem/awesome-grpc&lt;/a&gt;). &lt;/p&gt;

&lt;p&gt;I first learned about &lt;code&gt;gRPC&lt;/code&gt; about five years go. Since that moment in time when an engineer at &lt;a href="https://pubnub.com"&gt;PubNub&lt;/a&gt; introduced me to the framework, I have let the idea of &lt;code&gt;gRPC&lt;/code&gt; simmer more in the background, especially since I was already rather steeped in REST, Open API, Swagger, and other sundries seen in the broader API space (miss you, &lt;a href="https://developer.mashery.com/"&gt;Mashery&lt;/a&gt;. There seemed to be plenty of great tooling, documentation and technologies supporting "traditional" API development. Why break new ground and learn something new?&lt;/p&gt;

&lt;p&gt;Well, when I joined my new company, &lt;a href="https://www.lightbend.com"&gt;Lightbend&lt;/a&gt;, I quickly learned that &lt;code&gt;gRPC&lt;/code&gt; was a big part of my future! We use that framework as a big part of our new Platform-as-a-Service (PaaS), &lt;strong&gt;Akka Serverless&lt;/strong&gt;, that makes it as easy to build a real-time data application as it is to build a web page (well, a simple HTML one!). Now you might be thinking, "well, gRPC isn't so easy..." but you'd be wrong, or at least ripe for disruption. It takes a bit of learning, for sure, but there are plenty of great resources to help you out. And I'm going to dig into one of these in this post. A tool that makes it easy to try out those wonderful &lt;code&gt;gRPC&lt;/code&gt; services that I know you're going to build!&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Evans to try out a gRPC service
&lt;/h3&gt;

&lt;p&gt;Given my background in the API management space, and with not so distant memories of Mashery, Apigee and 3scale duking it out with their various flavors of API test consoles (kudos to Apigee for using their console to get ahead in the market!), one would think that I'm a sucker for UI. And yes, I do like the modern take on API test-and-try consoles; &lt;a href="https://www.postman.com/"&gt;Postman&lt;/a&gt; being quite a great example. I was excited about their beta announcement for &lt;code&gt;gRPC&lt;/code&gt; support! But as I dove into that tool and the other quite excellent API test-and-try tool, Kong's &lt;a href="https://insomnia.rest/"&gt;Insomnia&lt;/a&gt;, I realized that a critical feature - at least in my opinion - that was missing was &lt;code&gt;server reflection&lt;/code&gt;, which allows for dynamic clients to be used; no necessary gathering and loading of various &lt;code&gt;protobuf&lt;/code&gt; files. For more simplistic, single proto file implementations, not a problem. But with &lt;a href="https://akkaserverless.com"&gt;Akka Serverless&lt;/a&gt;, one can start to create rather elaborate &lt;code&gt;gRPC&lt;/code&gt; based APIs and microservices, including those that span over event brokers. The &lt;code&gt;protobuf&lt;/code&gt; files and structure become more sophisticated, with 3rd party library imports and the like. You &lt;em&gt;can&lt;/em&gt; gather up all the protos and sometimes that is indeed needed. But for quick testing, especially by those who aren't &lt;code&gt;gRPC&lt;/code&gt; experts, &lt;code&gt;server reflection&lt;/code&gt; makes it much easier to get going. &lt;/p&gt;

&lt;p&gt;And who am I kidding? I'm a CLI-type person. Which is why I was super excited to stumble about &lt;a href="https://github.com/ktr0731/evans"&gt;Evans&lt;/a&gt;. Within minutes, I had gone from installation to trying out TLS-secured APIs and microservices running in the cloud on Lightbend's new serverless offering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YoJLu7pL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3blq46ptmkq3c0rfa12.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YoJLu7pL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/x3blq46ptmkq3c0rfa12.png" alt="Screenshot of Evans CLI" width="880" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So let's try it out!&lt;/p&gt;

&lt;h4&gt;
  
  
  First, Install Evans!
&lt;/h4&gt;

&lt;p&gt;Following the instructions from the &lt;a href="https://github.com/ktr0731/evans#installation"&gt;Github repo&lt;/a&gt;, install the great &lt;code&gt;gRPC&lt;/code&gt; CLI tool, Evans. For MacOS users, it is as simple as:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ brew tap ktr0731/evans
$ brew install evans
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  Now take it out for a spin!
&lt;/h4&gt;

&lt;p&gt;For a terminal window, type in the following:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ evans --tls --host nameless-thunder-9740.us-east1.akkaserverless.app  --port 443 -r repl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The above command will create an Evans CLI session, connected to a demo gRPC service running in Lightbend's Akka Serverless Platform-as-a-Service (PaaS). The demo service in question is a simple counter API by which we can increment and decrement arbitrary counters. But don't take my word for it...&lt;/p&gt;

&lt;p&gt;First, get a list of packages available in the gRPC service, and then select the &lt;code&gt;com.example&lt;/code&gt; one. This is setting the context for further CLI commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; show package
+-------------------------+
|         PACKAGE         |
+-------------------------+
| com.example             |
| com.example.actions     |
| grpc.reflection.v1alpha |
+-------------------------+
nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; package com.example
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, get the list of &lt;code&gt;services&lt;/code&gt; exposed in the package. And select the &lt;code&gt;CounterService&lt;/code&gt; service; further defining the context, like selecting the &lt;code&gt;package&lt;/code&gt; above.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.example@nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; show service
+----------------+-------------------+---------------+----------------+
|    SERVICE     |        RPC        | REQUEST TYPE  | RESPONSE TYPE  |
+----------------+-------------------+---------------+----------------+
| CounterService | Increase          | IncreaseValue | Empty          |
| CounterService | Decrease          | DecreaseValue | Empty          |
| CounterService | Reset             | ResetValue    | Empty          |
| CounterService | GetCurrentCounter | GetCounter    | CurrentCounter |
+----------------+-------------------+---------------+----------------+
com.example@nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; service CounterService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Make an API call, to get the current state of the &lt;code&gt;foo&lt;/code&gt; counter. The Evans CLI will prompt you for the &lt;code&gt;counter_id&lt;/code&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.example.CounterService@nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; call GetCurrentCounter
counter_id (TYPE_STRING) =&amp;gt; foo
{
  "value": 23
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Increase the value of the counter by some amount, say &lt;code&gt;10&lt;/code&gt;. Again, the Evans CLI will ask you for the &lt;code&gt;counter_id&lt;/code&gt; and the &lt;code&gt;value&lt;/code&gt; by which the counter should be increased.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.example.CounterService@nameless-thunder-9740.us-east1.akkaserverless.app:443&amp;gt; call Increase
counter_id (TYPE_STRING) =&amp;gt; foo
value (TYPE_INT32) =&amp;gt; 10
{}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Finally, make another request to see the updated counter value.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&lt;a href="mailto:com.example.CounterService@nameless-thunder-9740.us-east1.akkaserverless.app"&gt;com.example.CounterService@nameless-thunder-9740.us-east1.akkaserverless.app&lt;/a&gt;:443&amp;gt; call GetCurrentCounter&lt;br&gt;
counter_id (TYPE_STRING) =&amp;gt; foo&lt;br&gt;
{&lt;br&gt;
  "value": 33&lt;br&gt;
}&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Where to go next&lt;br&gt;
&lt;/h3&gt;

&lt;p&gt;Definitely check out &lt;a href="https://github.com/grpc-ecosystem/awesome-grpc"&gt;Awesome gRPC&lt;/a&gt; for tons of great resources, even beyond the tooling like the Evans CLI. Also, if you want to start building &lt;code&gt;gRPC&lt;/code&gt; services in a streamlined fashion, without spinning up servers and figuring out deploys and operations, then you should sign-up for an account at &lt;a href="https://console.akkaserverless.lightbend.com/p/register#"&gt;Akka Serverless&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>grpc</category>
      <category>serverless</category>
      <category>akka</category>
    </item>
    <item>
      <title>Build Real-time Presence For Chat, Social and other Virtual Events</title>
      <dc:creator>Jeremy Pollock</dc:creator>
      <pubDate>Fri, 10 Dec 2021 22:57:21 +0000</pubDate>
      <link>https://dev.to/jpollock/build-real-time-presence-for-chat-social-and-other-virtual-events-3cpl</link>
      <guid>https://dev.to/jpollock/build-real-time-presence-for-chat-social-and-other-virtual-events-3cpl</guid>
      <description>&lt;p&gt;Thankfully, Turkey Day this year was a success, with time well spent with family and lots of drink and delicious food, although I was not able to convince my sister, responsible for food prep this year, to use my Thanksgiving Turkey of a post (hey!) in her cooking process. On this year's Thanksgiving Day, knowing that I had a day full of eating and drinking ahead of me, I took part in an annual tradition of mine: the Peloton Turkey Burn. A great way to burn calories but also to reflect on what it means to be real-time, within the context of a virtual social event with 10s of 1000s of users joining, sharing data and other wise participating in a shared experience. What technology enables this? How should it all work to yield the best experience? And when can I start eating? All questions that flowed through my mind during this year's event.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want to skip to code, go [[Add Scalable Real-time Presence with Akka Serverless, Scala and Kafka#Presence Requirements|here]]. Also, you can view and then clone the entire project containing the three services, created as part of the article, &lt;a href="https://github.com/jpollock/akka-serverless-presence-application"&gt;here&lt;/a&gt; (&lt;code&gt;git clone git@github.com:jpollock/akka-serverless-presence-application.git&lt;/code&gt; in a directory on your machine, if you want to cut to the chase!).&lt;/p&gt;




&lt;p&gt;Each year, tens of thousands of eager-to-burn-calories-in-advance-of-massive-food-intake riders hop on to their Pelotons and jointly, live, take part in a special ride, mostly in the comfort of their homes and apartments. Normally, and you can see this anecdotally just by participating in their live rides, you might find tens to hundreds of riders taking part in these real-time, live events. Scaling architectures and infrastructure to support these ups and downs - same solution for the live rides with tens of riders as for the Turkey Burns and other major events Peloton hosts throughout the year - is tough. With Peloton, of course the main feature is the live feed; I can't ride the bike if I don't have that instructor telling me what to do! But much of the success of their platform is based on the social features in the bike's application: from giving high-fives to fellow riders, to tracking position in the race - ahem, I mean 'ride' - to enabling one to filter out those pesky young riders so that this 50+ male from SF can feel good about his relative place in the world, the Peloton experience relies heavily on the idea of "presence": who is on-line, what are they all about, i.e. their profile, and what's happening relative to them, in the context of the event, in the case of Peloton. This is not much different from the presence of chat applications, on-line social events and even platforms like LinkedIn where they use #akka to deliver their &lt;a href="https://engineering.linkedin.com/blog/2018/01/now-you-see-me--now-you-dont--linkedins-real-time-presence-platf"&gt;real-time presence platform&lt;/a&gt;. Unless things have changed, Peloton leverages some real-time capabilities from &lt;a href="https://www.pubnub.com/docs/presence/overview"&gt;PubNub&lt;/a&gt; and as it happens, I was the Product Manager there during the development of a cool new feature that we built, based on Peloton's requirements: Presence Search.&lt;/p&gt;

&lt;p&gt;Each approach can yield success, either through a roll-your-own-solution using a technology like Lightbend's Akka or an As-A-Service offering like PubNub. It certainly depends on your needs; developers are often attracted to off-the-shelf offerings because of some of the inherent scaling challenges with presence, especially in those situations where usage is highly elastic. &lt;a href="https://www.lightbend.com/case-studies/scaling-handles-massive-traffic-spikes-with-ease"&gt;Dream11&lt;/a&gt;, another Lightbend customer and user of Akka, is another great example of this: they successfully use Akka to handle, efficiently, the real-time sensitive joining of users into live events. To quote that case study, linked above:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Each contest can have as few as two participants to upwards of tens of millions that can join up until the real-world event begins.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In either case, DIY and hosted API come with pros and cons. DIY gives you maximum control but comes with potential costs of having to think that much more deeply around architecture as well as supporting operationally highly elastic use cases. Hosted APIs are great but can sometimes cut down on flexibility of solution and comes with inherent availability risks of the the 3rd party vendor's services.&lt;/p&gt;

&lt;p&gt;What if you could get a little bit of the best of both worlds? To build a Peloton, a Dream11, a LinkedIn-esque real-time presence platform, to drive your use case, whether chat, on-line events, social applications and event IoT scenarios, all with the flexibility, robustness and scalability of a DIY framework like Akka, with the added value of not having to operate the services themselves?&lt;/p&gt;

&lt;p&gt;There is an answer! Akka Serverless!&lt;/p&gt;

&lt;h2&gt;
  
  
  Presence Requirements
&lt;/h2&gt;

&lt;p&gt;Before diggiing into code, let's just spend a moment on some basic requirements. I won't be fully replicating what LinkedIn, Dream11 and Peloton have done but it won't be too far off either.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Feature to Build&lt;/th&gt;
&lt;th&gt;Perf/scale requirements&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tracking on-line status of users&lt;/td&gt;
&lt;td&gt;On-line/off-line tracker with heartbeats used to update a user's status&lt;/td&gt;
&lt;td&gt;Possibly break out heartbeats from state management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provide ability to augment user profile with real-time data&lt;/td&gt;
&lt;td&gt;Flexible data model with real-time data integration support&lt;/td&gt;
&lt;td&gt;Possibly keep separate from heartbeats but with state management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provide queryability to the user data&lt;/td&gt;
&lt;td&gt;Search for state management, including on-line status and profile attributes&lt;/td&gt;
&lt;td&gt;Keep separate from heartbeats and possibly from core state management, i.e. #CQRS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For our solution, from the above, we'll create three separate services, using Akka Serverless for API logic and Kafka for event distribution. It could be that, in practice, we might not need them to developed as three seperate services but I do so such that the reader can see the art of possible with Akka Serverless. And if I were really building such a product or application, I would choose to do it this way, given my past experiences, product managing a very large virtual events API platform (PubNub). Through those experiences, and learnings from Lightbend as well, I can see:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Spiky usage, with large scale on-line events - think on-line concert, perhaps - driving very sudden increases in heartbeats and queries but perhaps similar increases for actual user profile data changes;&lt;/li&gt;
&lt;li&gt;Varied audience sizes - think normal Peloton class versus that Turkey Burn with 50K+ riders - along with varied usage scenarios, such that provisioning capacity becomes difficult to do;
&lt;/li&gt;
&lt;li&gt;Longer durations between heartbeating but with higher usage of querying for IoT use cases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To build this application that provides optimal performance and flexible scalability, I do so, with the following diagram leading the way:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--313dKltM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5jxzzq74ur4i8kw53om.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--313dKltM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y5jxzzq74ur4i8kw53om.png" alt="Architecture Picture" width="880" height="330"&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;This is going to give us the flexibility of scaling each component as needed and promote easier feature changes. I choose multiple languages (Java, Scala, Python) simply to show off the polyglot nature of Akka Serverless, which can help different teams build different pieces of the solution, in the language of their choice. Also, for a great developer experience, I use the Kafka-compatible Redpanda from &lt;a href="https://www.vectorized.io"&gt;Vectorized&lt;/a&gt; as the inter-service messaging solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's start!
&lt;/h2&gt;

&lt;p&gt;First, let's clone the repository, assuming that you want to look at the full files and even play with the service itself. Run the following in a directory of your choosing.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone git@github.com:jpollock/akka-serverless-presence-application.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Heartbeats Service (Java)
&lt;/h3&gt;

&lt;p&gt;Every time that I start an Akka Serverless project, using either Java or Scala, I use the &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/quickstart-template.html"&gt;project template&lt;/a&gt;. And thus it is true for the Heartbeats one. Definitely check-out that link for when you want to start your own development work. But for now, we're not going to step through the process. Not quite "in media res", the moment of API data domain definition and API specification is where I will pick up.&lt;/p&gt;
&lt;h4&gt;
  
  
  Domain Data
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;src/main/proto/com/example/demo/presence/domain/user_presence_domain.proto&lt;/code&gt;, I have defined the data schema for the &lt;code&gt;heartbeat&lt;/code&gt; domain, using &lt;a href="https://developers.google.com/protocol-buffers"&gt;protocol buffers&lt;/a&gt;.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;syntax = "proto3";

package com.example.demo.presence.domain;

import "akkaserverless/annotations.proto";

option (akkaserverless.file).replicated_entity = {
    name: "UserPresenceHeartbeat"
    entity_type: "user_presence_heartbeat"
    replicated_register: { 
        value: "Heartbeat" 
    }
};

message Heartbeat {
    string user_id = 1;
    string device_id = 2;
    bool is_online = 3;
    Profile profile = 4;
    bool is_modified = 5;
}

message Profile {
    string attr1  = 1;
    string attr2 = 2;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Most of the above is pretty straightforward. While how your domain is being modeled is most important, in order to use Akka Serverless, I do need to pick the &lt;a href="https://developer.lightbend.com/docs/akka-serverless/services/state-model.html"&gt;state model&lt;/a&gt;. This is set in this snippet of protobuf:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;option (akkaserverless.file).replicated_entity = {
    name: "UserPresenceHeartbeat"
    entity_type: "user_presence_heartbeat"
    replicated_register: { 
        value: "Heartbeat" 
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For presence heartbeats, I have decided to use Akka Serverless's &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/replicated-entity-crdt.html"&gt;Replicated Entity state model&lt;/a&gt;. There are several Conflict-Free Replicated Data Types (CRDTs) to pick from; in this case, I want to store just a value for each &lt;code&gt;user&lt;/code&gt;/&lt;code&gt;device&lt;/code&gt; combination. That's why I pick the &lt;code&gt;Replicated Register&lt;/code&gt; CRDT. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;name&lt;/em&gt;: denotes the base name for the Replicated Entity, the java code-generation process will create initial sources &lt;code&gt;UserPresenceHeartbeat&lt;/code&gt;, &lt;code&gt;UserPresenceHeartbeatTest&lt;/code&gt; and &lt;code&gt;UserPresenceHeartbeatIntegrationTest&lt;/code&gt;. Once these files exist, they are not overwritten, so you can freely add logic to them.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;entity_type&lt;/em&gt;: denotes a unique identifier of the "state storage". The entity name may be changed even after data has been created, the entity_type can’t.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;replicated_register&lt;/em&gt;: denotes the CRDT to be used.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;value&lt;/em&gt;: denotes the reference message definition, i.e. a pointer to another object defined in the protobuf.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  API Specification
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;src/main/proto/com/example/demo/presence/user_presence_api.proto&lt;/code&gt;, I have defined the facade, the specification of what API requests I will support and what their inputs and outputs are.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This is the public API offered by your entity.
syntax = "proto3";

import "google/protobuf/empty.proto";
import "akkaserverless/annotations.proto";
import "google/api/annotations.proto";

import "com/example/demo/presence/domain/user_presence_domain.proto";

package com.example.demo.presence;

message PresenceHeartbeatCommand {
    string user_id = 1 [(akkaserverless.field).entity_key = true];
    string device_id = 2 [(akkaserverless.field).entity_key = true];
    bool is_online = 3;
    domain.Profile profile = 4;
}

service PresenceHeartbeatCommandService {
    option (akkaserverless.service) = {
        type : SERVICE_TYPE_ENTITY
        component : "com.example.demo.presence.domain.UserPresenceHeartbeat"
    };

    rpc Heartbeat(PresenceHeartbeatCommand) returns (domain.Heartbeat) {
    }
}

service PresenceHeartbeatEventService {
    option (akkaserverless.service) = {
        type : SERVICE_TYPE_ACTION
    };

    rpc HeartbeatEvent(PresenceHeartbeatCommand) returns (domain.Heartbeat) {
        option (google.api.http) = {
            put: "/users/{user_id}/devices/{device_id}/heartbeat"
            body: "*"
        }; 
    }
    rpc HeartbeatEventToKafka(domain.Heartbeat) returns (domain.Heartbeat) {
        option (akkaserverless.method).eventing.out = {
            topic: "heartbeats"
        };    
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are many interesting aspects to this API specification.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;[(akkaserverless.field).entity_key = true]&lt;/code&gt; in the &lt;code&gt;PresenceHeartbeatCommand&lt;/code&gt; message definition are special Akka Serverless annotations; this one lets the run-time connect your incoming API request to specific entity instances (not quite DB rows but moe like uniquely addressable objects running in memory, with a backing DB behind it), e.g. user_is=jeremy and device_id=iphone would route incoming requests to the Akka Serverless entity with those two paticular attribute/value combinations. And given the &lt;code&gt;entity_key&lt;/code&gt; serves as a unique identifier, we know that there is only one instance of the entities.&lt;/li&gt;
&lt;li&gt;There's another Akka Serverless annotation and that is the one that starts with &lt;code&gt;option (akkaserverless.service) = {&lt;/code&gt; in the above (first line below the beginning of the &lt;code&gt;PresenceHeartbeatCommandService&lt;/code&gt; service definition). This is used by Akka Serverless code-gen processes so that plenty of boilerplate code can automatically be generated for you. In this case, we're telling the code-gen process what type of component code to write, e.g. &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#action"&gt;Action&lt;/a&gt; or &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#entity"&gt;Entity&lt;/a&gt; or &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#view"&gt;View&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The last Akka Serverless annotation in this particular protobuf is the one associated with the &lt;code&gt;rpc HeartbeatEventToKafka&lt;/code&gt; API call definition. In this case, we're letting Akka Serverless that this API is going to produce events - data - on to a message broker, with each event a message, sent to either Google Pubsub or Kafka.&lt;/li&gt;
&lt;li&gt;For supporting incoming web requests, ala REST, Google has some annotations itself; this is the &lt;code&gt;google.api.http&lt;/code&gt; entry, towards the bottoms of the protobuf, associated with the &lt;code&gt;rpc HeartbeatEvent&lt;/code&gt; API call definition.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  API Implementation
&lt;/h4&gt;

&lt;p&gt;In the above protbuf, you may have noticed that we have two &lt;code&gt;service&lt;/code&gt; definitions: one for the CRDT &lt;code&gt;entity&lt;/code&gt; that will store the actual heartbeat data and one for the &lt;code&gt;action&lt;/code&gt; that will ingest data events over HTTP/S. Why not just have the entity itself respond directly to HTTP/S requests? Because entities cannot emit events to external message brokers. But we can use the &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/actions-as-controller.html"&gt;Actions as Controllers&lt;/a&gt; pattern. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/main/java/com/example/demo/presence/PresenceHeartbeatEventServiceAction.java&lt;/code&gt;, we see our logic:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** An action. */
public class PresenceHeartbeatEventServiceAction extends AbstractPresenceHeartbeatEventServiceAction {

    public PresenceHeartbeatEventServiceAction(ActionCreationContext creationContext) {}

    /** Handler for "HeartbeatEvent". */
    @Override
    public Effect&amp;lt;UserPresenceDomain.Heartbeat&amp;gt; heartbeatEvent(UserPresenceApi.PresenceHeartbeatCommand presenceHeartbeatCommand) {
        CompletionStage&amp;lt;UserPresenceDomain.Heartbeat&amp;gt; heartbeatDone =
            components().userPresenceHeartbeat().heartbeat(presenceHeartbeatCommand)
                .execute();            

        CompletionStage&amp;lt;Effect&amp;lt;UserPresenceDomain.Heartbeat&amp;gt;&amp;gt; effect = heartbeatDone.thenApply(heartbeat -&amp;gt; {
        System.out.println("HeartbeatEvent: " + heartbeat);

        if (heartbeat.getIsModified()) {
            DeferredCall&amp;lt;UserPresenceDomain.Heartbeat, UserPresenceDomain.Heartbeat&amp;gt; call =
                components().presenceHeartbeatEventServiceAction().heartbeatEventToKafka(heartbeat); 
            return effects().forward(call);
        } else {
            return effects().reply(heartbeat);
        }

        });
        System.out.println("Heartbeat Effect: " + effect);
        return effects().asyncEffect(effect);

    }

    /** Handler for "HeartbeatEventToKafka". */
    @Override
    public Effect&amp;lt;UserPresenceDomain.Heartbeat&amp;gt; heartbeatEventToKafka(UserPresenceDomain.Heartbeat heartbeat) {
        System.out.println("HeartbeatEventToKafka: " + heartbeat);
        return effects().reply(heartbeat);

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The method &lt;code&gt;heartbeatEvent&lt;/code&gt; is the logic that will be executed whenever an API request is made to the endpoint specified in the protbuf file. This is what we call a &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#command_handler"&gt;command handler&lt;/a&gt;, i.e. the business logic that you want executed for given requests. In this particular handler, I'm using the service composability capabilities in Akka Serverless to make another request - internal to the product - to the actual entity service that is managing my heartbeat CRDT data. I access this through the service's &lt;code&gt;components&lt;/code&gt;, with &lt;code&gt;userPresenceHeartbeat&lt;/code&gt; matching the name of the component as defined in the service's protobuf definition. The method that I call, &lt;code&gt;heartbeat&lt;/code&gt;, is codified in &lt;code&gt;src/main/java/com/example/demo/presence/domain/UserPresenceHeartbeat.java&lt;/code&gt;. That code will be executed and once complete, returned to the action, which then determines if it should immediately reply or forward the logic flow to another action handler, &lt;code&gt;heartbeatEventToKafka&lt;/code&gt;, which ultimately is the control point for sending events to Google Pubsub or Kafka, given the &lt;code&gt;out&lt;/code&gt; to a topic definition in the protobuf file. We don't want to unnecessarily send unchanged data events so we use the logic of a simple &lt;code&gt;if&lt;/code&gt; statement, e.g. &lt;code&gt;if (heartbeat.getIsModified()) {&lt;/code&gt; to determine whether to forward or not. If forwarded, the data will be sent to the target message broker topic.&lt;/p&gt;

&lt;p&gt;We know now how the events are ingested and egressed out of the service and the logic in between. Well, part of the logic, that is; let's dig a bit into the CRDT entity code.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/main/java/com/example/demo/presence/domain/UserPresenceHeartbeat.java&lt;/code&gt;, we see our entity logic:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** A replicated entity. */
public class UserPresenceHeartbeat extends AbstractUserPresenceHeartbeat {
    @SuppressWarnings("unused")
    private final String entityId;

    public UserPresenceHeartbeat(ReplicatedEntityContext context) {
        this.entityId = context.entityId();
    }

    @Override
    public UserPresenceDomain.Heartbeat emptyValue() {
        return UserPresenceDomain.Heartbeat.getDefaultInstance();
    }

    @Override
    public Effect&amp;lt;UserPresenceDomain.Heartbeat&amp;gt; heartbeat(ReplicatedRegister&amp;lt;UserPresenceDomain.Heartbeat&amp;gt; currentData, UserPresenceApi.PresenceHeartbeatCommand presenceHeartbeatCommand) {
        System.out.println("UserPresenceHeartbeat.heartbeat.state: " + currentData);
        UserPresenceDomain.Heartbeat currentHeartbeat = currentData.get(); 

        boolean isModified = true;
        if (currentHeartbeat.getIsOnline() == presenceHeartbeatCommand.getIsOnline()) {
            isModified = false;
        } 
        UserPresenceDomain.Heartbeat newValue = UserPresenceDomain.Heartbeat.newBuilder()
            .setUserId(presenceHeartbeatCommand.getUserId())
            .setDeviceId(presenceHeartbeatCommand.getDeviceId())
            .setIsOnline(presenceHeartbeatCommand.getIsOnline())
            .setProfile(presenceHeartbeatCommand.getProfile())
            .setIsModified(isModified)
            .build();
        System.out.println("UserPresenceHeartbeat.heartbeat: " + newValue);
        return effects()
            .update(currentData.set(newValue)) 
            .thenReply(newValue);  

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Holy cow! &lt;code&gt;System.out.println&lt;/code&gt;??? Well, check my bio. I blame being a Product Manager! Anyway, the critical method, &lt;code&gt;heartbeat&lt;/code&gt;, is not doing anything terribly sophistiated: we look at the current state of the entity - that's automatically handed to us as part of the Akka Serverless proxy - and, if not changed, do nothing, else, update the state. We use the &lt;code&gt;isModified&lt;/code&gt; property to tell the calling action whether or not to forward the heartbeat event to the message broker. We only emit events for state changes; that allows us to scale each service differently, e.g. if 1000s of users are on-line and firing heart beat events every 5 seconds, we don't push that load to the other services unless actual changes are occurring.&lt;/p&gt;

&lt;p&gt;I didn't step through all of the code, line by line, but it should be faily self-apparent, especially given the small scope of actual logic. Let's fire up the service and quickly test it out.&lt;/p&gt;

&lt;h4&gt;
  
  
  Trying the Java Heartbeats Service
&lt;/h4&gt;

&lt;p&gt;Before you start, make sure Docker is running!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In a terminal window, get into the root of the project directory, cloned above, e.g.  &lt;code&gt;cd presence-heartbeats-java&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In the same terminal window, start the partially cooked Turkey API: &lt;code&gt;PORT=8081 mvn compile exec:exec&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In another terminal window, in the root of the project directory: &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  User State Service (Scala)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Domain Data
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;src/main/proto/com/example/demo/presence/domain/user_presence_domain.proto&lt;/code&gt;, I have defined the data schema for the &lt;code&gt;user_presence&lt;/code&gt; domain, using &lt;a href="https://developers.google.com/protocol-buffers"&gt;protocol buffers&lt;/a&gt;. This is the actual user state, including profile attributes that might be specific to an application and/or use case.&lt;/p&gt;

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

package com.example.demo.presence.domain;

import "akkaserverless/annotations.proto";

option (akkaserverless.file).value_entity = {
    name: "UserPresence"
    entity_type: "user_presence"
    state: "UserPresenceState"
};

message UserPresenceState {
    string user_id = 1;
    string device_id = 2;
    bool is_online = 3;
    Profile profile = 4;
}

message Heartbeat {
    string user_id = 1 [(akkaserverless.field).entity_key = true];
    string device_id = 2 [(akkaserverless.field).entity_key = true];
    bool is_online = 3;
    Profile profile = 4;
}

message Profile {
    string attr1  = 1;
    string attr2 = 2;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Like our heartbeats service, since we're designing our domain data model, we need to pick our state model. In this case, I've gone with &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/value-entity.html"&gt;Value Entity&lt;/a&gt;, as seen by &lt;code&gt;option (akkaserverless.file).value_entity&lt;/code&gt; above. Value entities are essentialy a Key-Value store.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;em&gt;name&lt;/em&gt;: denotes the base name for the Value Entity, the scala code-generation process will create initial sources &lt;code&gt;UserPresence&lt;/code&gt;, &lt;code&gt;UserPresenceTest&lt;/code&gt; and &lt;code&gt;UserPresenceIntegrationTest&lt;/code&gt;. Once these files exist, they are not overwritten, so you can freely add logic to them.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;entity_type&lt;/em&gt;: denotes a unique identifier of the "state storage". The entity name may be changed even after data has been created, the entity_type can’t.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;state&lt;/em&gt;: denotes the protobuf message representing the Value Entity’s state which is kept by Akka Serverless.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  API Specification
&lt;/h4&gt;

&lt;p&gt;In &lt;code&gt;src/main/proto/com/example/demo/presence/user_presence_api.proto&lt;/code&gt;, I have defined the facade, the specification of what API requests I will support and what their inputs and outputs are.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This is the public API offered by your entity.
syntax = "proto3";

import "google/protobuf/empty.proto";
import "akkaserverless/annotations.proto";
import "google/api/annotations.proto";

import "com/example/demo/presence/domain/user_presence_domain.proto";

package com.example.demo.presence;


message GetUserPresenceCommand {
    string user_id = 1 [(akkaserverless.field).entity_key = true];
    string device_id = 2 [(akkaserverless.field).entity_key = true];

}

service PresenceStateService {
    option (akkaserverless.service) = {
        type : SERVICE_TYPE_ENTITY
        component : "com.example.demo.presence.domain.UserPresence"
    };

    rpc TogglePresence(domain.Heartbeat) returns (domain.UserPresenceState) {}

    rpc GetCurrentUserPresence(GetUserPresenceCommand) returns (domain.UserPresenceState) {
        option (google.api.http) = {
            get: "/users/{user_id}/devices/{device_id}"
        };      
    }

}

service PresenceHeartbeatEventService {
    option (akkaserverless.service) = {
        type : SERVICE_TYPE_ACTION
    };


    rpc HeartbeatEvent(domain.Heartbeat) returns (domain.UserPresenceState) {
        option (akkaserverless.method).eventing.in = {
            topic: "heartbeats"
        }; 
        option (akkaserverless.method).eventing.out = {
            topic: "users"
        }; 

    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Given our description of the Java Heartbeats service's protobuf, the above should make sense. Everything is basically an analog of that other protobuf, from the Akka Serverless' annotations for conntecting to entity system models, to the mapping of events to pubsub/kafka topics.&lt;/p&gt;

&lt;h4&gt;
  
  
  API Implementation
&lt;/h4&gt;

&lt;p&gt;You're looking for my &lt;code&gt;println&lt;/code&gt; statements, right? Not in my scala, I say! Anyway, similar to the Heartbeats service, we define two APIs in our protobuf: one for the Key-Value &lt;code&gt;entity&lt;/code&gt; that will store the actual user data and one for the &lt;code&gt;action&lt;/code&gt; that will ingest and emit data events via messaging (Pubsub or Kafka). Remember: this is the &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/actions-as-controller.html"&gt;Actions as Controllers&lt;/a&gt; pattern. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/main/java/com/example/demo/presence/PresenceHeartbeatEventServiceAction.scala&lt;/code&gt;, we see our logic:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** An action. */
class PresenceHeartbeatEventServiceAction(creationContext: ActionCreationContext) extends AbstractPresenceHeartbeatEventServiceAction {

    /** Handler for "HeartbeatEvent". */
    override def heartbeatEvent(heartbeat: Heartbeat): Action.Effect[UserPresenceState] = {

        val heartbeatReply: Future[UserPresenceState] =
        for { 
            userPresenceState &amp;lt;- components.userPresence.togglePresence(heartbeat).execute()
        } yield userPresenceState

        effects.asyncReply(heartbeatReply)
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The method &lt;code&gt;heartbeatEvent&lt;/code&gt; is the logic that will be executed whenever a message, of type &lt;code&gt;Heartbeat&lt;/code&gt;, is received on the message broker topic, &lt;code&gt;heartbeats&lt;/code&gt;. Like our Java code, this is a &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#command_handler"&gt;command handler&lt;/a&gt; as well, i.e. the business logic that you want executed for given requests. In this particular handler, I'm using the service composability capabilities in Akka Serverless to make another request - internal to the product - to the actual entity service that is managing my user state Value Entity (Key-Value) data. I access this through the service's &lt;code&gt;components&lt;/code&gt;, with &lt;code&gt;userPresence&lt;/code&gt; matching the name of the component as defined in the service's protobuf definition. The method that I call, &lt;code&gt;heartbeat&lt;/code&gt;, is codified in &lt;code&gt;src/main/java/com/example/demo/presence/domain/UserPresence.scala&lt;/code&gt;. That code will be executed and once complete, returned to the action, which will we return it to the calling application, and, given the &lt;code&gt;out&lt;/code&gt; to a topic definition in the protobuf file, also to either Google Pubsub or Kafka.&lt;/p&gt;

&lt;p&gt;Let's dig a bit into the Key-Value entity code.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/main/java/com/example/demo/presence/domain/UserPresence.scala&lt;/code&gt;, we see our entity logic:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/** A value entity. */
class UserPresence(context: ValueEntityContext) extends AbstractUserPresence {
override def emptyState: UserPresenceState = UserPresenceState()

override def togglePresence(currentState: UserPresenceState, heartbeat: Heartbeat): ValueEntity.Effect[UserPresenceState] = {
    val newState = currentState.copy(userId = heartbeat.userId, 
    deviceId = heartbeat.deviceId, 
    isOnline = heartbeat.isOnline,
    profile = heartbeat.profile)

    effects
        .updateState(newState) 
        .thenReply(newState) 
}

override def getCurrentUserPresence(currentState: UserPresenceState, getUserPresenceCommand: presence.GetUserPresenceCommand): ValueEntity.Effect[UserPresenceState] = 
    effects.reply(currentState)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;No &lt;code&gt;println&lt;/code&gt;! This file contains two methods, one to enable fetching user state through a &lt;code&gt;GET&lt;/code&gt; call, i.e. the &lt;code&gt;getCurrentUserPresence&lt;/code&gt; method, which simply returns the current state of the user. The other method, &lt;code&gt;togglePresence&lt;/code&gt;, takes the event data from the message broker and transforms the &lt;code&gt;Heartbeat&lt;/code&gt; into a &lt;code&gt;UserPresenceState&lt;/code&gt;, signaling to Akka Serverless to save the update, via the &lt;code&gt;updateState&lt;/code&gt; call and then return the new data back to the &lt;code&gt;action&lt;/code&gt;, which in turn will emit that update out as an event published to the message broker topic, &lt;code&gt;users&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pretty simple, huh? Let's try this out!&lt;/p&gt;

&lt;h4&gt;
  
  
  Trying the Scala User State Service
&lt;/h4&gt;

&lt;p&gt;Before you start, make sure Docker is running!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In a terminal window, get into the root of the project directory, cloned above, e.g.  &lt;code&gt;cd presence-user-state-scala&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In the same terminal window, start the partially cooked Turkey API: &lt;code&gt;sbt run&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In another terminal window, in the root of the project directory: &lt;code&gt;docker-compose up&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Querying Service (Python)
&lt;/h3&gt;

&lt;p&gt;So far we've walked through the code for our Heartbeats service, which is able to be scaled up and down automatically in Akka Serverless depending on load and use case, handling the ingestion of potentially highly variable user on-line/off-line events. This was in Java. For actual storage of the users and their current state, we built our User State service, which uses an underling Key-Value state model, i.e. Value Entity, for storage and quick access to a user's current data. Both services have events flowing between using the message broker integration in Akka Serverless, whether Google Pubsub or Kafka based.&lt;/p&gt;

&lt;p&gt;The last piece of our architectural puzzle is our query service. This enables a #CQRS implementation, with querying in a separate service and as such can be optimized for performance separately from the other pieces of our overall presence application. I built mine using the community &lt;a href="https://jpollock.github.io/akkaserverless-python-sdk/python/index.html"&gt;Python SDK&lt;/a&gt;. Whenever I start a new Python service, I typically go &lt;a href="https://jpollock.github.io/akkaserverless-python-sdk/python/getting-started.html"&gt;here&lt;/a&gt;. There's no code-gen (yet) for Python SDK.&lt;/p&gt;

&lt;p&gt;The feature that we are using for the query service is called &lt;a href="https://jpollock.github.io/akkaserverless-python-sdk/python/views.html"&gt;Views&lt;/a&gt;. They enable you to query over the state. From &lt;a href="https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#view:"&gt;https://developer.lightbend.com/docs/akka-serverless/reference/glossary.html#view:&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A View provides a way to retrieve state from multiple Entities based on a query. You can query non-key data items. You can create views from Value Entity state, Event Sourced Entity events, and by subscribing to topics.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We'll use the "subscribing to topics" in our approach.&lt;/p&gt;

&lt;h4&gt;
  
  
  Domain Data
&lt;/h4&gt;

&lt;p&gt;The Python SDK works a bit different that Java or Scala. A single file protobuf is best and this is what I have done for now. The domain data I am dealing with is the same as defined in our Scala SDK, &lt;code&gt;UserPresenceState&lt;/code&gt;. That is what is being emitted from the User State service and what the view feature expects, in order to build up the underlying query implementation. The below should be straightforward, with nothing new; remember that the &lt;code&gt;[(akkaserverless.field).entity_key = true]&lt;/code&gt; tell Akka Serverless what the entity instance identifier fields are.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message UserPresenceState {
    string user_id = 1 [(akkaserverless.field).entity_key = true];
    string device_id = 2 [(akkaserverless.field).entity_key = true];
    bool is_online = 3;
    Profile profile = 4;
}

message Profile {
    string attr1  = 1;
    string attr2 = 2;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  API Specification
&lt;/h4&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message UsersResponse {
    repeated domain.UserPresenceState results = 1; 
}

service PresenceQueryApi {
    rpc UpdateView(UserPresenceState) returns (UserPresenceState) {
        option (akkaserverless.method).eventing = {

        in: {
            consumer_group: "python-consumer-group"
            topic: "users"
            }
        };
        option (akkaserverless.method).view.update = {
            table: "users"
        };
    }

    rpc GetUsers(google.protobuf.Empty) returns (UsersResponse) {
        option (akkaserverless.method).view.query = {
            query: "SELECT * AS results FROM users"
        };
        option (google.api.http) = {
            get: "/users"
        };  
    }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  API Implementation
&lt;/h4&gt;

&lt;p&gt;This is when it gets really complicated! Well, there really isn't an implementation. Akka Serverless does need to have some boilerplate code in order to do its thing but that's it. In &lt;code&gt;api_impl.py&lt;/code&gt; we find:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# imports fom Akka Serverless SDK
from akkaserverless.view import View

# imports fom Python generated code
from api_spec_pb2 import (_PRESENCEQUERYAPI, DESCRIPTOR as FILE_DESCRIPTOR)

view = View(_PRESENCEQUERYAPI,[FILE_DESCRIPTOR])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;All we're doing is writing some boilerplate to wire everything up, connecting the view to the API definition. We see this in the inclusion of the &lt;code&gt;_PRESENCEQUERYAPI&lt;/code&gt; import and passing that into the &lt;code&gt;View&lt;/code&gt; Akka Serverless Python object.&lt;/p&gt;

&lt;h4&gt;
  
  
  Trying the Python Querying Service
&lt;/h4&gt;

&lt;p&gt;Before you start, make sure Docker is running!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In a terminal window, get into the root of the project directory, cloned above, and enter the python folder e.g.  &lt;code&gt;cd presence-querying-python&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;You will want to create a &lt;a href="https://docs.python.org/3/library/venv.html"&gt;Virtual Environment&lt;/a&gt;: &lt;code&gt;python3 -m venv akkasls_env&lt;/code&gt; (&lt;code&gt;akkasls_env&lt;/code&gt; can be named whatever you want and located anywhere though);&lt;/li&gt;
&lt;li&gt;Initiate the virtual environment: &lt;code&gt;source akkasls_env/bin/activate&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;Install the needed Python libraries: &lt;code&gt;pip install -r requirements.txt&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In the same terminal window (or another with the virtual environment activated), start the Python service: &lt;code&gt;PORT=8082 USER_FUNCTION_PORT=$PORT start.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In another terminal window, in the same directory, with the virtual environment sourced, simulate an event using &lt;code&gt;kafka_message_generator.py&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Deploying and Testing in Akka Serverless
&lt;/h2&gt;

&lt;p&gt;We have three separate services as part of our application. This makes testing all locally a bit challenging, since your computer might not have all of the resources to run everything (&lt;code&gt;start_all.sh&lt;/code&gt; in the root of the project is there if you want though). So rather than do that, let's just deploy to Akka Serverless.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://developer.lightbend.com/docs/akka-serverless/akkasls/install-akkasls.html"&gt;Install the Akka Serverless CLI&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Once installed, you can sign-up for a new account via &lt;code&gt;akkasls auth signup&lt;/code&gt; (or visit the &lt;a href="https://console.akkaserverless.lightbend.com/p/register"&gt;Console Sign-up page&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Login to your account via the CLI: &lt;code&gt;akkasls auth login&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In a terminal window, in the root directory of the project, set environmental variables:
export DOCKER_REGISTRY=
export DOCKER_PASS=&lt;/li&gt;
&lt;li&gt;Configure your Kakfa broker per the [documentation](&lt;a href="https://developer.lightbend.com/docs/akka-serverless/projects/message-brokers.html#_confluent_cloud"&gt;https://developer.lightbend.com/docs/akka-serverless/projects/message-brokers.html#_confluent_cloud&lt;/a&gt;. &lt;strong&gt;Do not pick the Python client, since the actual Kafka integration is running in the Akka Serverless proxy.&lt;/strong&gt; You can also configure the broker to use other Kafka platforms; we love &lt;a href="https://vectorized.io/cloud"&gt;Redpanda&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Per the same documentation, create the &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;heartbeats&lt;/code&gt; topics in Confluent Cloud or Redpanda.&lt;/li&gt;
&lt;li&gt;In the same terminal window, run the command &lt;code&gt;deploy.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make some API calls!&lt;/p&gt;

&lt;p&gt;-- send a heartbeat (java service)&lt;br&gt;
curl -XPUT -H "Content-Type: application/json" "https://$(akkasls services get presence-heartbeats-java -o json | jq -r '.contourroutes[0].spec.host')/users/myuser/devices/mydevice/heartbeat" -d '{"is_online": true, "profile": {"attr1": "test", "attr2": "test"}}'&lt;/p&gt;

&lt;p&gt;-- get the user's state (scala service, updated via Kafka events)&lt;br&gt;
curl -XGET "https://$(akkasls services get presence-user-state-scala -o json | jq -r '.contourroutes[0].spec.host')/users/myuser/devices/mydevice"&lt;/p&gt;

&lt;p&gt;-- query the list of users (python service, updated via Kafka events)&lt;br&gt;
curl -XGET "https://$(akkasls services get presence-querying-python -o json | jq -r '.contourroutes[0].spec.host')/users"&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully you now have a better idea on how some of the moving parts work in Akka Serverless and how you can build event driven APIs and services, including those that can be integrated with Kafka. We also leverage much of the new service composability features in Akka Serverless, to make a rather sophisticated application without a whole lot of setup.&lt;/p&gt;

&lt;p&gt;And don't forget: get your free Akka Serverless account &lt;a href="https://akkaserverless.com"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>scala</category>
      <category>akka</category>
      <category>kafka</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Distributed Real-Time Turkey Cooking With Scala, Akka Serverless and Kafka</title>
      <dc:creator>Jeremy Pollock</dc:creator>
      <pubDate>Tue, 23 Nov 2021 19:06:48 +0000</pubDate>
      <link>https://dev.to/jpollock/distributed-real-time-turkey-cooking-with-scala-akka-serverless-and-kafka-53m4</link>
      <guid>https://dev.to/jpollock/distributed-real-time-turkey-cooking-with-scala-akka-serverless-and-kafka-53m4</guid>
      <description>&lt;p&gt;Right now, my mind turns toward the wonderful feast awaiting me this coming Thanksgiving Thursday. But before I dig into the turkey, stuffing and pumpkin pie, I thought that I would whet my appetite with an antipasto of Scala, Akka Serverless and Kafka.&lt;/p&gt;

&lt;p&gt;Thanksgiving is a big holiday here in the United States. It is a day when family and friends gather together to celebrate life and give thanks to the bounty that we enjoy. Also, we like to eat and drink on this day. A lot. And the foods we tend to enjoy are most often long observed traditions such as stuffing, pumpkin pies, cranberry sauce, mashed potatoes with the gravy made from the juices and nicely browned bits of the piece de resistance, the Thanksgiving Turkey.&lt;/p&gt;

&lt;p&gt;Gluttonous consumption seems rather distasteful these days so I thought that it would be great to see how we could leverage technology to make sure that the food that we do being to the table is done so most efficiently and with maximum great taste. What better tools to bring into the picture than Akka - in the form of the new serverless offering - and Kafka?&lt;/p&gt;

&lt;p&gt;There is plenty of content and data out there supporting the assertion that Akka is a highly efficient distributed data and streaming platform. These are some good articles and posts: &lt;a href="https://netflixtechblog.com/towards-a-reliable-device-management-platform-4f86230ca623"&gt;Towards a Reliable Device Management Platform&lt;/a&gt;, &lt;a href="https://www.infoq.com/presentations/linkedin-play-akka-distributed-systems/"&gt;Streaming a Million Likes/Second: Real-Time Interactions on Live Video&lt;/a&gt;, &lt;a href="https://medium.com/expedia-group-tech/actors-for-akka-stream-throughput-65d97837b34b"&gt;Actors for Akka Stream Throughput&lt;/a&gt;. But let's talk turkey!&lt;/p&gt;

&lt;p&gt;Wait. Is this another blog post about the perfect recipe or most effective cooking method for that large bird you've procured from the local supermarket?  It is not. In fact, this blog post is intended really to let us play a bit with an interesting new developer platform product: &lt;a href="https://akkaserverless.com"&gt;Akka Serverless&lt;/a&gt;. And to do so with a fun, funny and utterly useless use case: how to enable a distributed team of cooks, experts, and industry, to create the perfect turkey! &lt;/p&gt;

&lt;p&gt;In order to not stuff ourselves too much, we'll keep our focus tight:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Standup a general turkey management API, using the event sourcing capabilities of Akka Serverless;&lt;/li&gt;
&lt;li&gt;Integrate Kafka into the API, simulating an industry-hosted Machine Learning-based recommender system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At the end of this article, you will have prepared yourself fully for a real Thanksgiving Feast!&lt;/p&gt;

&lt;p&gt;Let's get going!&lt;/p&gt;

&lt;p&gt;For this exercise, we will start with a partially cooked project. Go ahead and get your environment setup by cloning: &lt;code&gt;git clone git@github.com:jpollock/turkey_tracker_scala.git&lt;/code&gt;. The &lt;code&gt;main&lt;/code&gt; brach is our starter, the partially cooked turkey, if you will. There are other branches that you can pull to get further along the cooking process. Oops. I mean "coding process"!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;schema_change&lt;/code&gt; branch has the modifications we will do in the first part of this exercise;&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;kafka_integration&lt;/code&gt; branch has the modifications we will do in the latter part, i.e. when we hook up Kafka to Akka Serverless!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What The Turkey Expects
&lt;/h2&gt;

&lt;p&gt;In order to walk through the code in this post, you're going to want the following set up in your environment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/install/"&gt;Docker 20.10.8 or higher&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.scala-sbt.org/"&gt;sbt&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://curl.se/download.html"&gt;Curl&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Initial State
&lt;/h2&gt;

&lt;p&gt;To kick things off, let's walk through the initial part of the exercise..&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In a terminal window, get into the root of the project directory, cloned above, e.g.  &lt;code&gt;cd turkey_tracker_scala&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In the same terminal window, start the partially cooked Turkey API: &lt;code&gt;sbt run&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In another terminal window, in the root of the project directory: &lt;code&gt;docker-compose -f docker-compose-proxy.yml&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Make Some API Calls
&lt;/h3&gt;

&lt;p&gt;Let's start cooking!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/StartCooking -d '{"turkey_id": "myfirstturkey"}'

curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/GetCurrentTurkey -d '{"turkey_id": "myfirstturkey"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":true,"done":"RAW","externalTemperature":0.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's stop cooking!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/EndCooking -d '{"turkey_id": "myfirstturkey"}'

curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/GetCurrentTurkey -d '{"turkey_id": "myfirstturkey"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":false,"done":"RAW","externalTemperature":0.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;But the question remains: &lt;strong&gt;Was the turkey tasty?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Modifying the API to prevent salmonella poisoning
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; You can &lt;code&gt;git clone schema_changes&lt;/code&gt; to get all of the code changes below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before determining taste though, the more important question is &lt;strong&gt;Has the turkey reached an internal temperature such that salmonella bacteria have been killed?&lt;/strong&gt; Because, you know, having folks visit the hospital on account of Thanksgiving eating is not desirable.&lt;/p&gt;

&lt;p&gt;Let's look at the current data model for our Turkey. Akka Serverless uses &lt;a href="https://developers.google.com/protocol-buffers"&gt;Protocol Buffers&lt;/a&gt; as the specification format for the data and event model as well as the API interfaces. The below is the contents from the &lt;code&gt;turkey_domain.proto&lt;/code&gt; file.&lt;/p&gt;

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

package com.example.domain;

import "akkaserverless/annotations.proto";

option (akkaserverless.file).event_sourced_entity = {
    name: "Turkey"
    entity_type: "turkey"
    state: "TurkeyState",
    events: ["InOven", "OutOfOven", "TemperatureChange"]
};

message TurkeyState {
    bool in_oven = 1;
    enum DoneStatus {
        RAW = 0;
        SALMONELLA = 1;
        STILL_SALMONELLA = 2;
        ALMOST_THERE = 3;
        PERFECT = 4;
    }
    DoneStatus done = 2;
    float external_temperature = 3;
}

message InOven {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
}
message OutOfOven {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
}

message TemperatureChange {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
    float new_temperature = 3;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There is much to unpack here but for now, let's focus on the mission at hand: preventing salmonella poisoning by fully cooking our bird! In the above, we see that we're tracking the external temperature. That's the oven. And we can imagine increasing or decreasing throughout the cooking process in order to ensure optimal results. But we won't know that unless we start tracking what the &lt;a href="https://www.usda.gov/media/blog/2020/11/12/countdown-food-safe-thanksgiving-day-faqs#:~:text=A%3A%20The%20turkey%20is%20ready,innermost%20part%20of%20the%20wing."&gt;USDA recommends&lt;/a&gt;: internal temperature.&lt;/p&gt;

&lt;p&gt;We can do that by adding a new attribute, &lt;code&gt;internal_temperature&lt;/code&gt; to the &lt;code&gt;TurkeyState&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message TurkeyState {
    bool in_oven = 1;
    enum DoneStatus {
        RAW = 0;
        SALMONELLA = 1;
        STILL_SALMONELLA = 2;
        ALMOST_THERE = 3;
        PERFECT = 4;
    }
    DoneStatus done = 2;
    float external_temperature = 3;
    float internal_temperature = 4;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That takes care of the domain data that we will manage. But how to communicate to the bird - or anyone else - that the internal temperature has indeed changed? In the above proto file, we see that we already have a &lt;code&gt;TemperatureChange&lt;/code&gt; event defined. This is used in the &lt;code&gt;IncreaseOvenTemperature&lt;/code&gt; and &lt;code&gt;DecreaseOvenTemperature&lt;/code&gt; API signatures in the &lt;code&gt;turkey_api.proto&lt;/code&gt;.  Let's try to re-use this approach by modifying the &lt;code&gt;TemperatureChange&lt;/code&gt; message schema.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message TemperatureChange {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
    enum Type {
        INTERNAL = 0;
        EXTERNAL = 1;
    }
    Type type = 2;
    float new_temperature = 3;    
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we can identify the type of change and, as we will see in just a moment, store the data in the right place. In order to store data though we have to receive it. Let's move over to our API specification in the &lt;code&gt;turkey_api.proto&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// This is the public API offered by your entity.
syntax = "proto3";

import "google/protobuf/empty.proto";
import "akkaserverless/annotations.proto";
import "google/api/annotations.proto";
import "turkey_domain.proto";

package com.example;

message CookingCommand {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
}
message TemperatureChangeCommand {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
    float temperature_change = 2;
}

message GetTurkeyCommand {
    string turkey_id = 1 [(akkaserverless.field).entity_key = true];
}

service TurkeyService {
    option (akkaserverless.service) = {
        type : SERVICE_TYPE_ENTITY
        component : "com.example.domain.Turkey"
    };
    rpc StartCooking(CookingCommand) returns (google.protobuf.Empty);
    rpc EndCooking(CookingCommand) returns (google.protobuf.Empty);
    rpc IncreaseOvenTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty);
    rpc DecreaseOvenTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty);

    rpc GetCurrentTurkey(GetTurkeyCommand) returns (domain.TurkeyState);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We see that we have API signatures - &lt;code&gt;Commands&lt;/code&gt; - for increasing and decreasing oven temperature. Let's support increasing and decreasing turkey temperature. We can add the following to the above protobuf file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    rpc IncreaseTurkeyTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty);
    rpc DecreaseTurkeyTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So far, we have modified our data schema and API specification to account for this need to prevent salmonella poisoining. Now we have to add the appropriate logic in our Scala code to account for this change. Let's look at our &lt;code&gt;src/main/scala/domain/Turkey.scala&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;As mentioned earlier in this post, we are using &lt;a href="https://martinfowler.com/eaaDev/EventSourcing.html"&gt;Event Sourcing&lt;/a&gt; as the state model for Akka Serverless. For the file that we're inspecting now - the logic behind getting data in and out of Akka - that means that we need to have code for handling both &lt;code&gt;commands&lt;/code&gt; and &lt;code&gt;events&lt;/code&gt;. We see both for our oven temperature changes; snippets for the &lt;code&gt;IncreaseOvenTemperature&lt;/code&gt; flow below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override def increaseOvenTemperature(currentState: TurkeyState, temperatureChangeCommand: example.TemperatureChangeCommand): EventSourcedEntity.Effect[Empty] = {
    effects
    .emitEvent(TemperatureChange(turkeyId=temperatureChangeCommand.turkeyId, newTemperature=(currentState.externalTemperature + temperatureChangeCommand.temperatureChange))) 
    .thenReply(_ =&amp;gt; Empty.defaultInstance) 
}

override def temperatureChange(currentState: TurkeyState, temperatureChange: TemperatureChange): TurkeyState = {
    currentState.copy(externalTemperature = temperatureChange.newTemperature)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;When an API request is issued to Akka Serverless, to increase the temperature of the oven, that request is handled by the command handler above, which creates the &lt;code&gt;TemperatureChange&lt;/code&gt; event and emits it. That event is subsequently, and &lt;strong&gt;asynchronously&lt;/strong&gt;, handled by the event handler, which updates the actual state of the turkey with the new &lt;code&gt;external_temperature&lt;/code&gt;. We need to make some modifications, to account for the &lt;code&gt;type&lt;/code&gt; attribute of the &lt;code&gt;TemperatureChange&lt;/code&gt; message schema, so we can reuse that, distinguishing between &lt;code&gt;internal&lt;/code&gt; and &lt;code&gt;external&lt;/code&gt; updates.&lt;/p&gt;

&lt;p&gt;Let's first update the existing code, adding in the &lt;code&gt;type&lt;/code&gt; attribute:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override def increaseOvenTemperature(currentState: TurkeyState, temperatureChangeCommand: example.TemperatureChangeCommand): EventSourcedEntity.Effect[Empty] = {
    effects
    .emitEvent(TemperatureChange(turkeyId=temperatureChangeCommand.turkeyId, changeType=TemperatureChange.Type.EXTERNAL, newTemperature=(currentState.externalTemperature + temperatureChangeCommand.temperatureChange))) 
    .thenReply(_ =&amp;gt; Empty.defaultInstance) 
}

override def decreaseOvenTemperature(currentState: TurkeyState, temperatureChangeCommand: example.TemperatureChangeCommand): EventSourcedEntity.Effect[Empty]= {
    effects
    .emitEvent(TemperatureChange(turkeyId=temperatureChangeCommand.turkeyId, changeType=TemperatureChange.Type.EXTERNAL, newTemperature=(currentState.externalTemperature - temperatureChangeCommand.temperatureChange))) 
    .thenReply(_ =&amp;gt; Empty.defaultInstance) 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's add the new command handlers for the increasing and decreasing of turkey temperature.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override def increaseTurkeyTemperature(currentState: TurkeyState, temperatureChangeCommand: example.TemperatureChangeCommand): EventSourcedEntity.Effect[Empty] = {
    effects
    .emitEvent(TemperatureChange(turkeyId=temperatureChangeCommand.turkeyId, changeType=TemperatureChange.Type.INTERNAL, newTemperature=(currentState.externalTemperature + temperatureChangeCommand.temperatureChange))) 
    .thenReply(_ =&amp;gt; Empty.defaultInstance) 
}

override def decreaseTurkeyTemperature(currentState: TurkeyState, temperatureChangeCommand: example.TemperatureChangeCommand): EventSourcedEntity.Effect[Empty]= {
    effects
    .emitEvent(TemperatureChange(turkeyId=temperatureChangeCommand.turkeyId, changeType=TemperatureChange.Type.INTERNAL, newTemperature=(currentState.externalTemperature - temperatureChangeCommand.temperatureChange))) 
    .thenReply(_ =&amp;gt; Empty.defaultInstance) 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And finally, let's update the event handler to account for the different types of temperature changes.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override def temperatureChange(currentState: TurkeyState, temperatureChange: TemperatureChange): TurkeyState = {
    temperatureChange.changeType match {
    case TemperatureChange.Type.EXTERNAL =&amp;gt; currentState.copy(externalTemperature = temperatureChange.newTemperature)
    case TemperatureChange.Type.INTERNAL =&amp;gt; currentState.copy(internalTemperature = temperatureChange.newTemperature)
    }    
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Smell that? That's some turkey cooking! Let's see how far along it is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Re-start the local dev environment and make some API calls
&lt;/h3&gt;

&lt;p&gt;In that same terminal command window, you can &lt;code&gt;CTRL+C&lt;/code&gt; to stop the current running service. If not already running, simply type &lt;code&gt;start.sh&lt;/code&gt;, which will recompile all of the protobufs, stop any running associated Docker containers and start the updated Akka Serverless service.&lt;/p&gt;

&lt;p&gt;And now for some cooking! I mean...curling!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/StartCooking -d '{"turkey_id": "myfirstturkey"}'

curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/IncreaseOvenTemperature -d '{"turkey_id": "myfirstturkey", "temperature_change": 100.0}'

curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/GetCurrentTurkey -d '{"turkey_id": "myfirstturkey"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":true,"done":"RAW","externalTemperature":100.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's make some additional API calls.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    curl -i -v -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/IncreaseTurkeyTemperature -d '{"turkey_id": "myfirstturkey", "temperature_change": 10.0}'

    curl -X POST -H 'Content-Type: application/json' http://localhost:9000/com.example.TurkeyService/GetCurrentTurkey -d '{"turkey_id": "myfirstturkey"}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The response should be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":true,"done":"RAW","externalTemperature":100.0,"internalTemperature":10.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Before moving on to the next section of this post, please shut down the services. &lt;code&gt;CTRL+C&lt;/code&gt; should work but it would be good to ensure proper shutdown of the Docker containers spun up: &lt;code&gt;docker-compose -f docker-compose-proxy.yml down&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Kafka events into our service
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; You can &lt;code&gt;git clone kafka_integration&lt;/code&gt; to get all of the code changes below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the amazing features in Akka Serverless is the ability to ingest (and egress if so desired) events from external messaging systems, e.g. Google Pubsub and Kafka, as well as use events to communicate between services running in the Akka Serverless Platform-as-a-Service (PaaS). You can read more about this feature &lt;a href="https://developer.lightbend.com/docs/akka-serverless/java/actions-publishing-subscribing.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Eventing easy to add though! And actually won't require any more Scala coding beyond the already implemented change for tracking a turkey's internal temperature.&lt;/p&gt;

&lt;p&gt;First, let's define that events will be supported, and of what type, for our APIs. For our prevent-salmonella-poisoning scenario, let's imagine that industry - a company perhaps - has delivered to the market a product that enables for remote recommendation generation based on machine-learning models being run in a cloud distant from the homes in which the turkeys are being cooked. We're not going to actually create an ML model and run it but we will simulate the process by which those events could be published on to a company's Kafka broker and sent through the pipes into Akka Serverless. So instead of making &lt;code&gt;gRPC&lt;/code&gt; or &lt;code&gt;HTTP&lt;/code&gt; API calls to increase the temperature of the oven, for example, we can have those commands issued from deep within the bowels of a company's infrastructure and sent over Kafka to the turkey entities managed in the Akka Serverless cloud. Neat, huh?&lt;/p&gt;

&lt;p&gt;To do that, we will update the &lt;code&gt;commands&lt;/code&gt; in the &lt;code&gt;turkey_api.proto&lt;/code&gt;: &lt;code&gt;IncreaseOvenTemperature&lt;/code&gt; and &lt;code&gt;DecreaseOvenTemperature&lt;/code&gt;. We can add the protobuf annotations supplied by Akka Serverless, to say "when &lt;code&gt;TemperatureChangeCommands&lt;/code&gt; are received on the &lt;code&gt;increase_temp&lt;/code&gt; topic, execute the &lt;code&gt;IncreaseOvenTemperature&lt;/code&gt; command." We do that for both commands.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rpc IncreaseOvenTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty) {
    option (akkaserverless.method).eventing.in = {
        topic: "increase_temp"
    };
}
rpc DecreaseOvenTemperature(TemperatureChangeCommand) returns (google.protobuf.Empty) {
    option (akkaserverless.method).eventing.in = {
        topic: "decrease_temp"
    };  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;That is it. I did say it was neat, didn't I?&lt;/p&gt;

&lt;p&gt;To run this locally, we take advantage of a great product, &lt;a href="https://vectorized.io/redpanda/"&gt;Redpanda&lt;/a&gt; from Vectorized.io. They have a Kafka API compatible streaming platform for mission-critical workloads, and a great way to run that locally (Docker or not).&lt;/p&gt;

&lt;p&gt;In a terminal window, in the root of the project directory: &lt;code&gt;docker-compose -f docker-compose-proxy.yml&lt;/code&gt;. This will start both the Akka Serverless proxy as well as the Redpanda container. From another terminal window, run the &lt;code&gt;sbt run&lt;/code&gt; command. You will notice some error messages that indicate that the topics, &lt;code&gt;increase_temp&lt;/code&gt; and &lt;code&gt;decrease_temp&lt;/code&gt; need to be created. Ignore for now, given that we are running locally. When moving to a hosted offering, like Confluent Cloud you will need to create topics &lt;a href="https://developer.lightbend.com/docs/akka-serverless/projects/message-brokers.html#_confluent_cloud"&gt;manually&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make some API calls and issue Kafka events
&lt;/h3&gt;

&lt;p&gt;First, let's get the initial state of our turkey.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X GET -H 'Content-Type: application/json' http://localhost:9000/turkeys/myfirstturkey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The result should look like.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":false,"done":"RAW","internalTemperature":0.0,"externalTemperature":0.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;From a new terminal window, in the root directory of the project: &lt;code&gt;sbt "runMain com.example.KafkaMessageGenerator myfirstturkey increase 10"&lt;/code&gt;. This will fire a &lt;code&gt;TemperatureChangeCommand&lt;/code&gt; event on the &lt;code&gt;increase_temp&lt;/code&gt; topic, sent to the locally running Redpanda cluster.&lt;/p&gt;

&lt;p&gt;Now if we make that same &lt;code&gt;GET&lt;/code&gt; call again, from above.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X GET -H 'Content-Type: application/json' http://localhost:9000/turkeys/myfirstturkey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The result should look like.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"inOven":false,"done":"RAW","internalTemperature":10.0,"externalTemperature":0.0}%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We have successfully delivered event data from an external source, via Kafka (Redpanda in this local case), into Akka Serverless. Profit!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to next?
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://developer.lightbend.com/docs/akka-serverless/akkasls/install-akkasls.html"&gt;Install the Akka Serverless CLI&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Once installed, you can sign-up for a new account via &lt;code&gt;akkasls auth signup&lt;/code&gt; (or visit the &lt;a href="https://console.akkaserverless.lightbend.com/p/register"&gt;Console Sign-up page&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Login to your account via the CLI: &lt;code&gt;akkasls auth login&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;In a terminal window, in the root directory of the project, package up the docker container and publish: &lt;code&gt;sbt docker:publish -Ddocker.username=&amp;lt;insert docker registry username&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Configure your Kakfa broker per the [documentation](&lt;a href="https://developer.lightbend.com/docs/akka-serverless/projects/message-brokers.html#_confluent_cloud"&gt;https://developer.lightbend.com/docs/akka-serverless/projects/message-brokers.html#_confluent_cloud&lt;/a&gt;. &lt;strong&gt;Do not pick the Python client, since the actual Kafka integration is running in the Akka Serverless proxy.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Per the same documentation, create the &lt;code&gt;increase_temp&lt;/code&gt; and &lt;code&gt;decrease_temp&lt;/code&gt; topics in Confluent Cloud.&lt;/li&gt;
&lt;li&gt;In the same terminal window, run the command &lt;code&gt;akkasls services deploy turkey-tracker $DOCKER_REGISTRY/$DOCKER_USER/turkey_tracker_scala:&amp;lt;insert tag from step #4 above&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In the same terminal window, run the command &lt;code&gt;akkasls services proxy turkey-tracker --grpcui&lt;/code&gt;. You can use this to explore the API running in the cloud without &lt;a href="https://developer.lightbend.com/docs/akka-serverless/akkasls/akkasls_services_expose.html"&gt;exposing&lt;/a&gt; over the internet.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully you now have a better idea on how some of the moving parts work in Akka Serverless and how you can build event driven APIs and services, including those that can be integrated with Kafka. While we're not really cooking turkeys, perhaps one day, we can leverage technologies like this to improve all of our Thanksgiving food-eating experiences!&lt;/p&gt;

&lt;p&gt;And don't forget: get your free Akka Serverless account &lt;a href="https://akkaserverless.com"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Photo credit: &lt;a href="https://www.istockphoto.com/portfolio/AlexRaths?mediatype=photography"&gt;https://www.istockphoto.com/portfolio/AlexRaths?mediatype=photography&lt;/a&gt;&lt;/p&gt;

</description>
      <category>scala</category>
      <category>akka</category>
      <category>kafka</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
