olive 🫒

Package Version Hex Docs

Table of content

Objectives

Olive is a development tool to help working on a wisp server (AKA the main server in this doc). Olive is a proxy to your main server, that adds the following features:

The different pieces are:

Anything else sent to the proxy is directly rerouted to your main server.

Who is this for?

Caveats / Current limitations

Make sure to checkout the help for any configuration options with gleam run -m olive -- --help

Current limitations are:

Installation and usage

Add olive has a dev dependency of your main server:

gleam add --dev olive@1

Then, use gleam to run it:

gleam run -m olive

Olive takes care of running your main server for you!

Example

This is a stripped example to show the relevant parts only. Be sure to check the docs for wisp / mist / any other lib that allows to have a server running on the BEAM.

Let’s say you did a gleam new my_project.

In src/my_project.gleam:

pub fn main() {
  wisp.configure_logger()

  let assert Ok(_) =
    wisp_mist.handler(router.handle_request, "secret_key")
    |> mist.new
    |> mist.port(3000)
    |> mist.start_http

  process.sleep_forever()
}

In src/my_project/router.gleam:

pub fn handle_request(_req: Request) -> Response {
  response.new(200)
  |> response.set_body(mist.Bytes(bytes_tree.from_string(html("Hello world"))))
}

fn html(content: String) {
  "<html>
    <head>
      <title>My project</title>
    </head>
    <body>"
    <> content
    <> "</body>
    </html>"
}

Now, after installing olive, you can run gleam run -m olive, and the following will happen:

  1. Your server will be listening on localhost:3000
  2. The olive server will be listening on localhost:1234

Open localhost:1234, and you should be granted with a Hello world.

Now update the file in router.gleam so the server sends back Hello olive, and voila! Your browser should refresh automatically after a quick rebuild and show you the new message 🎉

Logging

Olive uses erlang logger module, and allows you to specify what goes out on your terminal. 3 levels of filters are specified:

Olive logs 2 kind of log level: Notice and Error. It also adds the metadata {domain => [olive]} to any logs so you can add your own handler on it if needed.

⚠️ I don’t recommand turning off Error log level. ⚠️

When rebuilding your project, any error from gleam build will be an Olive error log, and you won’t see it if it is turned off!

Technicalities

After building your project, Olive runs your program for you, similar to how gleam run would.

In technical words, it means Olive runs the following in erlang world:

spawn_link("<your_project>@@main", run, ["<your_project>"]).

With your_project being the name defined in gleam.toml.

The reload part lives also in erlang world, using this nice piece of code:

reload_modules() ->
    Modules = code:modified_modules(),
    lists:foreach(fun(Mod) -> code:purge(Mod) end, Modules),
    atomic_load(Modules).

This purges any modified modules that a gleam build would have produced, then replaces them on the fly.

Next time one of this module is called, the new code will take the lead. This has one inconvenient, your main file never gets called more than once, so even if it gets replaced, it will always be the old code still running. Most of the time, the main file has a process.sleep_forever() so the old code stays.

This is why any changes to your main file will need a reboot of olive.

Search Document