Skip to content

Commit

Permalink
first draft insert_node_events
Browse files Browse the repository at this point in the history
  • Loading branch information
sorax committed Mar 19, 2024
1 parent b4d3a84 commit 2d1afca
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 58 deletions.
19 changes: 19 additions & 0 deletions lib/radiator/outline/dispatch.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
defmodule Radiator.Outline.Dispatch do
@moduledoc false

alias Radiator.Outline.Event
alias Radiator.Outline.EventProducer

def insert_node(attributes, user_id, event_id) do
"insert_node"
|> Event.build(attributes, user_id, event_id)
|> EventProducer.enqueue()
end

# TODO
# update_node
# delete_node
# move_node

# list_node different case, sync call
end
7 changes: 4 additions & 3 deletions lib/radiator/outline/event.ex
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
defmodule Radiator.Outline.Event do
@moduledoc false

def build(event_id, event_type, user_id, payload) do
%{
alias Radiator.Outline.Event.InsertNodeEvent

def build("insert_node", payload, user_id, event_id) do
%InsertNodeEvent{
event_id: event_id,
event_type: event_type,
user_id: user_id,
payload: payload
}
Expand Down
3 changes: 3 additions & 0 deletions lib/radiator/outline/event/insert_node_event.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
defmodule Radiator.Outline.Event.InsertNodeEvent do

Check warning on line 1 in lib/radiator/outline/event/insert_node_event.ex

View workflow job for this annotation

GitHub Actions / Build & Test

Modules should have a @moduledoc tag.
defstruct [:event_id, :user_id, :payload]
end
37 changes: 20 additions & 17 deletions lib/radiator/outline/event_consumer.ex
Original file line number Diff line number Diff line change
@@ -1,43 +1,46 @@
defmodule Radiator.Outline.EventConsumer do

Check warning on line 1 in lib/radiator/outline/event_consumer.ex

View workflow job for this annotation

GitHub Actions / Build & Test

Modules should have a @moduledoc tag.
use GenStage

alias Radiator.Outline
alias Radiator.Outline.EventProducer
alias Radiator.Outline.Event.InsertNodeEvent

def start_link(opts \\ []) do
GenStage.start_link(__MODULE__, opts, name: __MODULE__)
end

def init(_opts) do
options = []
{:consumer, :event_producer, subscribe_to: [{EventProducer, options}]}
def init(opts \\ [max_demand: 1]) do
{:consumer, :event_producer, subscribe_to: [{EventProducer, opts}]}
end

def handle_events(events, _from, state) do
IO.inspect(events, label: "EventConsumer handle_events")

Enum.each(events, fn event ->
process_event(event, state)
IO.inspect(event, label: "EventConsumer handle_events event")
end)
def handle_events([event], _from, state) do
process_event(event)

{:noreply, [], state}
end

defp process_event(%InsertNodeEvent{} = event) do
# validate
defp process_event(%InsertNodeEvent{payload: payload} = _event) do
payload
|> Outline.create_node()
|> handle_insert_result()

# validate
# true->
# database action: insert node()
# create && persist event (event contains all attributes, user, event_id, timestamps)
# broadcast event (topic: episode_id)
# broadcast node (topic: episode_id)
# false->
# log error and return error (audit log)
end

defp handle_result(:ok, event) do
persist_event(event)
broadcast_success(event)
defp handle_insert_result({:ok, node}) do
{:ok, node}
end

defp handle_result(:error, event) do
broadcast_error(event)
defp handle_insert_result({:error, _error}) do
# log_error_please :-)

:error
end
end
24 changes: 17 additions & 7 deletions lib/radiator/outline/event_producer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,31 @@ defmodule Radiator.Outline.EventProducer do
end

def init(_opts) do
{:producer, []}
{:producer, {:queue.new(), 0}}
end

def enqueue(event) do
GenStage.cast(__MODULE__, {:enqueue, event})
:ok
end

def handle_cast({:enqueue, event}, state) do
IO.inspect(state, label: "EventProducer. handle_cast")
{:noreply, [event], state}
def handle_cast({:enqueue, event}, {queue, 0}) do
queue = :queue.in(event, queue)
{:noreply, [], {queue, 0}}
end

def handle_demand(demand, state) do
IO.inspect(demand, label: "EventConsumer")
{:noreply, [], state}
def handle_cast({:enqueue, event}, {queue, demand}) do
queue = :queue.in(event, queue)
{{:value, event}, queue} = :queue.out(queue)
{:noreply, [event], {queue, demand - 1}}
end

def handle_demand(_incoming, {queue, demand}) do
with {item, queue} <- :queue.out(queue),
{:value, event} <- item do
{:noreply, [event], {queue, demand}}
else
_ -> {:noreply, [], {queue, demand + 1}}
end
end
end
31 changes: 0 additions & 31 deletions lib/radiator/outline/server.ex

This file was deleted.

34 changes: 34 additions & 0 deletions test/radiator/outline/dispatch_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule Radiator.Outline.DispatchTest do
use Radiator.DataCase

import Radiator.AccountsFixtures
import Radiator.PodcastFixtures

# alias Radiator.Outline
alias Radiator.Outline.Dispatch
alias Radiator.Outline.Node

describe "outline dispatch" do
setup do
%{episode: episode_fixture()}
end

test "insert_node does WHAT?", %{episode: episode} do
user = user_fixture()

node = %Node{episode_id: episode.id, content: "something very special 1!1"}
attributes = Map.from_struct(node)

event_id = Ecto.UUID.generate()

Dispatch.insert_node(attributes, user.id, event_id)

# _inserted_node =
# Outline.list_nodes()
# |> Enum.find(&(&1.content == "something very special 1!1"))

# assert inserted_node.episode_id == node.episode_id
# assert inserted_node.content == node.content
end
end
end

0 comments on commit 2d1afca

Please sign in to comment.