Context in Erlang

Here’s the translation of the Go code to Erlang, formatted in Markdown suitable for Hugo:

Our example demonstrates how to create a simple HTTP server in Erlang. This server showcases the usage of processes for handling cancellation, which is similar to the concept of context.Context in other languages. In Erlang, processes carry their own state and can communicate with each other, allowing for controlled cancellation and timeout handling.

-module(context_example).
-export([start/0]).

start() ->
    inets:start(),
    {ok, _} = inets:start(httpd, [
        {port, 8090},
        {server_name, "localhost"},
        {server_root, "."},
        {document_root, "."},
        {modules, [?MODULE]}
    ]),
    io:format("Server started on port 8090~n").

do(ModData) ->
    case ModData#mod.request_uri of
        "/hello" ->
            handle_hello(ModData);
        _ ->
            {proceed, ModData#mod.data}
    end.

handle_hello(ModData) ->
    io:format("server: hello handler started~n"),
    Parent = self(),
    Pid = spawn(fun() -> do_work(Parent) end),
    receive
        {Pid, done} ->
            io:format("server: hello handler ended~n"),
            {proceed, [{response, {200, "hello\n"}}]};
        {'EXIT', Pid, Reason} ->
            io:format("server: ~p~n", [Reason]),
            {proceed, [{response, {500, "Internal Server Error"}}]}
    after 10000 ->
        exit(Pid, timeout),
        io:format("server: request timed out~n"),
        {proceed, [{response, {500, "Request timed out"}}]}
    end.

do_work(Parent) ->
    process_flag(trap_exit, true),
    timer:sleep(10000),
    Parent ! {self(), done}.

In this Erlang example, we create an HTTP server that listens on port 8090. The handle_hello function is called when a request is made to the “/hello” endpoint.

Instead of using a context, we use Erlang’s built-in process management capabilities. The handle_hello function spawns a new process to do the work and waits for it to complete or for a timeout to occur.

The do_work function simulates some work by sleeping for 10 seconds before sending a message back to the parent process.

The parent process in handle_hello uses a receive block with a timeout. If the work completes within 10 seconds, it sends a success response. If a timeout occurs, it terminates the worker process and sends an error response.

To run the server:

$ erlc context_example.erl
$ erl -noshell -s context_example start -s init stop
Server started on port 8090

You can then make a request to the server:

$ curl localhost:8090/hello

If you interrupt the curl command before it completes (e.g., by pressing Ctrl+C), you’ll see the cancellation message in the server logs.

This example demonstrates how Erlang’s process model can be used to handle timeouts and cancellations in a way that’s conceptually similar to contexts in other languages, while leveraging Erlang’s built-in concurrency features.