Runners in depth

Technical reference for runners.

This reference guide assumes you already completed the steps described in the 5-minute getting started experience. To test that the Nextmv CLI is correctly configured, you can optionally run the following command on your terminal. It will get some files that are necessary to work with the Nextmv Platform. You can see the expected output as well.

nextmv sdk install

The Nextmv runners make it easy to read input data and options, run your algorithm and write output data. Data can come from Stdin, a file or an HTTP request for example and it can write to many different places. The options of your algorithm can be freely defined and will automatically be available via flags and environment variables. You can configure what the encoding of the input and output data is and set a variety of other options.

Let's dive in.

The CLI Runner

The CLI runner is the default runner and is intended to run your app from the Command Line Interface. It reads input data from Stdin or a file, runs your algorithm and writes the output to Stdout or a file. It also provides a --help flag that will print the options of your algorithm.

Here is a simple example.

    In this file we define a function called algorithm. This function defines an input struct which holds a field called Message and an option struct which holds a field called Duration. The output is defined as a struct with a Message field. The algorithm will take the duration that came in via the option, wait for that duration and then print the message that came in via the input with an additional word " World!". We are calling run.CLI to get the runner and then we call Run on it to start the actual run, which might return an error, so we handle that error.

    But how do the input and opts parameters in our algorithm function get populated when you run the program above by executing the bash script?

    Automatic flag and environment variable parsing

    The CLI runner will automatically parse the options of your algorithm from flags and environment variables. It also has some built-in options that you can use to configure the runner. When you build the above example and run the resulting binary with the --help flag, you will see the following output:

    The interesting part is the duration flag. It is automatically generated from the option struct of our algorithm. Note that the default value is 1s. This is because we defined 1s as the default via the go struct tag. Also note that the usage we defined in the go struct tag is also used in the help output. This means that you can document your algorithm options and they will be available via the --help command.

    The flags with the runner prefix are the runner specific options that come with the runner itself. As you can see in the bash script, we are passing a file path to the runner. runner.input.path is a built-in option that you can use to specify the path to the input file. If you don't specify a path, the runner will read from Stdin. Similarly, runner.output.path is a built-in option that you can use to specify the output path. If you don't specify a path, the runner will write to Stdout.

    Input decoding and output encoding

    The CLIRunner can decode input data from JSON, XML, GOB and CSV as well as encode output data to JSON, XML and GOB currently.

    In the following example, we will use the CSV decoding for the input and GOB encoding for the output. Note that GOB is a binary encoding and therefore the output contains some special characters.

      Turn your attention to the following lines:

      Here we configure the input decoding and output encoding. Note how we are providing type hints for the generic types. The first type is the type of our input (here [dataframe.DataFrame]), the second is the type of our options and lastly the type of our output.

      The algorithm itself is similar to the one in the previous example, but given we are now reading CSV data, we are showcasing some filtering on the Dataframe and then returning a message. If you look at the output tab, you'll notice some special characters which are there because the output is GOB encoded.

      The HTTP/S Runner

      The HTTP runner exposes your algorithm via an HTTP endpoint. You send the input data via a POST request and you can set the options of your algorithm via query parameters.

      Synchronous runs

      In the synchronous case, the output of the algorithm is returned to the caller synchronously. This means that the HTTP call will block until a run is finished. Let's look at an example.

        As you can see in the example above, the main function sets up the HTTP runner. We'll go into detail about the options in a moment. For now, turn your attention to the Bash tab. We are sending a POST request to the HTTP endpoint with the JSON input data in the body. We are also setting the duration as a query parameter. The output is returned as a JSON response. Just like you can configure decoders and encoders for the CLI runner, you can also do that for the HTTP runner in which case the input and output encodings would change appropriately - JSON is just the default.

        In the Output tab you can see the response to the curl request.

        In the Help tab, you can see the help output of the HTTP runner. It is similar to the help output of the CLI runner. You will find the duration option, because the algorithm hasn't changed. What has changed is the runner itself. The HTTP runner comes with different options, some of which you have seen in the code as well (address, maxparallel). Instead of setting them in the code, you can also set them via the command line flags and environment variables. If you want the HTTP runner to listen via HTTPS, you will have to set the path to both the certificate and the key file.

        Now, let us get back to setting the options for the HTTP runner and let us look at them in detail. SetAddr is used to set the port on which to listen, in the above example we are using port 9000. Furthermore SetMaxParallel is used to set the maximum number of parallel requests. If more requests than the maximum number of parallel requests come in at the same time, the ones that cause the overage will be rejected and a 429 status is returned (see below).

        Finally SetLogger is used to set the logger that the runner will use. In the following example we are provoking an error by sending a request with an invalid payload, which is just an opening curly bracket {.

          Asynchronous runs

          In the asynchronous case, the output of the algorithm is not returned to the caller. Instead, the caller receives a request ID and the output of the algorithm is posted to a given callback URL. Let's look at an example.

            The first go func in the main function uses Go's http module to start a callback server listening on port 8080. Of course in a real world scenario, this callback endpoint would not live in the same process and most likely not even on the same machine.

            Looking at the Bash tab, you can see that we are sending the same request as in the synchronous case. In contrast to the synchronous case, the response (see Output tab) is now a request ID. The callback function (see below) is configured to handle incoming requests. It writes the body of the request (which is the output of the algorithm) to a file called callback.txt (see tab callback.txt above). The request_id is the same id that the caller received when they initially sent the POST request and can be retrieved as depicted in the commented code in the callback function. This way a caller will be able to map requests to callback responses.

            This is the callback-side of the example. Now let's look at the HTTP runner once more.

            We configured the HTTP runner to work asynchronously. The default callback URL is set to post results to the endpoint that the first part of our code opened. The second option RequestOverride configures whether a caller can override the callback URL. In this case overriding the callback URL is forbidden. In case you want to allow the caller to specify a callback URL, set this value to true. A caller then passes callback_url with the appropriate URL in the header of the request.

            Page last updated

            Go to on-page nav menu