From b3a69c6797eaf3fa3872b183dfac00a5f3843572 Mon Sep 17 00:00:00 2001 From: MayaTheShy Date: Wed, 25 Mar 2026 21:53:47 -0400 Subject: [PATCH] feat: implement resilient task wrapper for parallel tasks to enhance stability --- inventoryManager.lua | 99 ++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 32 deletions(-) diff --git a/inventoryManager.lua b/inventoryManager.lua index 7b76854..24903b9 100644 --- a/inventoryManager.lua +++ b/inventoryManager.lua @@ -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