Sync’ up! … without getting drained

jul 4

NOTP: a middle way

NOTP logo

I’ve always considered Erlang to be an excellent general purpose programming language. With that, the one-off projects that aren’t systems or servers always had the bloat of OTP, and never felt right.

After writing Yanni, a Machine Learning suite in Erlang, one that needed to run, then stop, it was time to have a tool that shed the some sixty unused modules and just run my Erlang code already — with little overhead. Thanks to the final few pages in the Joe Armstrong 2nd edition Erlang book, the path was cleared and the inspiration was founded for NOTP.

What is NOTP?

NOTP is meant to be used as a ‘deps’ dependency inside textbook Erlang applications: applications designed to just run some code, then just stop; not unlike how ‘escript’ could be utilized.

Applications that need to run forever should utilize OTP and the apt target release tactics.

Getting started

You can use rebar[3] to bundle NOTP into your Erlang application using the conventional deps strategy.

The public repo for NOTP is as follows:

https://bitbucket.org/nato/notp

NOTP needs a file named ‘notp.config’ to be present in your project root, as it’s called from the ‘notp’ bootstrap routine.

The shape of ‘notp.config’ is as follows:

[
  {notp, [
    {support_modules, []},
    {local_modules, []}
  ]}
].

Since the goal of NOTP is to minimize the modules loaded for use, it’s up to you to dogmatically list the module names of your application within the ‘local_modules’ list. For example:

[
  {notp, [
    {support_modules, []},
    {local_modules, [my_code, my_code_lib]}
  ]}
].

It goes without stressing that other deps, if any, also need to be listed in this list.

Moreover, pretend that your Erlang application uses the ‘math’ and ‘rand’ modules. While it’s normally fine to assume these will be accessible without thinking about it, with NOTP, you need to list underlying OTP modules within the ‘support_modules’ list explicitly. For your convenience, the ‘lists’ and ‘erlang’ modules have already been accounted for, so you don’t need to specify those two. Again, take the following for instance:

[
  {notp, [
    {support_modules, [math, rand]},
    {local_modules, [my_code, my_code_lib]}
  ]}
].

If you neglect to include a needed module, you will be greeted with an error down the road.

Interfacing modules

In order to execute your application, one or more modules need to export a main/1 routine that the NOTP executable will call. It’s good housekeeping to have an API module that triggers all your code in an isolated module. You can model this behavior by taking a look at ‘src/notp_test.erl.’

N.B. these API module(s) ought not get included in your ‘notp.config’ lists, but of course need to be compiled.

Bootstrapping

In order to generate the various files to use NOTP, your code needs to be compiled, and a bootstrap call needs to be made. Here is an example of how that is done when NOTP is a deps and your ‘config’ file is up to snuff:

erlc -o ebin src/*.erl deps/*/src/*.erl
erl -config notp -pz ebin -s notp bootstrap

It should be noted that init:stop/0 is called by the bootstrapper; no need to include it in your erl command.

With that, you will be left with the notp executable in your project root, along with a requisite ‘notp.boot’ file. You may want to keep these files out of your project’s source control.

Usage

With all this in place, zippy Erlang code execution is ready to go. Here’s an example on how to use it:

./notp some_api_module_that_exports_main_1 [arg1 arg2 ... argk]

Note, the argument has no suffix — it’s just the name of a given API module. Also note, it will run your code without entering an Erlang shell.

What can NOTP do?

I tend to run code and spit out the results to standard out. But take a look at the exported routines of ‘src/notp.erl.’ All those goodies are available for use, and as such, quite a lot of ground can be covered with NOTP as your Erlang weapon of choice.