public async Task Run(CancellationToken token, ILog log) { log.Debug("Started"); // TODO: async token retrieval var vkToken = tokenMagic.GetTokenFromScratch(log); await vkApi.AuthorizeAsync(new ApiAuthParams() { AccessToken = vkToken.Token }); var modes = settings.GetWorkingModes(); var idTasks = settings.Targets .Select(async x => { var id = await vkApiUtils.ResolveId(x); return(name: x, id: id); }); var allIds = await Task.WhenAll(idTasks); var identifiers = allIds .Distinct() .ToImmutableList(); log.Debug($"Processing {JsonConvert.SerializeObject(modes)} for {string.Join(", ", identifiers.Select(x => $"[{x.name} {x.id}]"))}"); filesystemTools.LoadCache(log); var downloaderTask = downloader.Process(token, log); try { foreach (var identifier in identifiers) { var name = await vkApiUtils.GetName(identifier.id); var workDir = filesystemTools.CreateSubdir(filesystemTools.RootDir, name, CreateMode.OverwriteExisting); log.Info($"id [{identifier.id}], name [{name}], path [{workDir.FullName}]"); foreach (var mode in modes) { await ProcessTarget(identifier.id, workDir, mode, token, log); } } queueProvider.Pending.CompleteAdding(); var downloadErrors = await downloaderTask; foreach (var downloadError in downloadErrors) { log.Warn($"Failed {downloadError.DesiredName}", downloadError.Errors.LastOrDefault()); } } catch (TaskCanceledException) { queueProvider.Pending.CompleteAdding(); log.Warn($"Abandoned {queueProvider.Pending.GetConsumingEnumerable().Count()} pending downloads"); } finally { filesystemTools.SaveCache(log); } }