Force bootupsequence worker to check farmware before executing

feature/sequence-on-boot
Connor Rigby 2019-11-18 13:24:06 -08:00
parent 3f06afdccb
commit bd51878b41
No known key found for this signature in database
GPG Key ID: 29A88B24B70456E0
6 changed files with 68 additions and 14 deletions

View File

@ -22,7 +22,8 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FarmwareInstallation do
def init(fwi) do
:ok = DepTracker.register_asset(fwi, :init)
{:ok, %{fwi: fwi, backoff: 0}, 0}
send self(), :timeout
{:ok, %{fwi: fwi, backoff: 0}}
end
def handle_cast(:update, state) do
@ -49,8 +50,9 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FarmwareInstallation do
error ->
backoff = state.backoff + @back_off_time_ms
timeout = @error_retry_time_ms + backoff
Process.send_after(self(), :timeout, timeout)
error_log(fwi, "Failed to download Farmware manifest. Trying again in #{timeout}ms #{inspect(error)}")
{:noreply, %{state | backoff: backoff}, timeout}
{:noreply, %{state | backoff: backoff}}
end
end
@ -78,16 +80,17 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FarmwareInstallation do
updated =
FWI.changeset(fwi, %{manifest: nil, updated_at: fwi.updated_at})
|> Repo.update!()
{:noreply, %{state | fwi: updated}, 0}
send self(), :timeout
{:noreply, %{state | fwi: updated}}
error ->
:ok = DepTracker.register_asset(fwi, :complete)
BotState.report_farmware_installed(fwi.manifest.package, Manifest.view(fwi.manifest))
backoff = state.backoff + @back_off_time_ms
timeout = @error_retry_time_ms + backoff
Process.send_after(self(), :timeout, timeout)
error_log(fwi, "failed to check for updates. Trying again in #{timeout}ms #{inspect(error)}")
{:noreply, %{state | backoff: backoff}, timeout}
{:noreply, %{state | backoff: backoff}}
end
end
@ -125,8 +128,9 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FarmwareInstallation do
er ->
backoff = state.backoff + @back_off_time_ms
timeout = @error_retry_time_ms + backoff
Process.send_after(self(), :timeout, timeout)
error_log(updated, "update failed. Trying again in #{timeout}ms #{inspect(er)}")
{:noreply, %{state | fwi: updated, backoff: backoff}, timeout}
{:noreply, %{state | fwi: updated, backoff: backoff}}
end
end
end
@ -253,7 +257,16 @@ defimpl FarmbotCore.AssetWorker, for: FarmbotCore.Asset.FarmwareInstallation do
end
defp httpc_options, do: [body_format: :binary]
defp httpc_headers, do: [{'user-agent', 'farmbot-os'}]
case System.get_env("GITHUB_TOKEN") do
nil ->
defp httpc_headers, do: [{'user-agent', 'farmbot-farmware-installer'}]
token when is_binary(token) ->
@token token
require Logger; Logger.info "using github token: #{@token}"
defp httpc_headers, do: [{'user-agent', 'farmbot-farmware-installer'}, {'Authorization', 'token #{@token}'}]
end
def install_dir(%FWI{} = fwi) do
install_dir(fwi.manifest)

View File

@ -51,7 +51,7 @@ defmodule FarmbotCore.MixProject do
# Run "mix help compile.app" to learn about applications.
def application do
[
extra_applications: [:logger],
extra_applications: [:logger, :inets],
mod: {FarmbotCore, []}
]
end

View File

@ -92,6 +92,10 @@ config :farmbot_core, FarmbotCore.Asset.Repo,
config :farmbot_telemetry, file: to_charlist(Path.join(data_path, 'farmbot-telemetry.dets'))
config :farmbot_core, FarmbotCore.AssetWorker.FarmbotCore.Asset.FarmwareInstallation,
error_retry_time_ms: 30_000,
install_dir: Path.join(data_path, "farmware")
config :farmbot, FarmbotOS.Platform.Supervisor,
platform_children: [
FarmbotOS.Platform.Target.NervesHubClient,

View File

@ -92,6 +92,10 @@ config :farmbot_core, FarmbotCore.Asset.Repo,
config :farmbot_telemetry, file: to_charlist(Path.join(data_path, 'farmbot-telemetry.dets'))
config :farmbot_core, FarmbotCore.AssetWorker.FarmbotCore.Asset.FarmwareInstallation,
error_retry_time_ms: 30_000,
install_dir: Path.join(data_path, "farmware")
config :farmbot, FarmbotOS.Platform.Supervisor,
platform_children: [
FarmbotOS.Platform.Target.NervesHubClient,

View File

@ -16,6 +16,9 @@ defmodule FarmbotOS.BootupSequenceWorker do
end
def init(_args) do
# all_required_farmwares =
# FarmbotCore.Asset.Repo.all(FarmbotCore.Asset.FirstPartyFarmware) ++
# FarmbotCore.Asset.Repo.all(FarmbotCore.Asset.FarmwareInstallation)
%{
informational_settings: %{
sync_status: sync_status,
@ -30,6 +33,7 @@ defmodule FarmbotOS.BootupSequenceWorker do
firmware_idle: fw_idle,
firmware_version: fw_version,
firmware_configured: fw_configured,
farmwares_loaded: false,
sequence_id: nil,
sequence_started_at: nil,
sequence_completed_at: nil,
@ -41,10 +45,13 @@ defmodule FarmbotOS.BootupSequenceWorker do
end
def handle_info(:checkup, state) do
Logger.debug("| bootup sequence | checkup ok")
{:noreply, maybe_start_sequence(state)}
end
def handle_info(:start_sequence, %{sequence_id: id} = state) do
Logger.debug("| bootup sequence | start_sequence begin")
case Asset.get_sequence(id) do
nil ->
FarmbotCore.Logger.error(1, """
@ -55,10 +62,12 @@ defmodule FarmbotOS.BootupSequenceWorker do
{:noreply, state}
%{name: name} ->
Logger.debug("bootup sequence start: #{inspect(state)}")
Logger.debug("| bootup sequence | start_sequence ok #{inspect(state)}")
FarmbotCore.Logger.busy(2, "Starting bootup sequence: #{name}")
ref = make_ref()
FarmbotCeleryScript.execute(execute_ast(id), ref)
ast = execute_ast(id)
worker_pid = self()
_pid = spawn(FarmbotCeleryScript.StepRunner, :step, [worker_pid, ref, ast])
{:noreply, %{state | sequence_started_at: DateTime.utc_now(), sequence_ref: ref}}
end
end
@ -77,6 +86,7 @@ defmodule FarmbotOS.BootupSequenceWorker do
{BotState, %{changes: %{informational_settings: %{changes: %{idle: idle}}}}},
state
) do
Logger.debug("| bootup sequence | idle ok")
state = maybe_start_sequence(%{state | firmware_idle: idle})
{:noreply, state}
end
@ -97,8 +107,10 @@ defmodule FarmbotOS.BootupSequenceWorker do
) do
# this should really be fixed upstream not to dispatch if version is none.
if state.firmware_version == "none" do
Logger.debug("| bootup sequence | firmware_configured err")
{:noreply, state}
else
Logger.debug("| bootup sequence | firmware_configured ok")
state = maybe_start_sequence(%{state | firmware_configured: fw_configured})
{:noreply, state}
end
@ -108,12 +120,14 @@ defmodule FarmbotOS.BootupSequenceWorker do
{BotState, %{changes: %{informational_settings: %{changes: %{sync_status: "synced"}}}}},
state
) do
Logger.debug("| bootup sequence | synced ok")
state = maybe_start_sequence(%{state | synced: true})
{:noreply, state}
end
def handle_info({BotState, _}, state) do
state = maybe_start_sequence(%{state | synced: true})
# def handle_info({BotState, _}, state) do
def handle_info(_, state) do
state = maybe_start_sequence(state)
{:noreply, state}
end
@ -124,13 +138,32 @@ defmodule FarmbotOS.BootupSequenceWorker do
defp maybe_start_sequence(%{sequence_started_at: %DateTime{}} = state), do: state
defp maybe_start_sequence(%{sequence_completed_at: %DateTime{}} = state), do: state
defp maybe_start_sequence(%{farmwares_loaded: false} = state) do
farmwares = FarmbotCore.DepTracker.get_asset(FarmbotCore.Asset.FarmwareInstallation)
loaded =
Enum.all?(farmwares, fn
{{FarmbotCore.Asset.FarmwareInstallation, _id}, :complete} -> true
_ -> false
end)
loaded && Logger.debug("| bootup sequence | farmware_loaded ok")
if loaded,
do: maybe_start_sequence(%{state | farmwares_loaded: true}),
else: state
end
defp maybe_start_sequence(state) do
case Asset.fbos_config() do
%{boot_sequence_id: nil} ->
Logger.debug("| bootup sequnce | assets_loaded noop")
state
%{boot_sequence_id: id} ->
dependency_assets_loaded?() && send(self(), :start_sequence)
loaded? = dependency_assets_loaded?()
Logger.debug("| bootup sequnce | assets_loaded ok")
loaded? && send(self(), :start_sequence)
%{state | sequence_id: id}
end
end

View File

@ -67,7 +67,7 @@ defmodule FarmbotOS.MixProject do
def application do
[
mod: {FarmbotOS, []},
extra_applications: [:logger, :runtime_tools, :eex]
extra_applications: [:logger, :runtime_tools, :eex, :inets]
]
end