# jylis_ex
[](https://hex.pm/packages/jylis_ex)
[](https://coveralls.io/github/amclain/jylis_ex?branch=master)
[](https://hexdocs.pm/jylis_ex)
[](https://github.com/amclain/jylis_ex/blob/master/license.txt)
An idiomatic library for connecting an Elixir project to a
[Jylis](https://github.com/jemc/jylis) database.
> Jylis is a distributed in-memory database for Conflict-free Replicated Data
> Types (CRDTs), built for speed, scalability, availability, and ease of use.
## Installation
Add the `:jylis_ex` dependency to your `mix.exs` file:
```elixir
defp deps() do
[{:jylis_ex, ">= 0.0.0"}]
end
```
Run `mix deps.get` to get the new dependency.
## Database Connection
The connection URI must be specified in the format: `schema://host:port`, where
the schema is `jylis`. The `host` can be a host name, IP address, or domain name
of the database host to connect to. The `port` is optional and defaults to
`6379` unless otherwise specified.
```elixir
{:ok, connection} = Jylis.start_link("jylis://host:port")
```
## Queries
This library aims to be idiomatic with both Elixir and Jylis. Therefore, the
syntax of the queries closely match the [Jylis documentation](https://jemc.github.io/jylis/docs/types/)
and ideally it should feel natural to you, an Elixir programmer.
For example, take the case of a Jylis query to set a value for a
[`UJSON`](https://jemc.github.io/jylis/docs/types/ujson/#set-key-key-ujson) key:
```text
UJSON SET fruit apple '{"color": "red", "ripe": true}'
```
Using this library, the query looks like this:
```elixir
connection |> Jylis.UJSON.set(["fruit", "apple"], %{color: "red", ripe: true})
```
The format for a query is:
```text
Jylis.<data_type>.<function>(key(s), value?, timestamp?)
```
However, be sure to consult the [API documentation](https://hexdocs.pm/jylis_ex)
or the [Jylis documentation](https://jemc.github.io/jylis/docs/types/) for the
exact format of your particular query.
### TREG
Timestamped Register <sup>[[link](https://jemc.github.io/jylis/docs/types/treg/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.TREG.set("lamp_brightness", 80, 1528082143)
{:ok, result} = connection |> Jylis.TREG.get("lamp_brightness")
# {:ok, {"80", 1528082143}}
```
### TLOG
Timestamped Log <sup>[[link](https://jemc.github.io/jylis/docs/types/tlog/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.TLOG.ins("temperature", 68.8, 1528082150)
{:ok, _} = connection |> Jylis.TLOG.ins("temperature", 70.1, 1528082160)
{:ok, _} = connection |> Jylis.TLOG.ins("temperature", 73.6, 1528082170)
{:ok, size} = connection |> Jylis.TLOG.size("temperature")
# {:ok, 3}
{:ok, items} = connection |> Jylis.TLOG.get("temperature")
# {:ok, [{"73.6", 1528082170}, {"70.1", 1528082160}, {"68.8", 1528082150}]}
{:ok, _} = connection |> Jylis.TLOG.trim("temperature", 1)
{:ok, items} = connection |> Jylis.TLOG.get("temperature")
# {:ok, [{"73.6", 1528082170}]}
{:ok, _} = connection |> Jylis.TLOG.cutoff("temperature")
# {:ok, 1528082170}
```
### GCOUNT
Grow-Only Counter <sup>[[link](https://jemc.github.io/jylis/docs/types/gcount/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.GCOUNT.inc("mileage", 10)
{:ok, _} = connection |> Jylis.GCOUNT.inc("mileage", 5)
{:ok, value} = connection |> Jylis.GCOUNT.get("mileage")
# {:ok, 15}
```
### PNCOUNT
Positive/Negative Counter <sup>[[link](https://jemc.github.io/jylis/docs/types/pncount/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.PNCOUNT.inc("subscribers", 3)
{:ok, _} = connection |> Jylis.PNCOUNT.dec("subscribers", 1)
{:ok, value} = connection |> Jylis.PNCOUNT.get("subscribers")
# {:ok, 2}
```
### MVREG
Multi-Value Register <sup>[[link](https://jemc.github.io/jylis/docs/types/mvreg/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.MVREG.set("thermostat", 68)
{:ok, value} = connection |> Jylis.MVREG.get("thermostat")
# {:ok, ["68"]}
```
### UJSON
Unordered JSON <sup>[[link](https://jemc.github.io/jylis/docs/types/ujson/)]</sup>
```elixir
{:ok, _} = connection |> Jylis.UJSON.set(["users", "alice"], %{admin: false})
{:ok, _} = connection |> Jylis.UJSON.set(["users", "brett"], %{admin: false})
{:ok, _} = connection |> Jylis.UJSON.set(["users", "carol"], %{admin: true})
{:ok, users} = connection |> Jylis.UJSON.get("users")
# {:ok,
# %{
# "alice" => %{"admin" => false},
# "brett" => %{"admin" => false},
# "carol" => %{"admin" => true}
# }}
{:ok, _} = connection |> Jylis.UJSON.ins(["users", "brett", "banned"], true)
{:ok, _} = connection |> Jylis.UJSON.clr(["users", "alice"])
{:ok, users} = connection |> Jylis.UJSON.get("users")
# {:ok,
# %{
# "brett" => %{"admin" => false, "banned" => true},
# "carol" => %{"admin" => true}
# }}
```
### Raw Query
If this library doesn't contain a function for the query you would like to
perform, you can construct the query yourself by calling `Jylis.query`.
However, be aware that this function is non-idiomatic and may require you to
do your own pre/post processing on the data.
```elixir
{:ok, _} = connection |> Jylis.query(["TLOG", "INS", "temperature", 72.6, 5])
# {:ok, "OK"}
{:ok, value} = connection |> Jylis.query(["TLOG", "GET", "temperature"])
# {:ok, [["73.6", 1528082170]]}
```
### Timestamps
In addition to supporting integer timestamps as defined by the Jylis spec, this
library also has helpers to convert the Jylis `Timestamped` data types to/from
ISO 8601. Functions that have a `timestamp` parameter will automatically convert
an ISO 8601 string to a Unix timestamp.
```elixir
{:ok, _} = connection |> Jylis.TREG.set("volume", 64, "2018-06-06T01:42:57Z")
{:ok, result} = connection |> Jylis.TREG.get("volume")
# {:ok, {"64", 1528249377}}
result |> Jylis.Result.to_iso8601
# {"64", "2018-06-06T01:42:57Z"}
```