recursivelyLoadBlocksFromService function
Future<List<Block> >
recursivelyLoadBlocksFromService(
- BlocksService blocksService,
- String blockId, {
- int? maxDepth,
- int concurrency = 4,
- BlockChildrenCache? cache,
Variant that accepts a BlocksService directly (useful for testing).
Implementation
Future<List<Block>> recursivelyLoadBlocksFromService(
BlocksService blocksService,
String blockId, {
int? maxDepth,
int concurrency = 4,
BlockChildrenCache? cache,
}) async {
final childrenCache = cache ?? BlockChildrenCache();
// Use BFS across depth levels to better control concurrency per level.
final all = <Block>[];
final processedParents = <String>{};
// Queue of (parentId, depth)
var currentLevel = <_QueueItem>[_QueueItem(parentId: blockId, depth: 0)];
while (currentLevel.isNotEmpty) {
// If maxDepth is set and the current level exceeds it, stop.
final levelDepth = currentLevel.first.depth;
if (maxDepth != null && levelDepth > maxDepth) {
break;
}
// Fetch children for all parents in this level with bounded concurrency.
final nextLevel = <_QueueItem>[];
for (var i = 0; i < currentLevel.length; i += concurrency) {
final batch = currentLevel.sublist(
i,
(i + concurrency > currentLevel.length)
? currentLevel.length
: i + concurrency,
);
final futures = batch.map((item) async {
// Avoid fetching same parent's children multiple times.
if (processedParents.contains(item.parentId)) {
return <Block>[];
}
processedParents.add(item.parentId);
final children = await _getAllChildren(
blocksService,
item.parentId,
childrenCache,
);
// Collect children for this level
all.addAll(children);
// If we can go deeper, schedule children that have further descendants.
final nextDepth = item.depth + 1;
if (maxDepth == null || nextDepth <= maxDepth) {
for (final child in children) {
if (child.hasChildren) {
nextLevel.add(_QueueItem(parentId: child.id, depth: nextDepth));
}
}
}
return children;
}).toList();
// Wait for this batch to complete before starting the next batch.
await Future.wait(futures);
}
currentLevel = nextLevel;
}
return all;
}