https://github.com/scorsi/umbra
umbra helps you make your GenServer rocks in lesser code
https://github.com/scorsi/umbra
elixir elixir-library
Last synced: 4 months ago
JSON representation
umbra helps you make your GenServer rocks in lesser code
- Host: GitHub
- URL: https://github.com/scorsi/umbra
- Owner: scorsi
- License: mit
- Created: 2020-05-31T19:53:13.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2020-06-05T10:33:33.000Z (about 6 years ago)
- Last Synced: 2026-02-18T05:32:12.129Z (4 months ago)
- Topics: elixir, elixir-library
- Language: Elixir
- Homepage:
- Size: 98.6 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 7
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# Umbra [](https://travis-ci.com/scorsi/umbra) [](https://coveralls.io/github/scorsi/umbra?branch=master) [](https://hex.pm/packages/umbra) [](https://hex.pm/packages/umbra)
Umbra helps you make your GenServer rocks in lesser code, inspired by ExActor.
We all know [ExActor](https://github.com/sasa1977/exactor) which is a good project... which was... here the issues of ExActor:
- is not maintained since 2017,
- didn't support last GenServer functionalities like `continue`,
- did generate a lot of warnings in the user codebase like unused variables,
- isn't extensible.
Umbra has been inspired by ExActor, but nothing more, it is a totally re-write.
Umbra has a lightweight, well tested, highly documented and very comprehensive codebase.
The main differences with ExActor are :
- you have to declare function like you would normally do in the `handle_*` functions or `GenServer.*` call.
For example: `{:set_state, new_state}` and not like `set_state(new_state)`.
Umbra understands what you write :
- in the function definition,
- in the when guard,
- or in the state alias.
It will automatically :
- shadow unused variables,
- un-shadow necessary variables,
- create variables to optimize code,
- reduce code complexity when needed
- and all of this without your attention.
Actually Umbra lacks some features like `multicall` and `abcast` in addition to the `defstart`
which is internally done and not configurable to the user.
If you feel that Umbra lacks something or if you dive into a bug,
don't hesitate to create an issue or create a PR.
## Installation
Add umbra for Elixir as a dependency in your mix.exs file.
```elixir
def deps do
[
{:umbra, "~> 0.1.0"},
]
end
```
After you are done, fetch the new dependency:
```bash
$ mix deps.get
```
## Getting started
To get started, after adding the dependency to your mix project, you only have
to use the [`Umbra.GenServer`](https://hexdocs.pm/umbra/Umbra.GenServer.html)
and your GenServer already did start to being generated.
Here is a really simple exemple:
```elixir
defmodule BasicGenServer do
use Umbra.GenServer
definit state: state, do: {:ok, state}
defcall {:get_state}, state: state, do: {:reply, state, state}
defcast {:set_state, new_state}, do: {:noreply, new_state}
defcast {:increment}, state: state, do: {:noreply, state + 1}
defcast {:decrement}, state: state, do: {:noreply, state - 1}
end
{:ok, pid} = BasicGenServer.start_link(0) # state = 0
:ok = BasicGenServer.increment(pid) # state = 1
:ok = BasicGenServer.increment(pid) # state = 2
:ok = BasicGenServer.decrement(pid) # state = 1
:ok = BasicGenServer.set_state(pid, 42) # state = 42
{:ok, 42} = BasicGenServer.get_state(pid)
```
To deep further, please take a look at [HexDocs](https://hexdocs.pm/umbra).
## What do Umbra under the hood
Here is a notable example:
```elixir
defcall {:do_computation, {a, b}, _c}, when: is_number(a), state: state do
{:reply, a + b, state}
end
# The generated code
def do_computation(pid, {a, _b} = umbra_arg_1, c) when is_number(a) do
GenServer.call(pid, {:do_computation, umbra_arg_1, c})
end
def handle_call({:do_computation, {a, b}, _c}, _from, state) when is_number(a) do
{:reply, a + b, state}
end
```
Here what you can notice in this example:
- Umbra add a new variable `umbra_arg_1` to optimize the code. Passing `{a, b}` to the GenServer call
could be simpler but not optimized.
- Umbra automatically shadow the `b` variable to avoid warning for unused variable.
But it didn't do the same for the `a` variable since it is used in the when clause.
- Umbra did automatically un-shadow the `c` variable in the client-side function to avoid warning because
it is used in the GenServer call.
_Note: actually un-shadow and variable optimizations are not yet implemented but will come in the next updates._
## Tests
The project is tested for:
| Elixir version | OTP version |
| --- | --- |
| 1.7.4 | 21.3 |
| 1.7.4 | 22.3 |
| 1.8.2 | 21.3 |
| 1.8.2 | 22.3 |
| 1.9.4 | 21.3 |
| 1.9.4 | 22.3 |
| 1.10.3 | 21.3 |
| 1.10.3 | 22.3 |
| 1.10.3 | 23.0 |
Compatibility-issues only in tests for `otp < 21` caused primarily by the missing GenServer `continue` feature.
## Contributing
Contributions are welcome!
- [Fork it](https://github.com/scorsi/umbra/fork)!
- Create your feature branch (`git checkout -b your-new-feature`).
- Commit your change in only one commit (`git commit -am "Add my new feature"`).
- Push your change on your fork (`git push origin your-new-feature`).
- Create a new [Pull Request](https://github.com/scorsi/umbra/compare).
## Author
Sylvain Corsini ([@scorsi](https://github.com/scorsi))
## Credits
This project took inspiration from the well-known [ExActor](https://github.com/sasa1977/exactor).