Skip to content

Commit 9eff5e2

Browse files
committed
#106: work in progress: fixing unit tests
1 parent b4ff435 commit 9eff5e2

22 files changed

+258
-134
lines changed

insights/assets/css/app.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@
3939
background-color: #cbe2fc;
4040
}
4141

42+
a.list-group-item.selected {
43+
font-weight: bold;
44+
}
45+
4246
.separator {
4347
height: 5px;
4448
background-color: rgba(0, 0, 0, 0.125) !important;

insights/lib/insights/event_handler.ex

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ defmodule Insights.EventHandler do
2525
end
2626

2727
def handle_info({:broadcast, :topology, event}, state) do
28-
## info("Receiving topology event: #{inspect event}")
2928
Phoenix.PubSub.local_broadcast(Insights.PubSub, "topology", event)
3029
{:noreply, state}
3130
end
3231

32+
def handle_info({:broadcast, :commands, event}, state) do
33+
Phoenix.PubSub.local_broadcast(Insights.PubSub, "commands", event)
34+
{:noreply, state}
35+
end
36+
3337
def handle_info(_message, state) do
3438
## info("Receiving message: #{inspect message}")
3539
{:noreply, state}

insights/lib/insights/test.ex

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
defmodule Insights.Test do
2+
3+
require Logger
4+
5+
@host_unreachable 6
6+
@host_not_found 7
7+
@network_timeout 89
8+
@shutdown_in_progress 91
9+
@primary_stepped_down 189
10+
@exceeded_time_limit 262
11+
@socket_exception 9001
12+
@not_master 10107
13+
@interrupted_at_shutdown 11600
14+
@interrupted_due_to_repl_state_change 11602
15+
@not_master_no_slaveok 13435
16+
@not_master_or_secondary 13436
17+
@stale_shard_version 63
18+
@stale_epoch 150
19+
#@stale_config 13388
20+
@retry_change_stream 234
21+
@failed_to_satisfy_read_preference 133
22+
23+
@resumxable [@host_unreachable, @host_not_found, @network_timeout, @shutdown_in_progress, @primary_stepped_down,
24+
@exceeded_time_limit, @socket_exception, @not_master, @interrupted_at_shutdown, @interrupted_at_shutdown,
25+
@interrupted_due_to_repl_state_change, @not_master_no_slaveok, @not_master_or_secondary, @stale_shard_version,
26+
@stale_epoch, @retry_change_stream, @failed_to_satisfy_read_preference] #@stale_config,
27+
28+
@resumable [@primary_stepped_down ]
29+
def test() do
30+
@resumable
31+
|> Enum.map(fn code ->
32+
33+
fail_cmd = [
34+
configureFailPoint: "failCommand",
35+
mode: %{times: 1},
36+
data: [errorCode: code, failCommands: ["find"]]
37+
]
38+
39+
{:ok, _} = Mongo.admin_command(:mongo, fail_cmd)
40+
{:error, msg} = Mongo.find_one(:mongo, "test", %{})
41+
Logger.info("Error: #{inspect msg}")
42+
end)
43+
end
44+
end
45+

insights/lib/insights_web/live/topology_live.ex

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ defmodule InsightsWeb.TopologyLive do
1212

1313
if connected?(socket) do
1414
Phoenix.PubSub.subscribe(Insights.PubSub, "topology")
15+
Phoenix.PubSub.subscribe(Insights.PubSub, "commands")
1516
end
1617

1718
{:ok, reset_defaults(socket)}
@@ -23,16 +24,45 @@ defmodule InsightsWeb.TopologyLive do
2324
end
2425

2526
@impl true
26-
def handle_info(%Mongo.Events.ServerDescriptionChangedEvent{}, socket) do
27-
{:noreply, reset_defaults(socket)}
28-
end
27+
def handle_info(%Mongo.Events.ServerDescriptionChangedEvent{} = event, %{assigns: %{events: events}} = socket) do
28+
29+
event = event
30+
|> Map.put(:time_stamp, DateTime.utc_now())
31+
|> Map.put(:id, random_string(10))
32+
events = [event | events] |> Enum.take(10)
33+
socket = socket
34+
|> set_topology(Topology.get_state(:mongo))
35+
|> assign(events: events)
2936

30-
def handle_info(_message, socket) do
3137
{:noreply, socket}
3238
end
3339

40+
def handle_info(event, %{assigns: %{events: events}} = socket) do
41+
event = event
42+
|> Map.put(:time_stamp, DateTime.utc_now())
43+
|> Map.put(:id, random_string(10))
44+
events = [event | events] |> Enum.take(10)
45+
{:noreply, assign(socket, events: events)}
46+
end
47+
48+
def handle_event("show-events", _params, socket) do
49+
{:noreply, assign(socket, tab: "events")}
50+
end
51+
52+
def handle_event("show-details", _params, socket) do
53+
{:noreply, assign(socket, tab: "details")}
54+
end
55+
56+
def handle_event("select-event", %{"id" => event_id}, %{assigns: %{events: events}} = socket) do
57+
{:noreply, assign(socket, event: Enum.find(events, fn %{id: id} -> event_id == id end))}
58+
end
59+
3460
defp reset_defaults(socket) do
35-
set_topology(socket, Topology.get_state(:mongo))
61+
socket
62+
|> set_topology(Topology.get_state(:mongo))
63+
|> assign(events: [])
64+
|> assign(tab: "details")
65+
|> assign(event: nil)
3666
end
3767

3868
def set_topology(socket, %{topology: %{servers: servers} = topology, monitors: monitors}) do
@@ -54,5 +84,9 @@ defmodule InsightsWeb.TopologyLive do
5484
|> assign(monitors: [])
5585
end
5686

87+
def random_string(length) do
88+
:crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
89+
end
90+
5791

5892
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<div class="row">
2+
<div class="col-6">
3+
<%= if @topology do %>
4+
<ul class="list-group stripes">
5+
<li class="list-group-item d-flex justify-content-between"><label>Type:</label><%= @topology.type%></li>
6+
<li class="list-group-item d-flex justify-content-between"><label>Heartbeat frequency ms:</label><%= @topology.heartbeat_frequency_ms%></li>
7+
<li class="list-group-item d-flex justify-content-between"><label>Local threshold ms:</label><%= @topology.local_threshold_ms%></li>
8+
<li class="list-group-item d-flex justify-content-between"><label>Compatible:</label><%= @topology.compatible%></li>
9+
</ul>
10+
<% else %>
11+
<div class="alert alert-warning">
12+
<p>No topology entry found!</p>
13+
</div>
14+
<% end %>
15+
</div>
16+
</div>
17+
<div class="row mt-3">
18+
<div class="col-12">
19+
<h2 class="mt-3">Servers</h2>
20+
<%= for server <- @servers do %>
21+
<div class="row mt-3">
22+
<div class="col-6">
23+
<%= render InsightsWeb.TopologyView, "server.html", server: server %>
24+
</div>
25+
<div class="col-6">
26+
<%= render InsightsWeb.TopologyView, "monitor.html", monitor: Map.get(@monitors, server.address) %>
27+
</div>
28+
</div>
29+
<% end %>
30+
</div>
31+
</div>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<a href="javascript:void(0);" phx-click="select-event" phx-value-id={@event.id} class={"list-group-item d-flex justify-content-between #{event_selected?(@event.id == @select_event_id)}"}><label><%= @event.time_stamp%>:</label><%= event_name(@event)%></a>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<div class="row">
2+
<div class="col-8">
3+
<div class="list-group stripes">
4+
<%= for event <- @events do %>
5+
<%= if @event do %>
6+
<%= render InsightsWeb.TopologyView, "event.html", event: event, select_event_id: @event.id %>
7+
<% else %>
8+
<%= render InsightsWeb.TopologyView, "event.html", event: event, select_event_id: nil %>
9+
<% end %>
10+
<% end %>
11+
</div>
12+
</div>
13+
</div>
14+
15+
<%= if @event do %>
16+
<h5 class="mt-3"><%= event_name(@event)%></h5>
17+
<div class="row mt-3">
18+
<div class="col-8">
19+
<ul class="list-group stripes">
20+
<li class="list-group-item d-flex justify-content-between"><label>Timestamp:</label><%= @event.time_stamp%></li>
21+
</ul>
22+
</div>
23+
</div>
24+
<% end %>
Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,21 @@
11
<div class="container mt-5">
22
<h1>Topology</h1>
33

4-
<div class="row">
5-
<div class="col-6">
6-
<%= if @topology do %>
7-
<ul class="list-group stripes">
8-
<li class="list-group-item d-flex justify-content-between"><label>Type:</label><%= @topology.type%></li>
9-
<li class="list-group-item d-flex justify-content-between"><label>Heartbeat frequency ms:</label><%= @topology.heartbeat_frequency_ms%></li>
10-
<li class="list-group-item d-flex justify-content-between"><label>Local threshold ms:</label><%= @topology.local_threshold_ms%></li>
11-
<li class="list-group-item d-flex justify-content-between"><label>Compatible:</label><%= @topology.compatible%></li>
12-
</ul>
13-
<% else %>
14-
<div class="alert alert-warning">
15-
<p>No topology entry found!</p>
16-
</div>
17-
<% end %>
4+
<ul class="nav nav-tabs">
5+
<li class="nav-item">
6+
<a class={"nav-link #{tab_active("details", @tab)}"} phx-click="show-details" href="javascript:void(0);">Details</a>
7+
</li>
8+
<li class="nav-item">
9+
<a class={"nav-link #{tab_active("events", @tab)}"} phx-click="show-events" href="javascript:void(0);">Events</a>
10+
</li>
11+
</ul>
12+
<div class="tab-content pt-3 bg-white p-3 border-bottom border-end border-start">
13+
<div class={"tab-pane fade show #{tab_active("details", @tab)}"} id="details">
14+
<%= render InsightsWeb.TopologyView, "details.html", assigns %>
1815
</div>
19-
</div>
20-
<div class="row mt-3">
21-
<div class="col-12">
22-
<h2 class="mt-3">Servers</h2>
23-
<%= for server <- @servers do %>
24-
<div class="row mt-3">
25-
<div class="col-6">
26-
<%= render InsightsWeb.TopologyView, "server.html", server: server %>
27-
</div>
28-
<div class="col-6">
29-
<%= render InsightsWeb.TopologyView, "monitor.html", monitor: Map.get(@monitors, server.address) %>
30-
</div>
31-
</div>
32-
<% end %>
16+
<div class={"tab-pane fade show #{tab_active("events", @tab)}"} id="events">
17+
<%= render InsightsWeb.TopologyView, "events.html", assigns %>
3318
</div>
3419
</div>
20+
3521
</div>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,27 @@
11
defmodule InsightsWeb.TopologyView do
22
use InsightsWeb, :view
3+
4+
def event_name(%{__struct__: name} = struct) do
5+
name
6+
|> Module.split
7+
|> Enum.join(".")
8+
end
9+
10+
@doc """
11+
Support for tabs
12+
"""
13+
def tab_active(tab, current) do
14+
case tab == current do
15+
true -> "active"
16+
false -> []
17+
end
18+
end
19+
20+
def event_selected?(true) do
21+
"selected"
22+
end
23+
24+
def event_selected?(_) do
25+
[]
26+
end
327
end

lib/mongo.ex

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,6 @@ defmodule Mongo do
6969
# 5000
7070
@timeout 15000
7171

72-
@dialyzer [no_match: [count_documents!: 4]]
73-
7472
@type conn :: DbConnection.Conn
7573
@type collection :: String.t()
7674
@opaque cursor :: Mongo.Cursor.t()
@@ -805,19 +803,12 @@ defmodule Mongo do
805803
def exec_command_session(session, cmd, opts) do
806804
with {:ok, conn, new_cmd} <- Session.bind_session(session, cmd),
807805
{:ok, _cmd, response} <- DBConnection.execute(conn, %Query{action: :command}, [new_cmd], defaults(opts)),
808-
doc <- Session.update_session(session, response, opts), ## todo
809-
{:ok, _flags, doc} <- check_for_error(response) do
806+
:ok <- Session.update_session(session, response, opts),
807+
{:ok, {_flags, doc}} <- check_for_error(response) do
810808
{:ok, doc}
811809
else
812810
{:error, error} ->
813-
case Error.not_writable_primary_or_recovering?(error, opts) do
814-
true ->
815-
Session.mark_server_unknown(session)
816-
{:error, error}
817-
818-
false ->
819-
{:error, error}
820-
end
811+
{:error, error}
821812
end
822813
end
823814

@@ -853,8 +844,6 @@ defmodule Mongo do
853844
end
854845

855846
defp check_for_error({doc, event, _flags, duration}) do
856-
857-
Logger.info("Checking Error: #{inspect doc}")
858847
error = Mongo.Error.exception(doc)
859848

860849
Events.notify(
@@ -996,8 +985,7 @@ defmodule Mongo do
996985
with {:ok, doc} <- issue_command(topology_pid, cmd, :write, opts) do
997986
case doc do
998987
%{"writeErrors" => _} ->
999-
{:error,
1000-
%Mongo.WriteError{n: doc["n"], ok: doc["ok"], write_errors: doc["writeErrors"]}}
988+
{:error, %Mongo.WriteError{n: doc["n"], ok: doc["ok"], write_errors: doc["writeErrors"]}}
1001989

1002990
_ ->
1003991
case acknowledged?(write_concern) do
@@ -1480,13 +1468,7 @@ defmodule Mongo do
14801468
##
14811469
# Checks the validity of the document structure. that means either you use binaries or atoms as a key, but not in combination of both.
14821470
#
1483-
# todo support for structs
14841471
defp normalize_doc(doc) do
1485-
# doc = case Map.has_key?(doc, :__struct__) do
1486-
# true -> Map.to_list(doc)
1487-
# false -> doc
1488-
# end
1489-
14901472
Enum.reduce(doc, {:unknown, []}, fn
14911473
{key, _value}, {:binary, _acc} when is_atom(key) -> invalid_doc(doc)
14921474
{key, _value}, {:atom, _acc} when is_binary(key) -> invalid_doc(doc)

0 commit comments

Comments
 (0)