# Eidetic Projector
[![build status](https://gitlab.com/gt8/open-source/elixir/eidetic-projector/badges/master/pipeline.svg)](https://gitlab.com/gt8/open-source/elixir/eidetic-projector/commits/master)
[![code coverage](https://gitlab.com/gt8/open-source/elixir/eidetic-projector/badges/master/coverage.svg)](https://gitlab.com/gt8/open-source/elixir/eidetic-projector/commits/master)
This library aims to make it trivial to consume events, from whatever source,
and run them through middleware.
## Install
**Everything likely to change as this is rolled out internally at GT8. Not recommended for use by anyone else; yet 😉**
## Consumer
Consumers are modules that subscribe to a data source and convert a payload into an Eidetic Projector Bundle. It's the responsiblity of the consumer to prepare the payload for the Projector and to convert the response into whatever the calling consumer expects.
```elixir
%Eidetic.Projector.Event{
# A map storing any information that is relevant from the consumer, such as topic consumed and offset
consumer: map(),
# Modifiers can be set by the preprocess middleware, to provide information that may change how the handler
# proceeds
modifiers: map(),
# A handler must be configured by one of the preprocess middlewares
handler: atom() | fun(),
# Event can be anything you want, we enforce nothing
event: any(),
# A map storing the result, which can be modified by middlewares and the actual handler
result: map()
}
```
## Middleware
Middleware should implement `Eidetic.Projector.Middleware`, which describes what to expect:
```elixir
@callback process(%Bundle{}) :: {:ok | :skip | :error, %Bundle{}}
```
The first element of the return tuple from the middleware instructs the projector how to proceed:
`:ok` means we're happy. Continue to call all other middleware and our handler
`:skip` means we do not wish to handle this bundle and should exit, without calling any other middleware, or the handler
`:error` means we experienced a problem handling this bundle and we should retry again soon. No other middleware, or the handler, is called.
It doesn't make a lot of sense for a `postprocess` handler to return anything other than an `:ok` tuple. We may disregard responses from `postprocess` handlers, but that isn't the case yet.
## Handler
There is **no** handler that can be configured up-front or globally. You **MUST** use the `preprocess` middleware to configure a handler on the `%Bundle{handler: handler}` struct.
The handler can be set to an atom, which will assume it's a module and call `handle/1`. The handler may also be a function.
The handler should also respect the middleware callback:
```elixir
@callback process(%Event{}) :: {:ok | :skip | :error, %Event{}}
```
## Shit I Don't Need
Yes, you'll find some Consumers, Handlers and Middleware in this repository that you don't need. As I said, you shouldn't be using it. These are here until we're stabilised the API; after which we'll remove them. I wonder if anyone will ever read this anyway 👀
If you do, drop us an email!
`developers@gt8.online`