freshness v0.2.1 Freshness View Source

Freshness

Hex.pm

A minimal pooling wrapper on top of Mint. It is meant as an alternative pooling option (other than e.g. Mojito) that should in theory allow for more flexibility when using Mint options. It returns raw Mint responses back to callers.

Installation

Install the package by adding freshness to your list of dependencies in mix.exs. If you need to make https requests then you need to add the castore dependency too (as with Mint)

def deps do
  [
    {:castore, "~> 0.1.0"},
    {:freshness, "~> 0.2.0"}
  ]
end

How to use

Freshness needs an Registry to look up workers. For each additional destination you need make requests to you need to add an additional supervisor to handle them.

Add the following lines to your application.ex file (or under any other Supervisor you want).
You can also take a look at the Mint connection options

def start (_, _) do

  # create 2 different pools for 2 separate endpoints
  # name can be any term, and will be used to identify the correct pool

  # arguments are pool_name, no_of_workers_in_pool, scheme, domain, port, mint_connection_options
  config = Freshness.Config.new("google", 5, :http, "google.com", 80, [])
  config2 = Freshness.Config.new(:bing, 5, :http, "bing.com", 80)

  children = [
    # freshness expect to find a :unique registry named Registry.Freshness. If you are already
    # using the Registry module in your app, you will need to specify an id as follows:

    Supervisor.child_spec({Registry, keys: :unique, name: Freshness.Config.registry_name()},
      id: Freshness.Config.registry_name()
    ),

    # again, because we're specifying the Freshness.Supervisor module twice, we need to also provide a distinct id

    Supervisor.child_spec({Freshness.Supervisor, config}, id: config1.name),
    Supervisor.child_spec({Freshness.Supervisor, config2}, id: config2.name)
  ]
  ...
  Supervisor.start_link(children, strategy: :one_for_one)
end

Inside your application you can now issue requests to the configured endpoints

{:ok, %Freshness.Response{}} = Freshness.get("google", "/")
...
{:ok, %Freshness.Response{}} = Freshness.get(:bing, "/")

Advanced usage

If you do not know the destinations at runtime, you can start the Registry in your application.ex file as above, but start the Freshness.Supervisors under a DynamicSupervisor

How it works

Freshness works by creating pools of workers that each holds one or more connections to a given destination. Connections are opened lazily but are re-used, but more may be created on the spot if a given worker cannot satisfy a request. Connecting and HTTP1,2 protocol parsing and buffering are all Mint. Right now the number of open connections each worker can open is unbound.

Freshness discovers the worker to pass a request to using the Registry module and an :atomics counter to round robin the requests to each worker in the pool

Is this production ready?

Not by a long shot. It's barely tested. Perhaps it will be someday- right now it just serves as an exploration project.

Link to this section Summary

Functions

Make a GET request using the given pool

Make a request to the configured Freshness pool

Link to this section Functions

Link to this function

get(server, path, headers \\ [])

View Source
get(Freshness.Config.pool_name(), path :: String.t(), Mint.Types.headers()) ::
  {:ok, Freshness.Response.t()} | {:error, term()}

Make a GET request using the given pool

Link to this function

request(pool_name, method, path, headers \\ [], body \\ "")

View Source
request(
  Freshness.Config.pool_name(),
  method :: String.t(),
  path :: String.t(),
  Mint.Types.headers(),
  body :: iodata() | nil | :stream
) :: {:ok, Freshness.Response.t()} | {:error, term()}

Make a request to the configured Freshness pool