concurrent method
Manages concurrent download tasks.
Ensures that no more than 3 concurrent downloads are active for the same URL. If the number of concurrent downloads is less than 3, creates and adds new tasks.
Implementation
Future<void> concurrent(
DownloadTask task,
Map<String, String> headers,
int contentLength,
) async {
DownloadTask newTask = task;
int activeSize = VideoProxy.downloadManager.allTasks
.where((e) => e.url == newTask.url)
.length;
while (activeSize < 2) {
final nextStartRange = newTask.startRange + Config.segmentSize;
// Bail when the total length is unknown (head failed) or the next segment
// would start past EOF. Without the `contentLength <= 0` guard a failed
// head leaves no upper bound, so an all-cached tail spins this loop
// forever (activeSize never grows, nextStartRange never terminates).
if (contentLength <= 0 || nextStartRange >= contentLength) return;
// Clamp the last warmed segment to the real file boundary. Some servers
// reject over-wide byte ranges, which can leave a "preloaded" tail
// segment missing.
newTask = DownloadTask(
uri: newTask.uri,
startRange: nextStartRange,
endRange: _segmentEndRange(nextStartRange, contentLength),
headers: headers,
);
bool isExit = VideoProxy.downloadManager.allTasks
.where((e) => e.matchUrl == newTask.matchUrl)
.isNotEmpty;
Uint8List? dataMemory = await LruCacheSingleton().memoryGet(
newTask.matchUrl,
);
if (dataMemory != null) isExit = true;
newTask.cacheDir = await FileExt.createCachePath(newTask.uri.generateMd5);
File file = File(newTask.savePath);
if (file.existsSync()) isExit = true;
if (isExit) continue;
logD("Asynchronous download start: ${newTask.toString()}");
await VideoProxy.downloadManager.executeTask(newTask);
activeSize = VideoProxy.downloadManager.allTasks
.where((e) => e.url == newTask.url)
.length;
}
}