Skip to content

Commit f79c8f3

Browse files
committed
properly send events and delete state server record
1 parent 9a9be5f commit f79c8f3

4 files changed

Lines changed: 31 additions & 17 deletions

File tree

lib/live_debugger/gen_servers/ets_table_server.ex

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,8 @@ defmodule LiveDebugger.GenServers.EtsTableServer do
100100
@impl true
101101
def handle_call({:watch, pid}, {watcher, _}, state) do
102102
case Map.get(state, pid) do
103-
%TableInfo{watchers: watchers} = table_info ->
104-
updated_watchers = MapSet.put(watchers, watcher)
105-
106-
updated_state =
107-
Map.put(state, pid, %{table_info | watchers: updated_watchers})
103+
%TableInfo{} ->
104+
updated_state = update_watchers(state, pid, &MapSet.put(&1, watcher))
108105

109106
Process.monitor(watcher)
110107

@@ -144,27 +141,32 @@ defmodule LiveDebugger.GenServers.EtsTableServer do
144141
defp maybe_delete_ets_table(state, pid) do
145142
with {%TableInfo{alive?: false} = table_info, updated_state} <- Map.pop(state, pid),
146143
true <- Enum.empty?(table_info.watchers) do
144+
PubSubUtils.process_status_topic()
145+
|> PubSubUtils.broadcast({:process_status, {:not_watched, pid}})
146+
147147
:ets.delete(table_info.table)
148-
IO.inspect(pid, label: "DELETING TABLE")
149148
updated_state
150149
else
151150
_ ->
152151
state
153152
end
154153
end
155154

156-
@spec remove_watcher(state(), pid()) :: {state(), [pid()]}
155+
@spec remove_watcher(state(), pid()) :: {updated_state :: state(), touched_pids :: [pid()]}
157156
defp remove_watcher(state, watcher) when is_pid(watcher) do
158-
Enum.reduce(state, {state, []}, fn {pid, %{watchers: watchers} = table_info},
159-
{state_acc, pids} ->
157+
Enum.reduce(state, {state, []}, fn {pid, %{watchers: watchers}}, {state_acc, pids} ->
160158
if Enum.member?(watchers, watcher) do
161-
updated_state =
162-
Map.put(state_acc, pid, %{table_info | watchers: MapSet.delete(watchers, watcher)})
159+
updated_state = update_watchers(state_acc, pid, &MapSet.delete(&1, watcher))
163160

164161
{updated_state, [pid | pids]}
165162
else
166163
{state_acc, pids}
167164
end
168165
end)
169166
end
167+
168+
defp update_watchers(state, pid, update_fn) when is_map_key(state, pid) do
169+
table_info = Map.get(state, pid)
170+
Map.put(state, pid, %{table_info | watchers: update_fn.(table_info.watchers)})
171+
end
170172
end

lib/live_debugger/gen_servers/state_server.ex

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ defmodule LiveDebugger.GenServers.StateServer do
6767
{:noreply, state}
6868
end
6969

70-
def handle_info({:process_status, {:dead, pid}}, state) do
70+
def handle_info({:process_status, {:not_watched, pid}}, state) do
7171
:ets.delete(@ets_table_name, record_id(pid))
7272

7373
{:noreply, state}
7474
end
7575

76+
def handle_info({:process_status, _}, state), do: {:noreply, state}
77+
7678
defp save_state(%Trace{pid: pid} = trace) do
7779
with {:ok, channel_state} <- ProcessService.state(pid) do
7880
record_id = record_id(pid)

lib/live_debugger/structs/lv_process.ex

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ defmodule LiveDebugger.Structs.LvProcess do
1616
:module,
1717
:nested?,
1818
:debugger?,
19-
:embedded?
19+
:embedded?,
20+
alive?: true
2021
]
2122

2223
@type t() :: %__MODULE__{
@@ -28,7 +29,8 @@ defmodule LiveDebugger.Structs.LvProcess do
2829
module: module(),
2930
nested?: boolean(),
3031
embedded?: boolean(),
31-
debugger?: boolean()
32+
debugger?: boolean(),
33+
alive?: boolean()
3234
}
3335

3436
@spec new(pid :: pid(), socket :: Phoenix.LiveView.Socket.t()) :: t()

lib/live_debugger_web/hooks/linked_view.ex

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule LiveDebuggerWeb.Hooks.LinkedView do
77
- If the `lv_process` assign is not found, it will try to find a successor LiveView process and navigate to it.
88
- If no successor is found, it will navigate to the error page.
99
10-
It also handles a case when the LiveView process dies by trying to find a successor LiveView process.
10+
It also handles situation when process dies by updating `lv_process.alive?` field.
1111
1212
The only thing you need to do after adding this hook is to handle loading state in the template.
1313
## Example
@@ -89,7 +89,7 @@ defmodule LiveDebuggerWeb.Hooks.LinkedView do
8989
)
9090
when is_pid(pid) do
9191
socket
92-
|> find_successor_lv_process()
92+
|> make_lv_process_dead()
9393
|> halt()
9494
end
9595

@@ -124,7 +124,7 @@ defmodule LiveDebuggerWeb.Hooks.LinkedView do
124124
end
125125

126126
defp fetch_lv_process_with_retries(pid) do
127-
fn -> fetch_with_retries(fn -> LiveViewDiscoveryService.lv_process(pid) end) end
127+
fn -> fetch_with_retries(fn -> LvProcess.new(pid) end) end
128128
end
129129

130130
defp fetch_with_retries(function) do
@@ -138,4 +138,12 @@ defmodule LiveDebuggerWeb.Hooks.LinkedView do
138138
Process.sleep(milliseconds)
139139
function.()
140140
end
141+
142+
defp make_lv_process_dead(
143+
%{assigns: %{lv_process: %AsyncResult{ok?: true, result: result}}} = socket
144+
) do
145+
lv_process = AsyncResult.ok(%LvProcess{result | alive?: false})
146+
147+
assign(socket, :lv_process, lv_process)
148+
end
141149
end

0 commit comments

Comments
 (0)