# Seqy
Seqy is an events sequentializer. Need to process events in a specific order? Seqy can help.
## Under Seqy's Hood
```mermaid
graph TD
A[Seqy] --> B(Seqy.Processbook)
A --> C[topic_1_supervisor]
A --> D[topic_2_supervisor]
C --> E[topic_1_queue_1]
C --> F[topic_1_queue_2]
```
When `Seqy` is started, it also starts `Seqy.Processbook` and a supervisor for each sequence topic configured.
`Seqy.Processbook` is responsible for storing the `pid` of the process that would handle the processing of a specific event queue.
Once you enqueue an event, `Seqy` would check in the processbook if there's an active handler for the specific `queue_id`.
If there's none, `Seqy` would start an instance of the handler under the corresponding topic supervisor. When all the events are
exhausted, the handler for the specific queue would terminate.
## Installation
Add `seqy` as a dependency on your `mix.exs` file.
```elixir
def deps do
[
{:seqy, "~> 0.1.0"}
]
end
```
## Configuration
To make Seqy work, you need to define the topic, events and handler module.
```elixir
config :seqy,
topics: [
%{
name: :user_purchase,
actions: [:"user.created", :"user.purchased", :"user.paid"],
handler: MyApp.EventHandler
}
]
```
`actions` should have the desired order for processing the events.
## Usage
Before enqueueing events with Seqy, you need to define a handler for the topic.
To define a handler, create a module that `use` the `Seqy.Handler` module. Then,
implement the `handle/1` callback for each event you expect in the sequence.
```elixir
defmodule MyApp.EventHandler do
use Seqy.Handler
require Logger
def handle(%Seqy.Event{action: :"user.created", args: %{user_id: user_id}}) do
Logger.info("#{user_id} has been created.")
end
def handle(%Seqy.Event{action: :"user.purchased", args: %{user_id: user_id}}) do
Logger.info("#{user_id} has purchased an item.")
end
def handle(%Seqy.Event{action: :"user.paid", args: %{user_id: user_id}}) do
Logger.info("#{user_id} has paid.")
end
end
```
With the event handler ready, we can start enqueueing events to Seqy.
```elixir
%{action: :"user.created", queue_id: "user_id:1", topic: :user_purchase, args: %{user_id: 1}}
|> Seqy.new()
|> Seqy.enqueue()
```
An event should have the ff:
- `action` - event action that would be used for ordering
- `queue_id` - this would be used as the routing key
- `topic` - topic of the sequence you declared in your config
- `args` - event payload