Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add projector for host checks selection #1542

Merged
merged 4 commits into from
Jun 22, 2023
Merged

Add projector for host checks selection #1542

merged 4 commits into from
Jun 22, 2023

Conversation

EMaksy
Copy link
Member

@EMaksy EMaksy commented Jun 19, 2023

Description

This pull request introduces a new projector function, Trento.HostProjector, which handles host checks selection. Additionally, broadcasting functionality has been implemented to notify subscribed clients of any changes.

The database read model and migration have been updated to include a new column, selected_checks, in the hosts table.

How was this tested?

Automated test was added + manually tested

@EMaksy EMaksy added enhancement New feature or request elixir Pull requests that update Elixir code labels Jun 19, 2023
@EMaksy EMaksy self-assigned this Jun 19, 2023
@EMaksy EMaksy force-pushed the host-checks-projector branch 6 times, most recently from 71ca1f9 to 45a3a62 Compare June 19, 2023 14:20
Copy link
Contributor

@dottorblaster dottorblaster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nitpick then we can merge

lib/trento/application/projectors/host_projector.ex Outdated Show resolved Hide resolved
Copy link
Contributor

@arbulu89 arbulu89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some more nitpicks

@EMaksy EMaksy force-pushed the host-checks-projector branch 3 times, most recently from 8fdf446 to c99ecfc Compare June 21, 2023 15:33
changeset =
HostReadModel
|> Repo.get(id)
# TODO: couldn't make it work with Ecto.Multi
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, about this, i don't like it, but like in the cluster projector, but i spend multiple hours to make it work "right" but i could not find a way for it.
See:

# TODO: couldn't make it work with Ecto.Multi

So i'm open for suggestions or we track it as a tech debt, what do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EMaksy There are some reasons why this is happening. The main one is that you have default: [] for selected_checks in the read model. With this, ecto has some emtpy_fields logic which if the values is empty, it will default it, so in this case, as the default and the new empty value are the same, there is no changeset.

https://hexdocs.pm/ecto/Ecto.Changeset.html#cast/4

With this default, you are forced to have something different. Something like HostReadModel.changeset(%HostReadModel{id: "240f96b1-8d26-53b7-9e99-ffb0f2e735bf", selected_checks: [nil]}, %{selected_checks: []}) would work, but in the past we agreed to not use it, as it it looks like a trick.

The same happens when you want to set nil to values, as most of the times nil is the default value.

There are other options like setting force_changes in the cast function within our changeset, but this would require to change the changeset function to allow additional options, which looks an overkill.

I would go with the current solution.
In any case, i would remove the comment above, or at least the reference to ClusterReadModel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bottom line, same as @arbulu89 said. We already had this debate a couple times, and this is just the right way to do that. We should actually remove that comment in some places 😬

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay guys thanks for the additional information, then let's stick with this implementation, i will remove the comment :D

@EMaksy EMaksy force-pushed the host-checks-projector branch from 32b8064 to fd868a2 Compare June 21, 2023 15:56
@EMaksy EMaksy marked this pull request as ready for review June 21, 2023 16:00
message =
HostView.render(
"host_checks_updated.json",
%{host: %HostReadModel{id: id, selected_checks: checks}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use HostReadModel here as the view doesn't expect that.
It simply expects a map with id and selected_checks.
%{id: id, selected_checks: checks} should be it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

%{host: %HostReadModel{id: id, selected_checks: checks}}
)

TrentoWeb.Endpoint.broadcast("monitoring:hosts", "host_checks_updated", message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't create a new event for this. We can use host_details_updated I guess.
This way, we already handle this event and we don't need to touch the frontend redux state.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Let's keep it consistent with what happens in the cluster.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sounds good to me i won't add the host_checks_updated event and stick with host_details_updated

changeset =
HostReadModel
|> Repo.get(id)
# TODO: couldn't make it work with Ecto.Multi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@EMaksy There are some reasons why this is happening. The main one is that you have default: [] for selected_checks in the read model. With this, ecto has some emtpy_fields logic which if the values is empty, it will default it, so in this case, as the default and the new empty value are the same, there is no changeset.

https://hexdocs.pm/ecto/Ecto.Changeset.html#cast/4

With this default, you are forced to have something different. Something like HostReadModel.changeset(%HostReadModel{id: "240f96b1-8d26-53b7-9e99-ffb0f2e735bf", selected_checks: [nil]}, %{selected_checks: []}) would work, but in the past we agreed to not use it, as it it looks like a trick.

The same happens when you want to set nil to values, as most of the times nil is the default value.

There are other options like setting force_changes in the cast function within our changeset, but this would require to change the changeset function to allow additional options, which looks an overkill.

I would go with the current solution.
In any case, i would remove the comment above, or at least the reference to ClusterReadModel

test/trento/application/projectors/host_projector_test.exs Outdated Show resolved Hide resolved
%{checks: []}
]

Enum.each(test_checks_data, fn %{checks: checks} ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if people is aware of the common for in elixir hehe
for %{checks: checks} <- tests_checks_data do

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oki fair point, Enum.each was just the first thing which shot in my mind :D

test "should update the selected_checks field when event is received" do
%{id: host_id} = insert(:host, id: UUID.uuid4())

test_checks_data = [
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a big fan of this name. I would go with cases or scenarios.
Anyway, not strong opinions at all

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough :D

Copy link
Member

@nelsonkopliku nelsonkopliku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great @EMaksy! Welcome to the es/cqrs wonders 😄
Nothing to add besides what already shared.

Copy link
Contributor

@dottorblaster dottorblaster left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you adress @arbulu89's comments LGTM

@EMaksy EMaksy force-pushed the host-checks-projector branch from eb2364d to d770eaf Compare June 22, 2023 11:44
@EMaksy EMaksy force-pushed the host-checks-projector branch from d770eaf to 9441dd1 Compare June 22, 2023 11:45
@EMaksy EMaksy force-pushed the host-checks-projector branch 2 times, most recently from 8820908 to 29bc275 Compare June 22, 2023 11:53
@EMaksy EMaksy merged commit 5d04a50 into main Jun 22, 2023
@EMaksy EMaksy deleted the host-checks-projector branch June 22, 2023 12:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
elixir Pull requests that update Elixir code enhancement New feature or request
Development

Successfully merging this pull request may close these issues.

4 participants