Restart Vehicles supervisor after potential eid change

This commit is contained in:
Adrian Kumpf
2019-09-29 13:33:47 +02:00
parent 535edcc036
commit 0fe5dfac45
5 changed files with 57 additions and 4 deletions
+12 -2
View File
@@ -32,6 +32,11 @@ defmodule TeslaMate.Vehicles do
)
end
def kill do
Logger.warn("Restarting #{__MODULE__} supervisor")
__MODULE__ |> Process.whereis() |> Process.exit(:kill)
end
def restart do
with :ok <- Supervisor.stop(@name, :normal),
:ok <- block_until_started(250) do
@@ -61,8 +66,13 @@ defmodule TeslaMate.Vehicles do
end
defp fallback_vehicles do
Log.list_cars()
|> Enum.map(&%TeslaApi.Vehicle{id: &1.eid, vin: &1.vin, vehicle_id: &1.vid})
vehicles =
Log.list_cars()
|> Enum.map(&%TeslaApi.Vehicle{id: &1.eid, vin: &1.vin, vehicle_id: &1.vid})
Logger.warn("Using fallback vehicles:\n\n#{inspect(vehicles, pretty: true)}")
vehicles
end
defp create_or_update!(%TeslaApi.Vehicle{} = vehicle) do
+23 -2
View File
@@ -4,7 +4,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
require Logger
alias __MODULE__.Summary
alias TeslaMate.{Api, Log, Settings, Convert}
alias TeslaMate.{Vehicles, Api, Log, Settings, Convert}
alias TeslaMate.Vehicles.Identification
alias TeslaApi.Vehicle.State.{Climate, VehicleState, Drive, Charge}
@@ -61,6 +61,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
log: Keyword.get(opts, :deps_log, Log),
api: Keyword.get(opts, :deps_api, Api),
settings: Keyword.get(opts, :deps_settings, Settings),
vehicles: Keyword.get(opts, :deps_vehicles, Vehicles),
pubsub: Keyword.get(opts, :deps_pubsub, Phoenix.PubSub)
}
@@ -81,6 +82,14 @@ defmodule TeslaMate.Vehicles.Vehicle do
:ok = call(deps.settings, :subscribe_to_changes)
fuse_name = fuse_name(:vehicle_not_found, data)
fuse_opts = {{:standard, 8, :timer.minutes(10)}, {:reset, :timer.minutes(5)}}
case :fuse.install(fuse_name, fuse_opts) do
:reset -> Logger.info("Reset fuse: #{inspect(fuse_name)}")
:ok -> :ok
end
{:ok, :start, data, {:next_event, :internal, :fetch}}
end
@@ -227,7 +236,15 @@ defmodule TeslaMate.Vehicles.Vehicle do
{:error, :vehicle_not_found} ->
Logger.error("Error / :vehicle_not_found", car_id: data.car.id)
{:keep_state_and_data, schedule_fetch(60)}
fuse_name = fuse_name(:vehicle_not_found, data)
case :fuse.ask(fuse_name, :sync) do
:blown -> true = call(data.deps.vehicles, :kill)
:ok -> :ok = :fuse.melt(fuse_name)
end
{:keep_state_and_data, schedule_fetch(30)}
{:error, reason} ->
Logger.warn("Error / #{inspect(reason)}", car_id: data.car.id)
@@ -801,6 +818,10 @@ defmodule TeslaMate.Vehicles.Vehicle do
defp determince_interval(n) when not is_nil(n) and n > 0, do: round(725 / n) |> min(30)
defp determince_interval(_), do: 15
defp fuse_name(:vehicle_not_found, %Data{car: car}) do
:"#{__MODULE__}_#{car.id}_not_found"
end
defp notify_subscribers do
{:next_event, :internal, :notify_subscribers}
end
+6
View File
@@ -10,6 +10,7 @@ defmodule VehiclesMock do
GenServer.start_link(__MODULE__, opts, name: Keyword.fetch!(opts, :name))
end
def kill(name), do: GenServer.call(name, :kill)
def restart(name), do: GenServer.call(name, :restart)
def subscribe(name, car_id), do: GenServer.call(name, {:subscribe, car_id})
@@ -27,6 +28,11 @@ defmodule VehiclesMock do
{:reply, :ok, state}
end
def handle_call(:kill, _from, %State{pid: pid} = state) do
send(pid, {VehiclesMock, :kill})
{:reply, true, state}
end
def handle_call(:restart, _from, %State{pid: pid} = state) do
send(pid, {VehiclesMock, :restart})
{:reply, :ok, state}
+3
View File
@@ -17,11 +17,13 @@ defmodule TeslaMate.VehicleCase do
log_name = :"log_#{name}"
api_name = :"api_#{name}"
settings_name = :"settings_#{name}"
vehicles_name = :"vehicles_#{name}"
pubsub_name = :"pubsub_#{name}"
{:ok, _pid} = start_supervised({LogMock, name: log_name, pid: self()})
{:ok, _pid} = start_supervised({ApiMock, name: api_name, events: events, pid: self()})
{:ok, _pid} = start_supervised({SettingsMock, name: settings_name, pid: self()})
{:ok, _pid} = start_supervised({VehiclesMock, name: vehicles_name, pid: self()})
{:ok, _pid} = start_supervised({PubSubMock, name: pubsub_name, pid: self()})
opts =
@@ -52,6 +54,7 @@ defmodule TeslaMate.VehicleCase do
deps_log: {LogMock, log_name},
deps_api: {ApiMock, api_name},
deps_settings: {SettingsMock, settings_name},
deps_vehicles: {VehiclesMock, vehicles_name},
deps_pubsub: {PubSubMock, pubsub_name}
)}
)
+13
View File
@@ -211,4 +211,17 @@ defmodule TeslaMate.Vehicles.VehicleTest do
refute_receive _
end
end
describe "error handling" do
@tag :capture_log
test "restarts if the eid changed", %{test: name} do
events = [
{:error, :vehicle_not_found}
]
:ok = start_vehicle(name, events)
assert_receive {VehiclesMock, :kill}, 2500
end
end
end