From 8309412f49ee10d35bb46229e640b9c17b164b34 Mon Sep 17 00:00:00 2001 From: Rick Carlino Date: Sun, 17 May 2020 14:45:12 -0500 Subject: [PATCH] If stale records are found, abort, wait, retry --- VERSION | 2 +- .../lib/farmbot_core/asset/private.ex | 27 ++++----------- .../lib/farmbot_ext/api/dirty_worker.ex | 33 ++++++++++--------- 3 files changed, 25 insertions(+), 37 deletions(-) diff --git a/VERSION b/VERSION index 6d4a02bb..0b8f2046 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -10.0.0-rc40 +10.0.0-rc41 diff --git a/farmbot_core/lib/farmbot_core/asset/private.ex b/farmbot_core/lib/farmbot_core/asset/private.ex index ef3232c8..1ec76785 100644 --- a/farmbot_core/lib/farmbot_core/asset/private.ex +++ b/farmbot_core/lib/farmbot_core/asset/private.ex @@ -16,39 +16,24 @@ defmodule FarmbotCore.Asset.Private do @doc "Lists `module` objects that still need to be POSTed to the API." def list_local(module) do - list = Repo.all(from(data in module, where: is_nil(data.id))) - Enum.map(list, fn item -> - if module == FarmbotCore.Asset.Point do - msg = "list_local: Point#{item.id}.y = #{item.y || "nil"}" - FarmbotCore.Logger.info(3, msg) - end - item - end) + Repo.all(from(data in module, where: is_nil(data.id))) end @doc "Lists `module` objects that have a `local_meta` object" def list_dirty(module) do table = table(module) q = from(lm in LocalMeta, where: lm.table == ^table, select: lm.asset_local_id) - list = Repo.all(from(data in module, join: lm in subquery(q))) - Enum.map(list, fn item -> - if module == FarmbotCore.Asset.Point do - msg = "list_dirty: Point#{item.id}.y = #{item.y || "nil"}" - FarmbotCore.Logger.info(3, msg) - end - item - end) - end - - def maybe_get_local_meta(asset, table) do - Repo.one(from(lm in LocalMeta, where: lm.asset_local_id == ^asset.local_id and lm.table == ^table)) + Repo.all(from(data in module, join: lm in subquery(q))) end @doc "Mark a document as `dirty` by creating a `local_meta` object" def mark_dirty!(asset, params \\ %{}) do table = table(asset) - local_meta = maybe_get_local_meta(asset, table) || Ecto.build_assoc(asset, :local_meta) + local_meta = + Repo.one( + from(lm in LocalMeta, where: lm.asset_local_id == ^asset.local_id and lm.table == ^table) + ) || Ecto.build_assoc(asset, :local_meta) ## NOTE(Connor): 19/11/13 # the try/catch here seems unneeded here, but because of how sqlite/ecto works, it is 100% needed. diff --git a/farmbot_ext/lib/farmbot_ext/api/dirty_worker.ex b/farmbot_ext/lib/farmbot_ext/api/dirty_worker.ex index b5203c55..af55208e 100644 --- a/farmbot_ext/lib/farmbot_ext/api/dirty_worker.ex +++ b/farmbot_ext/lib/farmbot_ext/api/dirty_worker.ex @@ -42,27 +42,30 @@ defmodule FarmbotExt.API.DirtyWorker do @impl GenServer def handle_info(:do_work, %{module: module} = state) do - (Private.list_dirty(module) ++ Private.list_local(module)) - |> Enum.map(fn item -> + Process.sleep(1000) + list = Enum.uniq((Private.list_dirty(module) ++ Private.list_local(module))) + + stale = Enum.find(list, fn item -> if (item.id) do - Process.sleep(300) - next_item = Repo.get_by(module, id: item.id) - if module == FarmbotCore.Asset.Point do - old_y = item.y - new_y = next_item.y - msg = "Y value after DB refresh: #{old_y} => #{new_y}" - FarmbotCore.Logger.info(2, msg) + if item == Repo.get_by(module, id: item.id) do + false + else + IO.inspect(item, label: "=== STALE RECORD DETECTED!") + true end - next_item else - item + false end end) - |> Enum.uniq() - |> Enum.map(fn dirty -> work(dirty, module) end) - Process.send_after(self(), :do_work, @timeout) - {:noreply, state} + if stale do + Process.send_after(self(), :do_work, @timeout) + {:noreply, state} + else + Enum.map(list, fn dirty -> work(dirty, module) end) + Process.send_after(self(), :do_work, @timeout) + {:noreply, state} + end end def work(dirty, module) do