Upgrading from 0.1.x to 0.2.x

Version 0.2.0 brings this library in line with Elixir best practices for configuration.

Rationale

Configuration is no longer global. Instead, you configure Elasticsearch.Cluster modules, which are GenServers. This has several benefits:

  1. A single OTP app can talk to multiple Elasticsearch clusters. This is useful for umbrella apps in particular.

  2. Reading from environment variables is standardized. You do it by overriding the cluster's init/1 callback, as in Ecto and Phoenix.

  3. You can start clusters like any other genserver, passing in configuration at that time.

  4. You can bypass clusters altogether by passing configuration instead of a cluster to any function that expects a cluster.

Changes

BREAKING: an Elasticsearch.Cluster module or configuration map is now required for all Elasticsearch function calls.

BREAKING: {:system, "ENV_VAR"} is no longer supported in configuration. Instead, you should read from environment variables in the init/1 callback as described in the Elasticsearch.Cluster documentation.

BREAKING: The :api_module configuration option has been renamed to :api.

BREAKING: The required callbacks for Elasticsearch.API have been simplified down to a single request/5 function.

BREAKING: mix elasticsearch.build now requires the --cluster option.

How to Update Your App

First, add a Cluster to your application:

defmodule MyApp.ElasticsearchCluster do
  use Elasticsearch.Cluster, otp_app: :my_app
end

Next, switch over your :elasticsearch configuration over to your application, and include the cluster. Be sure to rename the :api_module option to :api. See Elasticsearch.Cluster for more options.

# BEFORE
config :elasticsearch,
  url: "http://localhost:9200",
  api_module: Elasticsearch.API.HTTP,
  # ...

# AFTER
config, :my_app, MyApp.ElasticsearchCluster,
  url: "http://localhost:9200",
  api: Elasticsearch.API.HTTP,
  # ...

Next, be sure to start your Cluster in your application supervisor:

children = [
  MyApp.ElasticsearchCluster
]

Next, add your cluster to all calls to Elasticsearch functions:

# BEFORE
Elasticsearch.post("/posts/_search", %{...})

# AFTER
Elasticsearch.post(MyApp.ElasticsearchCluster, "/posts/_search", %{...})

Next, update any mock implementations of Elasticsearch.API to implement the request/5 function instead of the previous functions.

# BEFORE
defmodule MyApp.ElasticsearchMock do
  @behaviour Elasticsearch.API

  def get("/url", _opts) do
    {:ok, %HTTPoison.Response{}}
  end
end

# AFTER
defmodule MyApp.ElasticsearchMock do
  @behaviour Elasticsearch.API

  @impl true
  def request(_config, :get, "/url", _data, _opts) do
    {:ok, %HTTPoison.Response{}}
  end
end

Finally, update any calls to mix elasticsearch.build to include the cluster as an option:

mix elasticsearch.build [index] --cluster MyApp.ElasticsearchCluster