View Source Conion

.github/workflows/elixir.yml

Conion is a package containing an Elixir application that provides some common modules for general tasks in your Elixir application.

At the moment, this is just a POC. Lets see how mature this application can get.

A persistent, supervised key/value store

...more to come

Install and prepare

git clone https://github.com/iboard/conion.git
cd conion
mkdir -p data/test data/dev
mix test

Use it as a dependency in your mix.exs

  defp deps do
    [
      { :conion, "~> 0.1"}
    ]

Usage Examples

Configuration

Define the following function in your top module

  def configurations,
    do: [
      # { {ENV,      :app,    :key, default}, set-function/1                }
      {{"LOG_LEVEL", :logger, :level, :info}, &Configuration.set_log_level/1}
    ]

and use it like

  def configure(),
    do:
      configurations()
      |> Enum.reduce(%{}, &Configuration.load_configuration_for/2)

CentralLogger

  use Conion.Common.CentralLogger
  
  def .... do 
    log(element_to_log, :warning, "Any message" )
  end

:warning is an example for any log-level (:info, :notice, :warning, :error, ...) The element_to_log will be "inspected" and passed through, thus you can use this log-function in a pipe.

CommonServer

To define your GenServers use ...

  use Conion.CommonServer
  
  def prepare_state_to_start(args) do
    # define any term that will be passed to `start_link(__MODULE__, state)` as
    # the initial state passed to GenServer's `init` function.
  end

  def initial_state(init_state_from_prepare_function) do
    # complete the "loading", "initializing" in the GenServer's init-callback here.
  end

  # use the `call/2` function to safely call a "handle_call" or "handle_cast"
  def bucket_name(pid), do: call(pid, :bucket_name)
  def persist(bucket), do: cast(process_name(bucket), :persist)
  
  # and implement the callbacks as usual
  def handle_call(:bucket_name, _, state), do: calculate_the_return; {:reply, state[:name], state}
  def handle_cast(:persist, state), do: do_something; {:noreply, state}

Store

Store.Persistor.File is a simple implementation of the Store.Persistor behaviour that writes the data into the given file, using :erlang.term_to_binary and reads it back using :erlang.binary_to_term

More implementations of "persistors" will follow.

alias CentralScrutinizer.Store
Store.new_bucket :family, Store.Persistor.File, filename: "data/dev/family.data"
# where `Store.Persistor.File` implements the `Persistor`-behaviour and writes the data to the
# given file.

{:ok, id_father} = Store.insert_new(:family, %{ name: "Father", age: 50})
{:ok, id_mother} = Store.insert_new(:family, %{ name: "Mother", age: 45})
{:ok, id_child} = Store.insert_new(:family, %{ name: "Child", age: 5})
Store.list(:family)
# [ {id, %{...}}, {id, %{...}}, ...]
Store.replace(:family, id_father, %{ name: "Papa", age: 51})
Store.get(:family, id_father) # => %{ name: "Papa", age: 51}
Store.remove(:family, id_father)
Store.persist(:family)

Generate an XREF image

to create an xref-graph use the following command:

mix xref graph --format dot  && \
dot -Tpng xref_graph.dot -o xref_graph.png && \
open xref_graph.png && \
sleep 5 && rm xref_graph.*

Generate documentation

mix docs && open doc/index.html