Skip to content

An idiomatic library for connecting an Elixir project to a Jylis CRDT database

License

Notifications You must be signed in to change notification settings

amclain/jylis_ex

Repository files navigation

jylis_ex

Hex.pm Coverage Status API Documentation MIT License

An idiomatic library for connecting an Elixir project to a Jylis CRDT 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:

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.

{: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 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 key:

UJSON SET fruit apple '{"color": "red", "ripe": true}'

Using this library, the query looks like this:

connection |> Jylis.UJSON.set(["fruit", "apple"], %{color: "red", ripe: true})

The format for a query is:

Jylis.<data_type>.<function>(key(s), value?, timestamp?)

However, be sure to consult the API documentation or the Jylis documentation for the exact format of your particular query.

TREG

Timestamped Register [link]

{:ok, _} = connection |> Jylis.TREG.set("lamp_brightness", 80, 1528082143)

{:ok, result} = connection |> Jylis.TREG.get("lamp_brightness")
# {:ok, {"80", 1528082143}}

TLOG

Timestamped Log [link]

{: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 [link]

{: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 [link]

{: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 [link]

{:ok, _} = connection |> Jylis.MVREG.set("thermostat", 68)

{:ok, value} = connection |> Jylis.MVREG.get("thermostat")
# {:ok, ["68"]}

UJSON

Unordered JSON [link]

{: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.

{: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.

{: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"}

About

An idiomatic library for connecting an Elixir project to a Jylis CRDT database

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Languages