0478GitHub
jev
Elixir/OTP client designed around GenServer replies and pattern matching.
dannote/jevREADME ↗
# Jev
[](https://hex.pm/packages/jev) [](https://hexdocs.pm/jev) [](https://github.com/dannote/jev/actions/workflows/ci.yml)
[TypeSafe Jev](https://docs.typesafe.ai) and compatible decision models for OTP.
Jev is a peer process. You reply to it from a GenServer, and its answer is a
message you pattern match on.
```elixir
defmodule Triage do
use Jev.Server
def init(_), do: {:ok, %{}}
def handle_call({:labels, issue}, from, s) do
{:reply, {from, issue,
kind: {"What kind of issue is this?", %{bug: "Broken", feature: "New behavior", other: nil}},
severity: {"How severe for users?", ["Cosmetic", "Workaround", "Blocks", "Data loss"]},
security: "Does this describe a vulnerability?"}, s}
end
# Clause order is the routing. Thresholds are guards.
def handle_answer(%{security: p}, from, s) when p > 0.5, do: done(from, [:security], s)
def handle_answer(%{kind: :bug, severity: sev, confidence: %{kind: c}}, from, s)
when c > 0.85 and sev >= 2,
do: done(from, [:bug, :"priority:high"], s)
def handle_answer(%{kind: k, confidence: %{kind: c}}, from, s) when c > 0.6, do: done(from, [k], s)
def handle_answer(%{kind: k}, from, s), do: done(from, [k, :"needs-triage"], s)
def handle_answer({:error, reason}, from, s), do: done(from, {:error, reason}, s)
defp done(from, result, s) do
GenServer.reply(from, result)
{:noreply, s}
end
end
```
Nothing below `handle_answer/3` touches the network, so tests call it with a
literal map. The server never blocks on Jev: a hundred calls can be in flight,
and each answer finds its clause when it lands.
## Installation
```elixir
def deps do
[{:jev, "~> 0.1"}]
end
```
```elixir
config :jev, api_key: System.get_env("TYPESAFE_API_KEY") # or just set TYPESAFE_API_KEY
```
Or,