# Eidetic Projector

[![build status](](
[![code coverage](](

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.

    # 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:

@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:

@callback process(%Bundle{}) :: {:ok | :skip | :error, %Bundle{}}

## 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!