Current section

Files

Jump to
geolix lib geolix.ex
Raw

lib/geolix.ex

defmodule Geolix do
@moduledoc """
IP location lookup provider.
## Usage
Fetching information for a single IP is done by passing it as a binary or
tuple to `Geolix.lookup/1`:
iex> Geolix.lookup("127.0.0.1")
%{
city: %{...},
country: %{...}
}
The response will be a map with the `:id` of each configured database as the
key and the database response as the value.
If you are only interested in the response of a specific database you can use
`Geolix.lookup/2`:
iex> Geolix.lookup({127, 0, 0, 1}, where: :my_database)
%{...}
The result structured of each database is specific to the adapter used.
### Lookup Options
There are two options you can pass to `Geolix.lookup/2` to modify the lookup
behaviour:
- `:timeout` - GenServer call timeout for the lookup. Defaults to `5_000`.
- `:where` - Lookup information in a single registered database
The adapter used can require and/or understand additional options. To
accommodate this the options are passed unmodified to the adapter's on lookup
function.
"""
alias Geolix.Database.Loader
alias Geolix.Server.Pool
@doc """
Looks up IP information.
"""
@spec lookup(ip :: :inet.ip_address() | binary, opts :: Keyword.t()) :: map | nil
def lookup(ip, opts \\ [])
def lookup(ip, opts) when is_binary(ip) do
case :inet.parse_address(Kernel.to_charlist(ip)) do
{:ok, parsed} -> lookup(parsed, opts)
{:error, _} -> nil
end
end
def lookup(ip, opts) when is_tuple(ip) do
request = {:lookup, ip, opts}
timeout = Keyword.get(opts, :timeout, 5000)
:poolboy.transaction(Pool, &GenServer.call(&1, request, timeout))
end
@doc """
Fetch metadata from one or multiple databases.
"""
@spec metadata(opts :: Keyword.t()) :: map | nil
def metadata(opts \\ []) do
request = {:metadata, opts}
timeout = Keyword.get(opts, :timeout, 5000)
:poolboy.transaction(Pool, &GenServer.call(&1, request, timeout))
end
@doc """
Loads a database according to its specification.
Requires at least the fields `:id` and `:adapter`. Any other required
fields depend on the adapter's requirements.
"""
@spec load_database(map) :: :ok | {:error, term}
def load_database(database) do
GenServer.call(Loader, {:load_database, database}, :infinity)
end
@doc """
Reloads all configured databases in the background.
"""
@spec reload_databases() :: :ok
def reload_databases, do: GenServer.cast(Loader, :reload_databases)
@doc """
Unloads a database.
This operation is lazy. The database will stay loaded but won't be reloaded
or used for lookups.
"""
@spec unload_database(atom) :: :ok
def unload_database(id), do: GenServer.call(Loader, {:unload_database, id})
end