Cowboy build takes too long

I’m fooling around with Cowboy, and the Getting Started guide has you build the src files with:

% make run

That takes 10-20 seconds on my system. That’s pretty intolerable when trying to write code. Is there a way to avoid having to rebuild the whole thing when I edit my src files?

You might find https://erlangforums.com/ a more focused audience for your question than this one if you don’t get any resolution here.

3 Likes

Here’s the thread on EFS:


I ended up following a tutorial on setting up cowboy in a Docker container using rebar3. I’m not using a Docker container, so what I ended up with is a rebar3 app with cowboy as a dependency. Thereafter, when I execute rebar3 shell, that starts a cowboy server and opens a shell in the terminal window. Then if I go into another terminal window and send a request to the url specified in my cowboy code, I get the expected response.

Here are the steps:

$ rebar3 new app my_cowboy_server
$ cd my_cowboy_server

In the file my_cowboy_server/rebar.config, add cowboy as a dependency:

{erl_opts, [debug_info]}.
{deps, [
  {cowboy, "2.10.0"}
]}.

{shell, [
  % {config, "config/sys.config"},
    {apps, [my_cowboy_server]}
]}.

You don’t have to add ranch or cow_lib as a dependency.

In the file my_cowboy_server/src/my_cowboy.app.src add cowboy to the list of applications that need to be started before your app:

{application, my_cowboy_server,
 [{description, "An OTP application"},
  {vsn, "0.1.0"},
  {registered, []},
  {mod, {my_cowboy_server_app, []}},
  {applications,
   [kernel,
    stdlib,
    cowboy
   ]},
  {env,[]},
  {modules, []},

  {licenses, ["Apache-2.0"]},
  {links, []}
 ]}.

In the file my_cowboy_server/src/my_cowboy_server_app.erl add your routes:

start(_StartType, _StartArgs) ->

    Dispatch = cowboy_router:compile([
        {'_', [{"/greet", hello_handler, []}]}
    ]),

    {ok, _} = cowboy:start_clear(my_http_listener,
        [{port, 8080}],
        #{env => #{dispatch => Dispatch}}
    ),

    my_cowboy_server_sup:start_link().

Create the file my_cowboy_server/src/hello_handler.erl:

-module(hello_handler).
-behavior(cowboy_handler).  

-export([init/2]).

init(Req0, State) ->
    Req = cowboy_req:reply(200,
        #{<<"content-type">> => <<"text/plain">>},
        <<"Hello Erlang!\r\n">>,
        Req0),

	{ok, Req, State}.

Then in one terminal window, I can execute:

my_cowboy_server$ rebar3 shell

and any output in my cowboy code will appear in that terminal window, for instance if I have this code:

-module(my_cowboy_server_app).
-behaviour(application).
-export([start/2, stop/1]).

start(_StartType, _StartArgs) ->
    io:format("[ME]: inside start()~n"),   % <======HERE

    Dispatch = cowboy_router:compile([
        {'_', [{"/greet", hello_handler, []}]}
    ]),

...
...

I see:

my_cowboy_server$ rebar3 shell
rebar3 shell
===> Verifying dependencies...
===> Analyzing applications...
===> Compiling my_cowboy_server
Erlang/OTP 26 [erts-14.1.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Eshell V14.1.1 (press Ctrl+G to abort, type help(). for help)
[ME]: inside start()     <===========THIS
===> Booted cowlib
===> Booted ranch
===> Booted cowboy
===> Booted my_cowboy_server
1> 

Then I can open another terminal window and send a request to the cowboy server, for instance:

$ curl "http://localhost:8080/greet"
Hello Erlang!

If you want/need to use the template generating capabilities of Erlang.mk, for instance to create hello_handler.erl, you could follow the cowboy Getting Started guide and create the hello_erlang release, then any time you need a template switch into that directory, generate the template, copy it, modify the module name, etc., then move it into your rebar3 app.

The command rebar3 shell compiles and executes the same code in about 1 second compared to 30-40 seconds for Erlang.mk. Of course, rebar3 shell is not creating a release, but if you want to experiment with cowboy, then a rebar3 app seems like the best way to quickly compile and execute your code.