Part of #2195.
Problem
updateApiObjectsNoChild calls updateApiMarkedBoards (src/components/Board/Board.actions.js:1036), which in turn calls updateApiObjectsNoChild recursively when it finds shouldCreateBoard flags (:1086). Termination relies on the assumption that each recursion clears at least one flag, so the set of pending boards monotonically shrinks.
That assumption is informal:
- No explicit depth bound — a malformed graph (cyclic
loadBoard references) could in principle keep marking boards.
- No telemetry to detect runaway cascades.
- The doc notes this in §14 with "Assumes finite board hierarchy depth."
In practice, the data model probably prevents cycles, so this is the lowest-priority item in the epic. But it's worth bounding defensively because the cost of a runaway loop is high (many API calls, possible stack overflow on deeply nested trees).
Proposed direction
Acceptance criteria
- A pathological input does not produce unbounded recursion.
- Depth/iteration count is observable in logs.
Part of #2195.
Problem
updateApiObjectsNoChildcallsupdateApiMarkedBoards(src/components/Board/Board.actions.js:1036), which in turn callsupdateApiObjectsNoChildrecursively when it findsshouldCreateBoardflags (:1086). Termination relies on the assumption that each recursion clears at least one flag, so the set of pending boards monotonically shrinks.That assumption is informal:
loadBoardreferences) could in principle keep marking boards.In practice, the data model probably prevents cycles, so this is the lowest-priority item in the epic. But it's worth bounding defensively because the cost of a runaway loop is high (many API calls, possible stack overflow on deeply nested trees).
Proposed direction
shouldCreateBoardandmarkToUpdateboards into a queue, drain iteratively. Combined with Sync: upsertApiCommunicator failures leave server-side communicator desynced silently #2197 (flags reflected in syncMeta) this becomes a normal Pass 1 push.Acceptance criteria