If stale records are found, abort, wait, retry

qa/10.0.0
Rick Carlino 2020-05-17 14:45:12 -05:00
parent 7431ecf800
commit 8309412f49
3 changed files with 25 additions and 37 deletions

View File

@ -1 +1 @@
10.0.0-rc40 10.0.0-rc41

View File

@ -16,39 +16,24 @@ defmodule FarmbotCore.Asset.Private do
@doc "Lists `module` objects that still need to be POSTed to the API." @doc "Lists `module` objects that still need to be POSTed to the API."
def list_local(module) do def list_local(module) do
list = Repo.all(from(data in module, where: is_nil(data.id))) 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)
end end
@doc "Lists `module` objects that have a `local_meta` object" @doc "Lists `module` objects that have a `local_meta` object"
def list_dirty(module) do def list_dirty(module) do
table = table(module) table = table(module)
q = from(lm in LocalMeta, where: lm.table == ^table, select: lm.asset_local_id) 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))) 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))
end end
@doc "Mark a document as `dirty` by creating a `local_meta` object" @doc "Mark a document as `dirty` by creating a `local_meta` object"
def mark_dirty!(asset, params \\ %{}) do def mark_dirty!(asset, params \\ %{}) do
table = table(asset) 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 ## NOTE(Connor): 19/11/13
# the try/catch here seems unneeded here, but because of how sqlite/ecto works, it is 100% needed. # the try/catch here seems unneeded here, but because of how sqlite/ecto works, it is 100% needed.

View File

@ -42,27 +42,30 @@ defmodule FarmbotExt.API.DirtyWorker do
@impl GenServer @impl GenServer
def handle_info(:do_work, %{module: module} = state) do def handle_info(:do_work, %{module: module} = state) do
(Private.list_dirty(module) ++ Private.list_local(module)) Process.sleep(1000)
|> Enum.map(fn item -> list = Enum.uniq((Private.list_dirty(module) ++ Private.list_local(module)))
stale = Enum.find(list, fn item ->
if (item.id) do if (item.id) do
Process.sleep(300) if item == Repo.get_by(module, id: item.id) do
next_item = Repo.get_by(module, id: item.id) false
if module == FarmbotCore.Asset.Point do else
old_y = item.y IO.inspect(item, label: "=== STALE RECORD DETECTED!")
new_y = next_item.y true
msg = "Y value after DB refresh: #{old_y} => #{new_y}"
FarmbotCore.Logger.info(2, msg)
end end
next_item
else else
item false
end end
end) end)
|> Enum.uniq()
|> Enum.map(fn dirty -> work(dirty, module) end)
Process.send_after(self(), :do_work, @timeout) if stale do
{:noreply, state} 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 end
def work(dirty, module) do def work(dirty, module) do