feat: implement resilient task wrapper for parallel tasks to enhance stability
This commit is contained in:
@@ -350,13 +350,35 @@ local function main()
|
||||
end
|
||||
print("")
|
||||
|
||||
-----------------------------------------------
|
||||
-- Resilient task wrapper: if a task crashes, it
|
||||
-- restarts after a brief delay instead of killing
|
||||
-- all other parallel tasks.
|
||||
-----------------------------------------------
|
||||
local function resilient(name, fn)
|
||||
return function()
|
||||
while true do
|
||||
local ok, err = pcall(fn)
|
||||
if not ok then
|
||||
log.error("TASK", "%s crashed: %s", name, tostring(err))
|
||||
sleep(5)
|
||||
log.info("TASK", "%s restarting...", name)
|
||||
else
|
||||
-- Task returned normally (shouldn't happen)
|
||||
log.warn("TASK", "%s exited unexpectedly, restarting...", name)
|
||||
sleep(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------
|
||||
-- Parallel tasks
|
||||
-----------------------------------------------
|
||||
|
||||
parallel.waitForAny(
|
||||
-- Task 1: Background inventory scanner
|
||||
function()
|
||||
resilient("Scanner", function()
|
||||
if cacheLoaded then
|
||||
pcall(ops.refreshCache)
|
||||
pcall(ops.checkAlerts)
|
||||
@@ -373,18 +395,18 @@ local function main()
|
||||
state.needsRedraw = true
|
||||
state.smelterNeedsRedraw = true
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 2: Barrel auto-sort
|
||||
function()
|
||||
resilient("Barrel-sort", function()
|
||||
while true do
|
||||
pcall(ops.sortBarrel)
|
||||
sleep(cfg.POLL_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 3: Auto-smelt
|
||||
function()
|
||||
resilient("Auto-smelt", function()
|
||||
while true do
|
||||
local ok, didWork = pcall(ops.autoSmelt)
|
||||
if ok and didWork then
|
||||
@@ -398,10 +420,10 @@ local function main()
|
||||
state.smelterNeedsRedraw = true
|
||||
sleep(cfg.SMELT_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 4: Defrag (consolidate partial stacks)
|
||||
function()
|
||||
resilient("Defrag", function()
|
||||
sleep(10)
|
||||
while true do
|
||||
activity.defragging = true
|
||||
@@ -411,10 +433,10 @@ local function main()
|
||||
state.needsRedraw = true
|
||||
sleep(cfg.DEFRAG_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 5: Auto-compost
|
||||
function()
|
||||
resilient("Auto-compost", function()
|
||||
while true do
|
||||
activity.composting = true
|
||||
state.needsRedraw = true
|
||||
@@ -424,10 +446,10 @@ local function main()
|
||||
pcall(ops.checkAlerts)
|
||||
sleep(cfg.COMPOST_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 5b: Auto-discard excess stock
|
||||
function()
|
||||
resilient("Auto-discard", function()
|
||||
if #cfg.TRASH_DROPPERS == 0 then
|
||||
while true do sleep(3600) end
|
||||
end
|
||||
@@ -441,10 +463,10 @@ local function main()
|
||||
state.needsRedraw = true
|
||||
sleep(cfg.DISCARD_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 5c: Auto-craft excess items into target products
|
||||
function()
|
||||
resilient("Auto-craft", function()
|
||||
sleep(12) -- let initial scan + discard settle first
|
||||
log.info("AUTOCRAFT", "Auto-craft active (%d explicit rule(s), smart=%s)",
|
||||
#cfg.AUTO_CRAFT_RULES, tostring(cfg.AUTO_CRAFT_FROM_EXCESS))
|
||||
@@ -458,10 +480,23 @@ local function main()
|
||||
end
|
||||
sleep(cfg.AUTO_CRAFT_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 5d: Collection hopper emptying (egg spawner, etc.)
|
||||
resilient("Hopper-collect", function()
|
||||
if #cfg.COLLECTION_HOPPERS == 0 then
|
||||
while true do sleep(3600) end
|
||||
end
|
||||
sleep(3)
|
||||
log.info("COLLECT", "Hopper collection active for %d hopper(s)", #cfg.COLLECTION_HOPPERS)
|
||||
while true do
|
||||
pcall(ops.collectHoppers)
|
||||
sleep(cfg.COLLECTION_INTERVAL)
|
||||
end
|
||||
end),
|
||||
|
||||
-- Task 6: Low-stock alert checker
|
||||
function()
|
||||
resilient("Alert-checker", function()
|
||||
sleep(5)
|
||||
pcall(ops.checkAlerts)
|
||||
state.needsRedraw = true
|
||||
@@ -470,10 +505,10 @@ local function main()
|
||||
pcall(ops.checkAlerts)
|
||||
state.needsRedraw = true
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 7: Main dashboard redraw (event-driven, polls 0.1s)
|
||||
function()
|
||||
resilient("Dashboard", function()
|
||||
state.needsRedraw = true
|
||||
while true do
|
||||
if state.needsRedraw then
|
||||
@@ -493,10 +528,10 @@ local function main()
|
||||
end
|
||||
sleep(0.1)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 8: Smelter dashboard redraw
|
||||
function()
|
||||
resilient("Smelter-dashboard", function()
|
||||
state.smelterNeedsRedraw = true
|
||||
while true do
|
||||
if state.smelterNeedsRedraw then
|
||||
@@ -506,10 +541,10 @@ local function main()
|
||||
end
|
||||
sleep(0.1)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 9: Touch event listener (both monitors)
|
||||
function()
|
||||
resilient("Touch-listener", function()
|
||||
while true do
|
||||
local event, side, x, y = os.pullEvent("monitor_touch")
|
||||
if display.smelterMonName and side == display.smelterMonName then
|
||||
@@ -520,20 +555,20 @@ local function main()
|
||||
display.handleTouch(x, y)
|
||||
end
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 10: Network state broadcast (skips if nothing changed)
|
||||
function()
|
||||
resilient("Broadcast", function()
|
||||
while true do
|
||||
if state.stateVersion ~= state.lastBroadcastVersion then
|
||||
pcall(broadcastState)
|
||||
end
|
||||
sleep(cfg.BROADCAST_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 11: Peripheral detach handler
|
||||
function()
|
||||
resilient("Detach-handler", function()
|
||||
while true do
|
||||
local event, name = os.pullEvent("peripheral_detach")
|
||||
if name then
|
||||
@@ -546,10 +581,10 @@ local function main()
|
||||
end
|
||||
end
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 11b: Peripheral attach handler (auto-detect crafting turtle)
|
||||
function()
|
||||
resilient("Attach-handler", function()
|
||||
while true do
|
||||
local event, name = os.pullEvent("peripheral_attach")
|
||||
if name and name:match("^turtle_") and not ctx.craftTurtleName then
|
||||
@@ -558,10 +593,10 @@ local function main()
|
||||
pcall(broadcastState)
|
||||
end
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 12: Supply chest (builder / manifest-based stocking)
|
||||
function()
|
||||
resilient("Supply-chest", function()
|
||||
if cfg.SUPPLY_CHEST == "" or #cfg.SUPPLY_MANIFEST == 0 then
|
||||
while true do sleep(3600) end
|
||||
end
|
||||
@@ -570,10 +605,10 @@ local function main()
|
||||
pcall(ops.supplyChest)
|
||||
sleep(cfg.SUPPLY_INTERVAL)
|
||||
end
|
||||
end,
|
||||
end),
|
||||
|
||||
-- Task 13: Network order/command listener
|
||||
function()
|
||||
resilient("Network-listener", function()
|
||||
if not ctx.networkModem then
|
||||
while true do sleep(3600) end
|
||||
end
|
||||
@@ -832,7 +867,7 @@ local function main()
|
||||
end -- idempotency else
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user