Implementing services in JavaScript

Before starting, make sure that you have the following installed:

  • Node - The JavaScript SDK uses the grpc node package new tab, which compiles a native gRPC implementation using node-gyp. It requires Node 12. You will find links to download Node here new tab.

  • Docker - You will need Docker new tab to build a container that you can deploy to Akka Serverless. You can publish the container to a variety of registries.

The SDK uses the protoc compiler to serialize your protobuf definitions into the protobuf binary descriptor format, but you do not need to explicitly install it. We provide helper scripts to automatically download the protoc compiler for your platform and compile your project.

Development project requirements

Use your favorite IDE to implement Akka Serverless services. You can create a JavaScript project from scratch, use our code generation tools to generate one, or start with one of our examples or tutorials.

The code generation tools do more than just provide a starter project, after you modify a .proto file, they will generate code stubs for the elements you changed or added.

If you are starting from scratch, you will need to add configuration and code to:

Add SDK libraries

Once you have the prerequisites, you need to add the @lightbend/akkaserverless-javascript-sdk package to your service development project, which can be done by running:

npm install akkaserverless@0.7.0-beta.1 --save-exact

To create a basic service, you need to include the akkaserverless package dependencies in your project, define gRPC descriptors in .proto files and reference them in your project, compile the .proto files, and have logic to start the gRPC server in your source code.

The following shows a minimal package.json configuration for a shopping cart service project:

{
  "name": "shopping-cart",
  "version": "0.1.0",
  "dependencies": {
    "@lightbend/akkaserverless-javascript-sdk": "0.7.0-beta.1"

  },
  "scripts": {
    "prestart": "compile-descriptor shoppingcart.proto",
    "start": "node index.js"
  }
}

Define gRPC descriptors and compile

Descriptors for gRPC are defined in protobuf files. You can place protobuf files in your project wherever you like, for example, in the root directory, or in a directory named protos. In the package.json example, above we’ve placed the service descriptor in a file in the root folder called shoppingcart.proto. See Writing gRPC descriptors for more details.

Precompile the protobuf descriptor set

The gRPC descriptor is serialized to binary using the Protobuf FileDescriptorSet message type. Akka Serverless requires that you precompile this descriptor using protoc. We provide a utility that does this for you. It downloads the protoc binary for your platform, and runs it with the necessary arguments and include paths. You can run the utility manually, or we recommend adding it as a script to the build.

To run the utility manually, invoke node_modules/@lightbend/akkaserverless-javascript-sdk/bin/compile-descriptor.js.

Or, add a prestart script to your npm build:

{
  "scripts": {
    "prestart": "compile-descriptor my-descriptor.proto"
  }
}

The compile-descriptor utility

Multiple protobuf files can be passed to the compile-descriptor utility. You can also pass any arguments accepted by protoc. Ror example, if you are importing files from other directories, you can add those directories as an include path by adding -Ipath/to/protobuf/dir.

By default, the descriptor is written to user-function.desc, if you wish to change this, you can set --descriptor_set_out=my-descriptor.desc. Note that if you output the descriptor to a different path, you will also need to pass that custom path to the constructor of the Akkaserverless class when you got to instantiate it.

Create and start the gRPC server

There are two ways to create and start an Akka Serverless gRPC server. The first is to create an Entity, and invoke start on it. This allows creating a server that serves a single entity, with the default options. We’ll look at this more in the subsequent pages. Alternatively, you can use the AkkaServerless class, add one or more entities to it, and then invoke start, like so:

const cloudstate = require("cloudstate");
const shoppingcart = require("./shoppingcart");

const server = new cloudstate.CloudState();
server.addEntity(shoppingcart);
server.start();

If you created your protobuf file descriptor set at a different location to the default of user-function.desc, you can configure that here:

const server = new cloudstate.CloudState({
    descriptorSetPath: "my-descriptor.desc"
});

For all options available on the AkkaServerless class, see CloudStateoptions.