Skip to content

Commit

Permalink
Emit host details updated event (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
fabriziosestito authored Jan 11, 2022
1 parent dd5f93c commit da61ec7
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 29 deletions.
14 changes: 11 additions & 3 deletions assets/js/state/hosts.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,25 @@ export const hostsListSlice = createSlice({
appendHost: (state, action) => {
state.hosts = [...state.hosts, action.payload];
},
updateHost: (state, action) => {
state.hosts = state.hosts.map((host) => {
if (host.id === action.payload.id) {
host = { ...host, ...action.payload }
}
return host;
});
},
setHeartbeatPassing: (state, action) => {
state.hosts = state.hosts.map((host) => {
if (host.id === action.payload.id_host) {
if (host.id === action.payload.id) {
host.heartbeat = "passing";
}
return host;
});
},
setHeartbeatCritical: (state, action) => {
state.hosts = state.hosts.map((host) => {
if (host.id === action.payload.id_host) {
if (host.id === action.payload.id) {
host.heartbeat = "critical";
}
return host;
Expand All @@ -41,7 +49,7 @@ export const hostsListSlice = createSlice({
},
});

export const { setHosts, appendHost, startLoading, stopLoading, setHeartbeatPassing, setHeartbeatCritical } =
export const { setHosts, appendHost, updateHost, startLoading, stopLoading, setHeartbeatPassing, setHeartbeatCritical } =
hostsListSlice.actions;

export default hostsListSlice.reducer;
4 changes: 4 additions & 0 deletions assets/js/state/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ const processChannelEvents = (store) => {
store.dispatch({ type: 'HOST_REGISTERED', payload })
);

channel.on('host_details_updated', (payload) =>
store.dispatch({ type: 'HOST_DETAILS_UPDATED', payload })
);

channel.on('heartbeat_succeded', (payload) =>
store.dispatch({ type: 'HEARTBEAT_SUCCEDED', payload })
);
Expand Down
12 changes: 10 additions & 2 deletions assets/js/state/sagas/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { get } from 'axios';
import { put, all, call, takeEvery } from 'redux-saga/effects';

import { appendHost, setHosts, startLoading, stopLoading, setHeartbeatPassing, setHeartbeatCritical }
import { appendHost, setHosts, updateHost, startLoading, stopLoading, setHeartbeatPassing, setHeartbeatCritical }
from '../hosts';
import { watchNotifications } from './notifications';

Expand Down Expand Up @@ -31,6 +31,14 @@ function* watchHostRegistered() {
yield takeEvery('HOST_REGISTERED', hostRegistered);
}

function* hostDetailsUpdated({ payload }) {
yield put(updateHost(payload));
}

function* watchHostDetailsUpdated() {
yield takeEvery('HOST_DETAILS_UPDATED', hostDetailsUpdated);
}

function* heartbeatSucceded({ payload }) {
yield put(setHeartbeatPassing(payload));
yield put(
Expand Down Expand Up @@ -60,5 +68,5 @@ function* watchHeartbeatFailed() {
}

export default function* rootSaga() {
yield all([initialDataFetch(), watchHostRegistered(), watchHeartbeatSucceded(), watchHeartbeatFailed(), watchNotifications()]);
yield all([initialDataFetch(), watchHostRegistered(), watchHostDetailsUpdated(), watchHeartbeatSucceded(), watchHeartbeatFailed(), watchNotifications()]);
}
17 changes: 17 additions & 0 deletions lib/tronto/monitoring/domain/hosts/events/host_details_updated.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
defmodule Tronto.Monitoring.Domain.Events.HostDetailsUpdated do
@moduledoc """
This event is emitted when host details are updated.
"""

use TypedStruct

@derive Jason.Encoder
typedstruct do
@typedoc "HostDetailsUpdated event"

field :id_host, String.t(), enforce: true
field :hostname, String.t(), enforce: true
field :ip_addresses, [String.t()], enforce: true
field :agent_version, String.t(), enforce: true
end
end
49 changes: 47 additions & 2 deletions lib/tronto/monitoring/domain/hosts/host.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule Tronto.Monitoring.Domain.Host do
alias Tronto.Monitoring.Domain.Events.{
HeartbeatFailed,
HeartbeatSucceded,
HostDetailsUpdated,
HostRegistered
}

Expand Down Expand Up @@ -49,13 +50,39 @@ defmodule Tronto.Monitoring.Domain.Host do
}
end

# Host exists but details didn't change
def execute(
%Host{id_host: _},
%RegisterHost{}
%Host{
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
},
%RegisterHost{
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
}
) do
[]
end

def execute(
%Host{},
%RegisterHost{
id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
}
) do
%HostDetailsUpdated{
id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
}
end

# Heartbeat received
def execute(
%Host{id_host: nil},
Expand Down Expand Up @@ -107,6 +134,24 @@ defmodule Tronto.Monitoring.Domain.Host do
}
end

def apply(
%Host{} = host,
%HostDetailsUpdated{
id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
}
) do
%Host{
host
| id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
}
end

def apply(
%Host{} = host,
%HeartbeatSucceded{id_host: id_host}
Expand Down
42 changes: 36 additions & 6 deletions lib/tronto/monitoring/projectors/host_projector.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ defmodule Tronto.Monitoring.HostProjector do
alias Tronto.Monitoring.Domain.Events.{
HeartbeatFailed,
HeartbeatSucceded,
HostDetailsUpdated,
HostRegistered
}

Expand Down Expand Up @@ -41,6 +42,27 @@ defmodule Tronto.Monitoring.HostProjector do
end
)

project(
%HostDetailsUpdated{
id_host: id,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
},
fn multi ->
changeset =
HostReadModel
|> Repo.get(id)
|> HostReadModel.changeset(%{
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
})

Ecto.Multi.update(multi, :host, changeset)
end
)

project(
%HeartbeatSucceded{id_host: id},
fn multi ->
Expand Down Expand Up @@ -79,30 +101,38 @@ defmodule Tronto.Monitoring.HostProjector do
end

def after_update(
%HeartbeatSucceded{id_host: id_host},
%HostDetailsUpdated{},
_,
%{host: host}
) do
TrontoWeb.Endpoint.broadcast("hosts:notifications", "host_details_updated", host)
end

def after_update(
%HeartbeatSucceded{},
_,
%{host: %HostReadModel{hostname: hostname}}
%{host: %HostReadModel{id: id, hostname: hostname}}
) do
TrontoWeb.Endpoint.broadcast(
"hosts:notifications",
"heartbeat_succeded",
%{
id_host: id_host,
id: id,
hostname: hostname
}
)
end

def after_update(
%HeartbeatFailed{id_host: id_host},
%HeartbeatFailed{},
_,
%{host: %HostReadModel{hostname: hostname}}
%{host: %HostReadModel{id: id, hostname: hostname}}
) do
TrontoWeb.Endpoint.broadcast(
"hosts:notifications",
"heartbeat_failed",
%{
id_host: id_host,
id: id,
hostname: hostname
}
)
Expand Down
2 changes: 1 addition & 1 deletion lib/tronto_web/controllers/host_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule TrontoWeb.HostController do
|> put_status(:accepted)
|> json(%{})

{:error, reason} ->
{:error, _, reason, _} ->
conn
|> put_status(:bad_request)
|> json(%{error: reason})
Expand Down
89 changes: 74 additions & 15 deletions test/tronto/monitoring/domain/host/host_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ defmodule Tronto.Monitoring.HostTest do
alias Tronto.Monitoring.Domain.Events.{
HeartbeatFailed,
HeartbeatSucceded,
HostDetailsUpdated,
HostRegistered
}

Expand Down Expand Up @@ -53,27 +54,85 @@ defmodule Tronto.Monitoring.HostTest do
)
end

test "should not register a host if it is already registered" do
test "should update host details if it is already registered" do
id_host = Faker.UUID.v4()
new_hostname = Faker.StarWars.character()
new_ip_addresses = [Faker.Internet.ip_v4_address()]
new_agent_version = Faker.Internet.slug()

initial_events = [
%HostRegistered{
id_host: Faker.UUID.v4(),
hostname: Faker.StarWars.character(),
ip_addresses: [Faker.Internet.ip_v4_address()],
agent_version: Faker.Internet.slug(),
heartbeat: :unknown
}
]

commands = [
RegisterHost.new!(
id_host: id_host,
hostname: new_hostname,
ip_addresses: new_ip_addresses,
agent_version: new_agent_version
)
]

assert_events(
initial_events,
commands,
[
%HostRegistered{
%HostDetailsUpdated{
id_host: id_host,
hostname: Faker.StarWars.character(),
ip_addresses: [Faker.Internet.ip_v4_address()],
agent_version: Faker.Internet.slug(),
heartbeat: :unknown
hostname: new_hostname,
ip_addresses: new_ip_addresses,
agent_version: new_agent_version
}
],
[
RegisterHost.new!(
id_host: id_host,
hostname: Faker.StarWars.character(),
ip_addresses: [Faker.Internet.ip_v4_address()],
agent_version: Faker.Internet.slug()
)
],
]
)

assert_state(
initial_events,
commands,
%Host{
id_host: id_host,
hostname: new_hostname,
ip_addresses: new_ip_addresses,
agent_version: new_agent_version,
heartbeat: :unknown
}
)
end

test "should not update host details if the same details were already registered" do
id_host = Faker.UUID.v4()
hostname = Faker.StarWars.character()
ip_addresses = [Faker.Internet.ip_v4_address()]
agent_version = Faker.Internet.slug()

initial_events = [
%HostRegistered{
id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version,
heartbeat: :unknown
}
]

commands = [
RegisterHost.new!(
id_host: id_host,
hostname: hostname,
ip_addresses: ip_addresses,
agent_version: agent_version
)
]

assert_events(
initial_events,
commands,
[]
)
end
Expand Down

0 comments on commit da61ec7

Please sign in to comment.