Skip to content

Commit 63ba922

Browse files
committed
[Launcher] feat: support add cancellation support for incremental updater
1 parent b4c1358 commit 63ba922

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

Launcher/lib/features/download_manager/services/download_orchestrator.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ class DownloadOrchestrator with ChangeNotifier {
320320
final updater = IncrementalUpdater();
321321
final result = await updater.update(
322322
downloadUrl: downloadUrl,
323+
controller: controller,
323324
onPhaseChanged: (phase) {
324325
if (phase != .downloadingMissingMods) {
325326
controller.updateProgress(1);

Launcher/lib/features/download_manager/services/incremental_updater.dart

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:io';
22
import 'dart:math';
33

4+
import 'package:background_downloader/background_downloader.dart';
45
import 'package:collection/collection.dart';
56
import 'package:flutter_rust_bridge/flutter_rust_bridge.dart';
67
import 'package:kyber_collection/kyber_collection.dart';
@@ -40,11 +41,15 @@ class IncrementalUpdater {
4041

4142
DownloaderHandle? d;
4243
try {
44+
_logger.fine('Checking incremental update eligibility for $downloadUrl');
45+
4346
d = await downloaderCreate(
4447
id: 'check-${DateTime.now().millisecondsSinceEpoch}',
4548
zipUrl: downloadUrl,
4649
outputDir: tmpDir.path,
4750
);
51+
52+
_logger.fine('Fetching mod collection entries for eligibility check');
4853
entries = await downloaderListEntries(d: d);
4954

5055
final collectionEntry = entries.firstWhereOrNull(
@@ -55,6 +60,7 @@ class IncrementalUpdater {
5560
return false;
5661
}
5762

63+
_logger.fine('Downloading collection manifest for eligibility check');
5864
await downloaderDownloadEntryByName(
5965
d: d,
6066
entryName: collectionEntry.name,
@@ -115,6 +121,7 @@ class IncrementalUpdater {
115121
void Function(UpdatePhase phase)? onPhaseChanged,
116122
void Function(int current, int total)? onProgress,
117123
void Function(int bytesDownloaded, int totalBytes)? onDownloadProgress,
124+
CallbackTaskController? controller,
118125
}) async {
119126
final uri = Uri.parse(downloadUrl);
120127

@@ -131,6 +138,7 @@ class IncrementalUpdater {
131138
String? newDir;
132139

133140
try {
141+
controller?.throwIfCancelled();
134142
onPhaseChanged?.call(.fetchingEntries);
135143

136144
onProgress?.call(1, 1);
@@ -161,6 +169,7 @@ class IncrementalUpdater {
161169
return false;
162170
}
163171

172+
controller?.throwIfCancelled();
164173
onPhaseChanged?.call(.parsingCollection);
165174

166175
await downloaderDownloadEntryByName(
@@ -179,6 +188,7 @@ class IncrementalUpdater {
179188
return false;
180189
}
181190

191+
controller?.throwIfCancelled();
182192
onPhaseChanged?.call(.comparingMods);
183193

184194
final installedMods = sl.get<ModService>().mods;
@@ -215,6 +225,7 @@ class IncrementalUpdater {
215225
)
216226
.fold<int>(0, (sum, e) => sum + e.compressedSize);
217227

228+
controller?.throwIfCancelled();
218229
onPhaseChanged?.call(.copyingExistingMods);
219230

220231
final random = String.fromCharCodes(
@@ -231,6 +242,7 @@ class IncrementalUpdater {
231242
_logger.info('Creating collection in $newDir');
232243
await Directory(newDir).create(recursive: true);
233244

245+
controller?.throwIfCancelled();
234246
onPhaseChanged?.call(.downloadingMissingMods);
235247

236248
d = await downloaderCreate(
@@ -248,6 +260,7 @@ class IncrementalUpdater {
248260

249261
try {
250262
for (var i = 0; i < missing.length; i++) {
263+
controller?.throwIfCancelled();
251264
final mod = missing[i];
252265
final entryInfo = entries.firstWhereOrNull(
253266
(e) => e.name == mod.$1,
@@ -257,6 +270,7 @@ class IncrementalUpdater {
257270
);
258271
final streamSink = RustStreamSink<int>();
259272

273+
// TODO: use frb cancel token to allow cancelling mid-download
260274
final future = downloaderDownloadEntryByName(
261275
d: d,
262276
entryName: mod.$1,
@@ -286,6 +300,7 @@ class IncrementalUpdater {
286300
_logger.info('All missing mods downloaded, copying existing mods');
287301

288302
for (var i = 0; i < installed.length; i++) {
303+
controller?.throwIfCancelled();
289304
final mod = installed[i];
290305
onProgress?.call(i + 1, installed.length);
291306

@@ -314,6 +329,20 @@ class IncrementalUpdater {
314329
} catch (_) {}
315330

316331
return true;
332+
} on CancelledException {
333+
_logger.info('Incremental update cancelled');
334+
335+
if (newDir != null) {
336+
try {
337+
await Directory(newDir).delete(recursive: true);
338+
} catch (_) {
339+
_logger.warning(
340+
'Failed to clean up partial output directory: $newDir',
341+
);
342+
}
343+
}
344+
345+
rethrow;
317346
} catch (e, s) {
318347
_logger.severe('Incremental update failed', e, s);
319348

0 commit comments

Comments
 (0)